From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- share/extensions/.darglint | 3 + share/extensions/.gitmodules | 9 + share/extensions/.pre-commit-config.yaml | 5 + share/extensions/.pylintrc | 374 + share/extensions/CONTRIBUTING.md | 4 + share/extensions/LICENSE.txt | 340 + share/extensions/MANIFEST.in | 2 + share/extensions/Poly3DObjects/cube.obj | 19 + share/extensions/Poly3DObjects/cuboct.obj | 30 + share/extensions/Poly3DObjects/dodec.obj | 36 + share/extensions/Poly3DObjects/great_dodec.obj | 96 + .../Poly3DObjects/great_rhombicosidodec.obj | 185 + .../Poly3DObjects/great_rhombicuboct.obj | 77 + .../extensions/Poly3DObjects/great_stel_dodec.obj | 96 + share/extensions/Poly3DObjects/icos.obj | 36 + share/extensions/Poly3DObjects/icosidodec.obj | 65 + .../Poly3DObjects/jessens_orthog_icos.obj | 35 + share/extensions/Poly3DObjects/methane.obj | 13 + share/extensions/Poly3DObjects/oct.obj | 17 + share/extensions/Poly3DObjects/rh_axes.obj | 12 + share/extensions/Poly3DObjects/rhomb_dodec.obj | 29 + share/extensions/Poly3DObjects/rhomb_triacont.obj | 65 + .../Poly3DObjects/small_rhombicosidodec.obj | 127 + .../Poly3DObjects/small_rhombicuboct.obj | 54 + .../extensions/Poly3DObjects/small_triam_icos.obj | 95 + share/extensions/Poly3DObjects/snub_cube.obj | 65 + share/extensions/Poly3DObjects/snub_dodec.obj | 156 + share/extensions/Poly3DObjects/szilassi.obj | 24 + share/extensions/Poly3DObjects/tet.obj | 12 + share/extensions/Poly3DObjects/trunc_cube.obj | 42 + share/extensions/Poly3DObjects/trunc_dodec.obj | 96 + share/extensions/Poly3DObjects/trunc_icos.obj | 96 + share/extensions/Poly3DObjects/trunc_oct.obj | 42 + share/extensions/Poly3DObjects/trunc_tet.obj | 24 + share/extensions/README.md | 67 + share/extensions/TESTING.md | 104 + share/extensions/addnodes.inx | 28 + share/extensions/addnodes.py | 87 + share/extensions/aisvg.inx | 14 + share/extensions/aisvg.xslt | 36 + share/extensions/alphabet_soup/2.svg | 11 + share/extensions/alphabet_soup/3.svg | 11 + share/extensions/alphabet_soup/6.svg | 10 + share/extensions/alphabet_soup/7.svg | 10 + share/extensions/alphabet_soup/Cblob.svg | 10 + share/extensions/alphabet_soup/Chook.svg | 10 + share/extensions/alphabet_soup/Ctail.svg | 10 + share/extensions/alphabet_soup/Delta.svg | 10 + share/extensions/alphabet_soup/Eb.svg | 10 + share/extensions/alphabet_soup/Eserif.svg | 16 + share/extensions/alphabet_soup/Et.svg | 10 + share/extensions/alphabet_soup/G.svg | 10 + share/extensions/alphabet_soup/IBSerif.svg | 10 + share/extensions/alphabet_soup/ITSerif.svg | 10 + share/extensions/alphabet_soup/Lb.svg | 10 + share/extensions/alphabet_soup/Lt.svg | 10 + share/extensions/alphabet_soup/Ocross.svg | 10 + share/extensions/alphabet_soup/Oterm.svg | 10 + share/extensions/alphabet_soup/P.svg | 10 + share/extensions/alphabet_soup/Q.svg | 10 + share/extensions/alphabet_soup/Rblock.svg | 10 + share/extensions/alphabet_soup/Tb.svg | 16 + share/extensions/alphabet_soup/Tt.svg | 16 + share/extensions/alphabet_soup/U.svg | 10 + share/extensions/alphabet_soup/Vser.svg | 10 + share/extensions/alphabet_soup/Xh.svg | 10 + share/extensions/alphabet_soup/Xne.svg | 10 + share/extensions/alphabet_soup/Xnw.svg | 10 + share/extensions/alphabet_soup/Xvb.svg | 10 + share/extensions/alphabet_soup/Xvt.svg | 10 + share/extensions/alphabet_soup/a.svg | 10 + share/extensions/alphabet_soup/abase.svg | 10 + share/extensions/alphabet_soup/acap.svg | 10 + share/extensions/alphabet_soup/b.svg | 10 + share/extensions/alphabet_soup/bar.svg | 10 + share/extensions/alphabet_soup/bar2.svg | 10 + share/extensions/alphabet_soup/barcap.svg | 10 + share/extensions/alphabet_soup/c.svg | 10 + share/extensions/alphabet_soup/cross.svg | 10 + share/extensions/alphabet_soup/cserif.svg | 10 + share/extensions/alphabet_soup/e.svg | 10 + share/extensions/alphabet_soup/epsilon.svg | 8 + share/extensions/alphabet_soup/f.svg | 16 + share/extensions/alphabet_soup/gamma.svg | 10 + share/extensions/alphabet_soup/h.svg | 10 + share/extensions/alphabet_soup/h2.svg | 10 + share/extensions/alphabet_soup/hcap.svg | 10 + share/extensions/alphabet_soup/idot.svg | 10 + share/extensions/alphabet_soup/j.svg | 10 + share/extensions/alphabet_soup/k.svg | 10 + share/extensions/alphabet_soup/l.svg | 10 + share/extensions/alphabet_soup/lserif.svg | 10 + share/extensions/alphabet_soup/m.svg | 10 + share/extensions/alphabet_soup/mcap.svg | 10 + share/extensions/alphabet_soup/n.svg | 10 + share/extensions/alphabet_soup/o.svg | 10 + share/extensions/alphabet_soup/ocap.svg | 10 + share/extensions/alphabet_soup/question.svg | 10 + share/extensions/alphabet_soup/r.svg | 10 + share/extensions/alphabet_soup/rcap.svg | 10 + share/extensions/alphabet_soup/s.svg | 10 + share/extensions/alphabet_soup/serif.svg | 10 + share/extensions/alphabet_soup/t.svg | 16 + share/extensions/alphabet_soup/tserif.svg | 10 + share/extensions/alphabet_soup/v.svg | 10 + share/extensions/alphabet_soup/vcap.svg | 10 + share/extensions/alphabet_soup/vserl.svg | 10 + share/extensions/alphabet_soup/vserr.svg | 10 + share/extensions/alphabet_soup/x.svg | 10 + share/extensions/alphabet_soup/y.svg | 10 + share/extensions/alphabet_soup/yogh.svg | 10 + share/extensions/alphabet_soup/z.svg | 10 + share/extensions/barcode/Base.py | 171 + share/extensions/barcode/BaseEan.py | 204 + share/extensions/barcode/Code128.py | 246 + share/extensions/barcode/Code25i.py | 71 + share/extensions/barcode/Code39.py | 98 + share/extensions/barcode/Code39Ext.py | 97 + share/extensions/barcode/Code93.py | 187 + share/extensions/barcode/Ean13.py | 44 + share/extensions/barcode/Ean2.py | 40 + share/extensions/barcode/Ean5.py | 50 + share/extensions/barcode/Ean8.py | 38 + share/extensions/barcode/Rm4scc.py | 139 + share/extensions/barcode/Upca.py | 40 + share/extensions/barcode/Upce.py | 112 + share/extensions/barcode/__init__.py | 77 + share/extensions/color_blackandwhite.inx | 15 + share/extensions/color_blackandwhite.py | 24 + share/extensions/color_brighter.inx | 14 + share/extensions/color_brighter.py | 27 + share/extensions/color_custom.inx | 36 + share/extensions/color_custom.py | 74 + share/extensions/color_darker.inx | 14 + share/extensions/color_darker.py | 22 + share/extensions/color_desaturate.inx | 14 + share/extensions/color_desaturate.py | 19 + share/extensions/color_grayscale.inx | 14 + share/extensions/color_grayscale.py | 18 + share/extensions/color_hsl_adjust.inx | 32 + share/extensions/color_hsl_adjust.py | 44 + share/extensions/color_lesshue.inx | 14 + share/extensions/color_lesshue.py | 16 + share/extensions/color_lesslight.inx | 14 + share/extensions/color_lesslight.py | 16 + share/extensions/color_lesssaturation.inx | 14 + share/extensions/color_lesssaturation.py | 16 + share/extensions/color_list.inx | 14 + share/extensions/color_list.py | 26 + share/extensions/color_morehue.inx | 14 + share/extensions/color_morehue.py | 16 + share/extensions/color_morelight.inx | 14 + share/extensions/color_morelight.py | 16 + share/extensions/color_moresaturation.inx | 14 + share/extensions/color_moresaturation.py | 16 + share/extensions/color_negative.inx | 14 + share/extensions/color_negative.py | 18 + share/extensions/color_randomize.inx | 25 + share/extensions/color_randomize.py | 89 + share/extensions/color_removeblue.inx | 14 + share/extensions/color_removeblue.py | 15 + share/extensions/color_removegreen.inx | 14 + share/extensions/color_removegreen.py | 15 + share/extensions/color_removered.inx | 14 + share/extensions/color_removered.py | 15 + share/extensions/color_replace.inx | 24 + share/extensions/color_replace.py | 46 + share/extensions/color_rgbbarrel.inx | 14 + share/extensions/color_rgbbarrel.py | 19 + share/extensions/colors.xml | 151 + share/extensions/convert2dashes.inx | 14 + share/extensions/convert2dashes.py | 105 + share/extensions/dhw_input.inx | 14 + share/extensions/dhw_input.py | 121 + share/extensions/dimension.inx | 20 + share/extensions/dimension.py | 159 + share/extensions/doc_ai_convert.inx | 39 + share/extensions/doc_ai_convert.py | 79 + share/extensions/docinfo.inx | 14 + share/extensions/docinfo.py | 85 + share/extensions/docs/Makefile | 20 + share/extensions/docs/_templates/versions.html | 27 + share/extensions/docs/authors/index.rst | 29 + share/extensions/docs/authors/interpreters.rst | 114 + share/extensions/docs/authors/inx-overview.rst | 238 + share/extensions/docs/authors/inx-widgets.rst | 536 + ...Lighter_extension_in_Inkscape_1.1.2_and_1.2.png | Bin 0 -> 36157 bytes .../docs/authors/samples/unit_camera.svg | 730 + share/extensions/docs/authors/samples/units1.svg | 4 + share/extensions/docs/authors/samples/units2.svg | 9 + share/extensions/docs/authors/submit.rst | 97 + share/extensions/docs/authors/unit-tests.rst | 67 + share/extensions/docs/authors/units.rst | 316 + share/extensions/docs/authors/update1.0.rst | 301 + share/extensions/docs/authors/update1.2.rst | 229 + share/extensions/docs/authors/widgets/bool.png | Bin 0 -> 1137 bytes share/extensions/docs/authors/widgets/color.png | Bin 0 -> 10374 bytes share/extensions/docs/authors/widgets/float.png | Bin 0 -> 3267 bytes share/extensions/docs/authors/widgets/image.png | Bin 0 -> 17053 bytes share/extensions/docs/authors/widgets/integer.png | Bin 0 -> 3178 bytes share/extensions/docs/authors/widgets/label.png | Bin 0 -> 4230 bytes share/extensions/docs/authors/widgets/notebook.png | Bin 0 -> 1475 bytes .../docs/authors/widgets/optiongroup.png | Bin 0 -> 5632 bytes share/extensions/docs/authors/widgets/path.png | Bin 0 -> 1585 bytes .../extensions/docs/authors/widgets/separator.png | Bin 0 -> 2014 bytes share/extensions/docs/authors/widgets/spacer.png | Bin 0 -> 5345 bytes share/extensions/docs/authors/widgets/string.png | Bin 0 -> 4254 bytes share/extensions/docs/conf.py | 93 + share/extensions/docs/dev/getting-started.rst | 148 + share/extensions/docs/dev/index.rst | 8 + share/extensions/docs/favicon.svg | 159 + share/extensions/docs/index.rst | 35 + share/extensions/docs/make.bat | 35 + share/extensions/docs/source/index.rst | 21 + share/extensions/docs/tutorial/index.rst | 49 + .../docs/tutorial/my-first-effect-extension.rst | 130 + .../docs/tutorial/my-first-import-extension.rst | 305 + .../docs/tutorial/my-first-text-extension.rst | 223 + .../tutorial/resources/Call_Extension_Failure.png | Bin 0 -> 54314 bytes .../Inkscape_Recognizes_Our_Extension.gif | Bin 0 -> 457560 bytes .../docs/tutorial/resources/Smiles_Format.gif | Bin 0 -> 1015850 bytes .../resources/Text_Ext_Moment_of_truth.gif | Bin 0 -> 941111 bytes .../tutorial/resources/call_extension_success.gif | Bin 0 -> 489312 bytes .../docs/tutorial/resources/make_red_extension.zip | Bin 0 -> 1201 bytes .../tutorial/resources/stroke-parity-widget.png | Bin 0 -> 20362 bytes .../tutorial/resources/stroke_parity_extension.zip | Bin 0 -> 1628 bytes .../docs/tutorial/resources/template_effect.zip | Bin 0 -> 2582 bytes .../docs/tutorial/resources/vanillin.smi | 1 + .../docs/tutorial/simple-path-extension.rst | 162 + share/extensions/doxygen-main.dox | 4 + share/extensions/dpi90to96.inx | 17 + share/extensions/dpi96to90.inx | 17 + share/extensions/dpiswitcher.py | 384 + share/extensions/draw_from_triangle.inx | 75 + share/extensions/draw_from_triangle.py | 493 + share/extensions/dxf12_outlines.inx | 17 + share/extensions/dxf12_outlines.py | 156 + share/extensions/dxf14_footer.txt | 62 + share/extensions/dxf14_header.txt | 202 + share/extensions/dxf14_style.txt | 358 + share/extensions/dxf_input.inx | 48 + share/extensions/dxf_input.py | 1636 + share/extensions/dxf_input_text_scale_factor.svg | 832 + share/extensions/dxf_outlines.inx | 57 + share/extensions/dxf_outlines.py | 443 + share/extensions/edge3d.inx | 21 + share/extensions/edge3d.py | 144 + share/extensions/eps_input.inx | 24 + share/extensions/export_gimp_palette.inx | 14 + share/extensions/export_gimp_palette.py | 77 + share/extensions/extrude.inx | 48 + share/extensions/extrude.py | 150 + share/extensions/fig_input.inx | 15 + share/extensions/fig_input.py | 38 + share/extensions/flatten.inx | 15 + share/extensions/flatten.py | 49 + share/extensions/foldablebox.inx | 26 + share/extensions/foldablebox.py | 259 + share/extensions/fontfix.conf | 55 + share/extensions/fractalize.inx | 16 + share/extensions/fractalize.py | 105 + share/extensions/frame.inx | 48 + share/extensions/frame.py | 183 + share/extensions/funcplot.inx | 69 + share/extensions/funcplot.py | 300 + share/extensions/generate_voronoi.inx | 26 + share/extensions/generate_voronoi.py | 203 + share/extensions/genpofiles.sh | 7 + share/extensions/gimp_xcf.inx | 31 + share/extensions/gimp_xcf.py | 204 + share/extensions/grid_cartesian.inx | 73 + share/extensions/grid_cartesian.py | 297 + share/extensions/grid_isometric.inx | 25 + share/extensions/grid_isometric.py | 547 + share/extensions/grid_polar.inx | 43 + share/extensions/grid_polar.py | 270 + share/extensions/guides_creator.inx | 96 + share/extensions/guides_creator.py | 325 + share/extensions/guillotine.inx | 23 + share/extensions/guillotine.py | 199 + share/extensions/handles.inx | 14 + share/extensions/handles.py | 75 + share/extensions/hershey.inx | 130 + share/extensions/hershey.py | 2040 + share/extensions/hpgl_decoder.py | 109 + share/extensions/hpgl_encoder.py | 526 + share/extensions/hpgl_input.inx | 20 + share/extensions/hpgl_input.py | 76 + share/extensions/hpgl_output.inx | 46 + share/extensions/hpgl_output.py | 91 + share/extensions/image_attributes.inx | 76 + share/extensions/image_attributes.py | 153 + share/extensions/image_embed.inx | 15 + share/extensions/image_embed.py | 147 + share/extensions/image_embed_selected.inx | 13 + share/extensions/image_extract.inx | 19 + share/extensions/image_extract.py | 213 + share/extensions/image_extract_selected.inx | 19 + share/extensions/ink2canvas.inx | 14 + share/extensions/ink2canvas.py | 99 + share/extensions/ink2canvas_lib/__init__.py | 0 share/extensions/ink2canvas_lib/canvas.py | 200 + share/extensions/ink2canvas_lib/svg.py | 326 + share/extensions/inkex/__init__.py | 32 + share/extensions/inkex/base.py | 537 + share/extensions/inkex/bezier.py | 488 + share/extensions/inkex/colors.py | 535 + share/extensions/inkex/command.py | 309 + share/extensions/inkex/css.py | 61 + .../extensions/inkex/deprecated-simple/README.rst | 4 + .../extensions/inkex/deprecated-simple/bezmisc.py | 46 + .../inkex/deprecated-simple/cspsubdiv.py | 25 + .../inkex/deprecated-simple/cubicsuperpath.py | 52 + share/extensions/inkex/deprecated-simple/ffgeom.py | 92 + .../inkex/deprecated-simple/run_command.py | 79 + .../inkex/deprecated-simple/simplepath.py | 68 + .../inkex/deprecated-simple/simplestyle.py | 55 + .../inkex/deprecated-simple/simpletransform.py | 122 + share/extensions/inkex/deprecated/__init__.py | 3 + .../inkex/deprecated/deprecatedeffect.py | 313 + share/extensions/inkex/deprecated/main.py | 178 + share/extensions/inkex/deprecated/meta.py | 109 + share/extensions/inkex/elements/__init__.py | 55 + share/extensions/inkex/elements/_base.py | 755 + share/extensions/inkex/elements/_filters.py | 367 + share/extensions/inkex/elements/_groups.py | 126 + share/extensions/inkex/elements/_image.py | 29 + share/extensions/inkex/elements/_meta.py | 293 + share/extensions/inkex/elements/_parser.py | 118 + share/extensions/inkex/elements/_polygons.py | 507 + share/extensions/inkex/elements/_selected.py | 237 + share/extensions/inkex/elements/_svg.py | 371 + share/extensions/inkex/elements/_text.py | 202 + share/extensions/inkex/elements/_use.py | 81 + share/extensions/inkex/elements/_utils.py | 144 + share/extensions/inkex/extensions.py | 475 + share/extensions/inkex/gui/README.md | 15 + share/extensions/inkex/gui/__init__.py | 50 + share/extensions/inkex/gui/app.py | 176 + share/extensions/inkex/gui/asyncme.py | 330 + share/extensions/inkex/gui/listview.py | 562 + share/extensions/inkex/gui/pixmap.py | 346 + share/extensions/inkex/gui/tester.py | 78 + share/extensions/inkex/gui/window.py | 201 + share/extensions/inkex/interfaces/IElement.py | 39 + share/extensions/inkex/interfaces/__init__.py | 0 share/extensions/inkex/inx.py | 244 + share/extensions/inkex/localization.py | 117 + share/extensions/inkex/paths.py | 2018 + share/extensions/inkex/ports.py | 105 + share/extensions/inkex/properties.py | 800 + share/extensions/inkex/styles.py | 621 + share/extensions/inkex/tester/__init__.py | 437 + share/extensions/inkex/tester/decorators.py | 9 + share/extensions/inkex/tester/filters.py | 180 + share/extensions/inkex/tester/inx.py | 128 + share/extensions/inkex/tester/mock.py | 455 + share/extensions/inkex/tester/svg.py | 55 + share/extensions/inkex/tester/word.py | 42 + share/extensions/inkex/tester/xmldiff.py | 124 + share/extensions/inkex/transforms.py | 1250 + share/extensions/inkex/turtle.py | 255 + share/extensions/inkex/tween.py | 847 + share/extensions/inkex/units.py | 150 + share/extensions/inkex/utils.py | 271 + share/extensions/inkscape.extension.rng | 554 + share/extensions/inkscape.extension.schema | 9 + share/extensions/inkscape_follow_link.inx | 12 + share/extensions/inkscape_follow_link.py | 33 + share/extensions/inkweb.js | 223 + share/extensions/inkwebeffect.py | 58 + share/extensions/interp.inx | 23 + share/extensions/interp.py | 142 + share/extensions/interp_att_g.inx | 57 + share/extensions/interp_att_g.py | 197 + share/extensions/jessyInk.js | 2727 ++ .../jessyInk_core_mouseHandler_noclick.js | 53 + .../jessyInk_core_mouseHandler_zoomControl.js | 434 + share/extensions/jessyink_autotexts.inx | 28 + share/extensions/jessyink_autotexts.py | 50 + share/extensions/jessyink_effects.inx | 40 + share/extensions/jessyink_effects.py | 69 + share/extensions/jessyink_export.inx | 29 + share/extensions/jessyink_export.py | 79 + share/extensions/jessyink_install.inx | 21 + share/extensions/jessyink_install.py | 110 + share/extensions/jessyink_key_bindings.inx | 70 + share/extensions/jessyink_key_bindings.py | 193 + share/extensions/jessyink_master_slide.inx | 24 + share/extensions/jessyink_master_slide.py | 62 + share/extensions/jessyink_mouse_handler.inx | 27 + share/extensions/jessyink_mouse_handler.py | 65 + share/extensions/jessyink_summary.inx | 20 + share/extensions/jessyink_summary.py | 172 + share/extensions/jessyink_transitions.inx | 39 + share/extensions/jessyink_transitions.py | 72 + share/extensions/jessyink_uninstall.inx | 29 + share/extensions/jessyink_uninstall.py | 69 + share/extensions/jessyink_video.inx | 20 + share/extensions/jessyink_video.py | 96 + share/extensions/jessyink_video.svg | 596 + share/extensions/jessyink_view.inx | 26 + share/extensions/jessyink_view.py | 77 + share/extensions/jitternodes.inx | 31 + share/extensions/jitternodes.py | 107 + share/extensions/layer2png.inx | 36 + share/extensions/layer2png.py | 200 + share/extensions/layers2svgfont.inx | 14 + share/extensions/layers2svgfont.py | 105 + share/extensions/layout_nup.inx | 75 + share/extensions/layout_nup.py | 317 + share/extensions/lindenmayer.inx | 51 + share/extensions/lindenmayer.py | 129 + share/extensions/lorem_ipsum.inx | 25 + share/extensions/lorem_ipsum.py | 316 + share/extensions/markers_strokepaint.inx | 39 + share/extensions/markers_strokepaint.py | 149 + share/extensions/measure.inx | 73 + share/extensions/measure.py | 286 + share/extensions/media_zip.inx | 19 + share/extensions/media_zip.py | 209 + share/extensions/merge_styles.inx | 19 + share/extensions/merge_styles.py | 70 + share/extensions/motion.inx | 18 + share/extensions/motion.py | 174 + share/extensions/new_glyph_layer.inx | 15 + share/extensions/new_glyph_layer.py | 55 + share/extensions/next_glyph_layer.inx | 14 + share/extensions/next_glyph_layer.py | 50 + share/extensions/nicechart.inx | 102 + share/extensions/nicechart.py | 654 + share/extensions/other/clipart/LICENSE.txt | 674 + share/extensions/other/clipart/MANIFEST.in | 9 + share/extensions/other/clipart/README.md | 12 + share/extensions/other/clipart/import_sources.py | 272 + .../extensions/other/clipart/import_web_image.inx | 12 + share/extensions/other/clipart/import_web_image.py | 395 + .../extensions/other/clipart/import_web_image.svg | 239 + share/extensions/other/clipart/import_web_image.ui | 934 + .../other/clipart/import_web_image_cli.py | 22 + share/extensions/other/clipart/licenses/asl.svg | 343 + share/extensions/other/clipart/licenses/bsd.svg | 343 + .../other/clipart/licenses/cc-by-nc-sa.svg | 346 + .../extensions/other/clipart/licenses/cc-by-nc.svg | 340 + .../extensions/other/clipart/licenses/cc-by-nd.svg | 340 + .../extensions/other/clipart/licenses/cc-by-sa.png | Bin 0 -> 2275 bytes .../extensions/other/clipart/licenses/cc-by-sa.svg | 340 + share/extensions/other/clipart/licenses/cc-by.svg | 334 + share/extensions/other/clipart/licenses/cc0.svg | 334 + share/extensions/other/clipart/licenses/gpl.svg | 347 + share/extensions/other/clipart/licenses/mit.svg | 308 + .../extensions/other/clipart/licenses/perm-by.svg | 93 + .../extensions/other/clipart/licenses/perm-nc.svg | 100 + .../extensions/other/clipart/licenses/perm-nd.svg | 92 + .../extensions/other/clipart/licenses/perm-ne.svg | 90 + .../other/clipart/licenses/perm-notice.svg | 82 + .../extensions/other/clipart/licenses/perm-pd.svg | 87 + .../extensions/other/clipart/licenses/perm-sa.svg | 84 + .../extensions/other/clipart/licenses/unknown.svg | 340 + share/extensions/other/clipart/pyproject.toml | 19 + share/extensions/other/clipart/sources/bioicons.py | 97 + .../extensions/other/clipart/sources/bioicons.svg | 145 + .../other/clipart/sources/inkscape-web.py | 74 + .../other/clipart/sources/inkscape-web.svg | 569 + share/extensions/other/clipart/sources/ocal.py | 97 + share/extensions/other/clipart/sources/ocal.svg | 132 + share/extensions/other/clipart/sources/reactome.py | 64 + .../extensions/other/clipart/sources/reactome.svg | 111 + .../extensions/other/clipart/sources/wikimedia.py | 76 + .../extensions/other/clipart/sources/wikimedia.svg | 92 + share/extensions/other/gcodetools/.darglint | 3 + share/extensions/other/gcodetools/.pylintrc | 374 + share/extensions/other/gcodetools/LICENSE.txt | 340 + share/extensions/other/gcodetools/MANIFEST.in | 2 + share/extensions/other/gcodetools/README.md | 45 + share/extensions/other/gcodetools/TESTING.md | 104 + share/extensions/other/gcodetools/gcodetools.py | 5930 +++ .../other/gcodetools/gcodetools_about.inx | 52 + .../other/gcodetools/gcodetools_area.inx | 133 + .../other/gcodetools/gcodetools_dxf_points.inx | 79 + .../other/gcodetools/gcodetools_engraving.inx | 91 + .../other/gcodetools/gcodetools_graffiti.inx | 120 + .../other/gcodetools/gcodetools_lathe.inx | 113 + .../gcodetools/gcodetools_orientation_points.inx | 57 + .../other/gcodetools/gcodetools_path_to_gcode.inx | 93 + .../gcodetools_prepare_path_for_plasma.inx | 59 + .../other/gcodetools/gcodetools_tools_library.inx | 62 + share/extensions/other/gcodetools/genpofiles.sh | 7 + share/extensions/other/gcodetools/setup.cfg | 2 + ...46547012e-17__--orientation-points-count__3.out | 41 + ...codetools__06eec9617e749f35cb949d850415f68d.out | 30 + ...codetools__2bf3b298fa730dafb8c6fd51921078f0.out | 40 + ...codetools__4a9fb751baf0533eadd4d394957c966d.out | 0 .../tests/data/svg/default-inkscape-SVG.svg | 37 + .../other/gcodetools/tests/data/svg/shapes.svg | 284 + .../other/gcodetools/tests/dev_requirements.txt | 11 + .../other/gcodetools/tests/test_gcodetools.py | 65 + .../other/gcodetools/tests/test_inkex_inx.py | 114 + share/extensions/other/gcodetools/tox.ini | 14 + share/extensions/other/inkman/MANIFEST.in | 6 + share/extensions/other/inkman/inkman/__init__.py | 5 + share/extensions/other/inkman/inkman/archive.py | 120 + share/extensions/other/inkman/inkman/backfoot.py | 84 + .../other/inkman/inkman/data/__init__.py | 0 share/extensions/other/inkman/inkman/data/gui.ui | 736 + share/extensions/other/inkman/inkman/data/info.ui | 338 + .../other/inkman/inkman/data/package.json | 20 + .../other/inkman/inkman/data/pixmaps/__init__.py | 0 .../other/inkman/inkman/data/pixmaps/core_icon.svg | 112 + .../other/inkman/inkman/data/pixmaps/default.svg | 75 + .../inkman/inkman/data/pixmaps/default_icon.svg | 71 + .../other/inkman/inkman/data/pixmaps/docs.png | Bin 0 -> 54648 bytes .../other/inkman/inkman/data/pixmaps/icon.svg | 79 + .../inkman/inkman/data/pixmaps/module_icon.svg | 82 + .../other/inkman/inkman/data/pixmaps/not-found.png | Bin 0 -> 42907 bytes .../inkman/inkman/data/pixmaps/orphan_icon.svg | 88 + .../other/inkman/inkman/data/pixmaps/star-lots.svg | 95 + .../other/inkman/inkman/data/pixmaps/star-none.svg | 95 + .../other/inkman/inkman/data/pixmaps/star-some.svg | 95 + share/extensions/other/inkman/inkman/factory.py | 199 + .../extensions/other/inkman/inkman/gui/__init__.py | 32 + share/extensions/other/inkman/inkman/gui/info.py | 105 + share/extensions/other/inkman/inkman/gui/main.py | 371 + share/extensions/other/inkman/inkman/package.py | 330 + share/extensions/other/inkman/inkman/remote.py | 153 + share/extensions/other/inkman/inkman/target.py | 375 + share/extensions/other/inkman/inkman/targets.py | 20 + share/extensions/other/inkman/inkman/utils.py | 166 + .../extensions/other/inkman/manage_extensions.inx | 12 + share/extensions/other/inkman/manage_extensions.py | 69 + share/extensions/other/inkman/pyproject.toml | 19 + share/extensions/output_scour.inx | 129 + share/extensions/output_scour.py | 99 + share/extensions/output_scour.svg | 5 + share/extensions/param_curves.inx | 61 + share/extensions/param_curves.py | 236 + share/extensions/path_envelope.inx | 14 + share/extensions/path_envelope.py | 159 + share/extensions/path_mesh_m2p.inx | 37 + share/extensions/path_mesh_m2p.py | 346 + share/extensions/path_mesh_p2m.inx | 32 + share/extensions/path_mesh_p2m.py | 92 + share/extensions/path_number_nodes.inx | 30 + share/extensions/path_number_nodes.py | 95 + share/extensions/path_to_absolute.inx | 14 + share/extensions/path_to_absolute.py | 38 + share/extensions/pathalongpath.inx | 42 + share/extensions/pathalongpath.py | 222 + share/extensions/pathmodifier.py | 226 + share/extensions/pathscatter.inx | 38 + share/extensions/pathscatter.py | 235 + share/extensions/pdflatex.inx | 33 + share/extensions/pdflatex.py | 139 + share/extensions/perfectboundcover.inx | 41 + share/extensions/perfectboundcover.py | 132 + share/extensions/perspective.inx | 14 + share/extensions/perspective.py | 171 + share/extensions/pixelsnap.inx | 24 + share/extensions/pixelsnap.py | 501 + share/extensions/plotter.inx | 104 + share/extensions/plotter.py | 162 + share/extensions/poetry.lock | 1229 + share/extensions/polyhedron_3d.inx | 97 + share/extensions/polyhedron_3d.py | 439 + share/extensions/prepare_file_save_as.inx | 14 + share/extensions/prepare_file_save_as.py | 51 + share/extensions/previous_glyph_layer.inx | 14 + share/extensions/previous_glyph_layer.py | 34 + share/extensions/print_win32_vector.inx | 15 + share/extensions/print_win32_vector.py | 250 + share/extensions/printing_marks.inx | 49 + share/extensions/printing_marks.py | 622 + share/extensions/ps_input.inx | 23 + share/extensions/ps_input.py | 104 + share/extensions/pyproject.toml | 51 + share/extensions/raster_output_jpg.inx | 40 + share/extensions/raster_output_jpg.py | 28 + share/extensions/raster_output_jpg.svg | 119 + share/extensions/raster_output_png.inx | 38 + share/extensions/raster_output_png.py | 62 + share/extensions/raster_output_tiff.inx | 37 + share/extensions/raster_output_tiff.py | 30 + share/extensions/raster_output_webp.inx | 38 + share/extensions/raster_output_webp.py | 27 + share/extensions/render_alphabetsoup.inx | 18 + share/extensions/render_alphabetsoup.py | 542 + share/extensions/render_alphabetsoup_config.py | 902 + share/extensions/render_barcode.inx | 32 + share/extensions/render_barcode.py | 54 + share/extensions/render_barcode_datamatrix.inx | 50 + share/extensions/render_barcode_datamatrix.py | 588 + share/extensions/render_barcode_qrcode.inx | 107 + share/extensions/render_barcode_qrcode.py | 1352 + share/extensions/render_gear_rack.inx | 19 + share/extensions/render_gear_rack.py | 88 + share/extensions/render_gears.inx | 26 + share/extensions/render_gears.py | 181 + share/extensions/replace_font.inx | 36 + share/extensions/replace_font.py | 248 + share/extensions/restack.inx | 63 + share/extensions/restack.py | 99 + share/extensions/rtree.inx | 17 + share/extensions/rtree.py | 67 + share/extensions/rubberstretch.inx | 16 + share/extensions/rubberstretch.py | 110 + share/extensions/scribus_export_pdf.inx | 41 + share/extensions/scribus_export_pdf.py | 199 + share/extensions/seamless_pattern.svg | 544 + share/extensions/setup_typography_canvas.inx | 19 + share/extensions/setup_typography_canvas.py | 81 + share/extensions/spirograph.inx | 23 + share/extensions/spirograph.py | 152 + share/extensions/straightseg.inx | 16 + share/extensions/straightseg.py | 83 + share/extensions/svg2fxg.inx | 14 + share/extensions/svg2fxg.xsl | 3008 ++ share/extensions/svg2xaml.inx | 15 + share/extensions/svg2xaml.xsl | 2987 ++ share/extensions/svg_fonts/EMSAllure.svg | 235 + share/extensions/svg_fonts/EMSElfin.svg | 236 + share/extensions/svg_fonts/EMSFelix.svg | 235 + share/extensions/svg_fonts/EMSNixish.svg | 235 + share/extensions/svg_fonts/EMSNixishItalic.svg | 235 + share/extensions/svg_fonts/EMSOsmotron.svg | 235 + share/extensions/svg_fonts/EMSReadability.svg | 235 + .../extensions/svg_fonts/EMSReadabilityItalic.svg | 235 + share/extensions/svg_fonts/EMSTech.svg | 236 + share/extensions/svg_fonts/HersheyGothEnglish.svg | 261 + share/extensions/svg_fonts/HersheySans1.svg | 260 + share/extensions/svg_fonts/HersheySansMed.svg | 260 + share/extensions/svg_fonts/HersheyScript1.svg | 261 + share/extensions/svg_fonts/HersheyScriptMed.svg | 261 + share/extensions/svg_fonts/HersheySerifBold.svg | 261 + .../svg_fonts/HersheySerifBoldItalic.svg | 262 + share/extensions/svg_fonts/HersheySerifMed.svg | 260 + .../extensions/svg_fonts/HersheySerifMedItalic.svg | 260 + share/extensions/svg_fonts/OFL.txt | 97 + share/extensions/svgcalendar.inx | 144 + share/extensions/svgcalendar.py | 548 + share/extensions/svgfont2layers.inx | 15 + share/extensions/svgfont2layers.py | 112 + share/extensions/synfig_fileformat.py | 257 + share/extensions/synfig_output.inx | 18 + share/extensions/synfig_output.py | 1485 + share/extensions/synfig_prepare.py | 323 + share/extensions/tar_layers.inx | 17 + share/extensions/tar_layers.py | 89 + share/extensions/template.py | 62 + share/extensions/template_business_card.inx | 30 + share/extensions/template_desktop.inx | 42 + share/extensions/template_dvd_cover.inx | 29 + share/extensions/template_dvd_cover.py | 67 + share/extensions/template_envelope.inx | 25 + share/extensions/template_generic.inx | 41 + share/extensions/template_icon.inx | 23 + share/extensions/template_page.inx | 43 + share/extensions/template_seamless_pattern.inx | 24 + share/extensions/template_seamless_pattern.py | 92 + share/extensions/template_video.inx | 35 + share/extensions/tests/README.md | 1 + share/extensions/tests/__init__.py | 1 + share/extensions/tests/add_pylint.py | 118 + share/extensions/tests/data/README.md | 10 + share/extensions/tests/data/batches/barcodes.dat | 513 + .../fig2dev/5d879c5bf2edd4bc478d8bef487538b9.msg | 29 + .../cmd/gimp/a8418e80d6e849cc2e91b1baecbfada4.msg | 2204 ++ .../cmd/gimp/ba387a2bf0dfa5d22b061bfbe6fae05b.msg | 2918 ++ .../gswin64c/488450070287cd66d418d312b70b4285.msg | 63 + .../gswin64c/67ad522b1b2203d1e9355c8bcb6bacfc.msg | 63 + .../inkscape/03dd4e9c9ee257c7ae161057ebe7c8a3.msg | 25 + .../inkscape/054966b8da855f76de0c1c5c2615c696.msg | 93 + .../inkscape/0ac64d7c051206284e72bf3e0800186d.msg | 1025 + .../inkscape/106011cd22941d59371660c2b4abf75c.msg | 25 + .../inkscape/12146d0ed761a6686175edea7c8df347.msg | 171 + .../inkscape/1b0252977bd9eafe0af2686834decd6e.msg | 28 + .../inkscape/1c734cd0171b9097039996e1bd63ed6f.msg | 569 + .../inkscape/1f50fa6d71e2543dd18dfc807fe56018.msg | 25 + .../inkscape/21e5197995b5aa619151b61ebee79f23.msg | 261 + .../inkscape/2911a62f9cfb6cf1e950992909bf7efb.msg | 25 + .../inkscape/2aee6b61724952541d5114e64953ae32.msg | 28 + .../inkscape/37d9cfceb38aade8eda7ad77e4ad0c29.msg | 25 + .../inkscape/4b7027944d0833efa65b5f203a16a5d0.msg | 375 + .../inkscape/51125b32a740b8441210140690d55f8e.msg | 13 + .../inkscape/586740f52b3a497fe4ba77501ad443f4.msg | 73 + .../inkscape/67e526c4c1e53207e5e46274e8cdfcc0.msg | 17 + .../inkscape/683466390d1961f2c66be46d75893e9c.msg | 64 + .../inkscape/6bb74fec5efd21cdad5bc4e0bb7b7b40.msg | 120 + .../inkscape/7b45b58536327cfdced28568323b9f2c.msg | 115 + .../inkscape/7c51bb494fcde6ed09463674eed1e75f.msg | 376 + .../inkscape/7e16d346b278485f0e308b7c8eda301d.msg | 25 + .../inkscape/7f8bea1476711ae5f57b9d30111ec50b.msg | 94 + .../inkscape/88e23ddddb7b44e469a8309d48b71594.msg | 25 + .../inkscape/8d81a6ce40b41366bc5784c8b8e3f3e3.msg | 28 + .../inkscape/9216316249e241e47bf118e187386687.msg | 28 + .../inkscape/925a03cfc32f34622997616ca335c846.msg | 234 + .../inkscape/96e4049adf5290ee08bfbcd580bd8dd1.msg | 19 + .../inkscape/994e3f169976a1af54f6590723d399ee.msg | 28 + .../inkscape/9f18b1246e864e6f3945f8cd64d6ca14.msg | 603 + .../inkscape/a274e3a1c2d893233fa49b8ad9850098.msg | 18 + .../inkscape/b493ad11b50db40a61c857109f083621.msg | 604 + .../inkscape/bf3e6cfcbb81940d4f7d667750681b0c.msg | 1038 + .../inkscape/c1bf37c2aa47000fc9941d96b415218c.msg | 28 + .../inkscape/d475a74656cd1f8ba68e095b0ec7c469.msg | 1025 + .../inkscape/da3b4e4db182a123e61e1317b2e4578b.msg | 25 + .../inkscape/ee1fdaa387bcb73ee6f7a2359fa9bd62.msg | 28 + .../inkscape/fbabf7cf387f29c12ae11a51af0a9926.msg | 28 + .../pdflatex/6cb19641894666183e4e3e0dbf0d0098.msg | 1361 + .../pdflatex/93c25fa37a5c8216644b4392a3d3654e.msg | 673 + .../pdflatex/acb704059fd20b4a9a5c69387a391c7d.msg | 1171 + .../pdflatex/b78a310017b7056b187bd023af227d1e.msg | 493 + .../pdflatex/fa0bf1f8c5a5eafc88832c60950b0a40.msg | 543 + .../ps2pdf/754c0d01b6fab11719df7fe755bd3be8.msg | 63 + .../ps2pdf/82b68f6250bfc65d80157a71522c62fb.msg | 63 + .../scribus/cbaa8e934937d1d6b0355b525b5351e5.msg | 261 + .../scribus/e1f8033066a1e79d574f64111d5b92af.msg | 13 + share/extensions/tests/data/io/CADTextHeight.dxf | 6566 ++++ share/extensions/tests/data/io/PAGE_001.DHW | Bin 0 -> 12320 bytes share/extensions/tests/data/io/PGLT_161.DHW | Bin 0 -> 456 bytes share/extensions/tests/data/io/PGLT_162.DHW | Bin 0 -> 976 bytes share/extensions/tests/data/io/PGLT_163.DHW | Bin 0 -> 1916 bytes share/extensions/tests/data/io/color.dxf | 3062 ++ .../tests/data/io/dxf_multiple_inserts.dxf | 3098 ++ share/extensions/tests/data/io/dxf_polylines.dxf | 2713 ++ share/extensions/tests/data/io/dxf_with_arc.dxf | 25184 ++++++++++++ share/extensions/tests/data/io/nicechart_01.csv | 13 + .../extensions/tests/data/io/no_block_section.dxf | 10690 +++++ share/extensions/tests/data/io/test.eps | 83 + share/extensions/tests/data/io/test.fig | 15 + share/extensions/tests/data/io/test.hpgl | 1 + share/extensions/tests/data/io/test.ps | 120 + share/extensions/tests/data/io/test2_r12.dxf | 33472 ++++++++++++++++ share/extensions/tests/data/io/test2_r13.dxf | 38502 +++++++++++++++++++ share/extensions/tests/data/io/test2_r14.dxf | 38018 ++++++++++++++++++ share/extensions/tests/data/io/test_extrude.dxf | 20478 ++++++++++ share/extensions/tests/data/io/test_r12.dxf | 5592 +++ share/extensions/tests/data/io/test_r14.dxf | 1398 + share/extensions/tests/data/refs/addnodes.out | 0 .../addnodes__--id__p1__--id__r3__--max__2__0.out | 41 + ...d__path1115__--method__bynum__--segments__3.out | 11 + ..._--id__layer_group_path__--id__root_rect_uu.out | 40 + ..._r2__--id__r3__--id__r4__--id__r5__--id__r6.out | 43 + .../data/refs/color_replace__--id__rect184.out | 17 + ...lor_replace__--id__rect184__--id__rect184-8.out | 14 + .../extensions/tests/data/refs/convert2dashes.out | 0 .../convert2dashes__--id__dashme2__dash__svg.out | 17 + ...dashes__--id__dashme2__dash_zerolength__svg.out | 15 + .../tests/data/refs/dhw_input__PAGE_001__DHW.out | 8 + .../tests/data/refs/dhw_input__PGLT_161__DHW.out | 8 + .../tests/data/refs/dhw_input__PGLT_162__DHW.out | 8 + .../tests/data/refs/dhw_input__PGLT_163__DHW.out | 8 + .../tests/data/refs/dimension__--id__circle1.out | 44 + ...isual__--xoffset__100__0__--yoffset__100__0.out | 41 + ...d__r3__--xoffset__100__0__--yoffset__100__0.out | 41 + share/extensions/tests/data/refs/dm2svg.out | 27 + .../refs/doc_ai_convert__doc_ai_conv_m_in__svg.out | 24 + .../doc_ai_convert__doc_ai_conv_mm_in__svg.out | 24 + .../data/refs/doc_ai_convert__shapes__svg.out | 41 + .../tests/data/refs/docinfo__guides__svg.out | 10 + .../docinfo__three_pages_and_two_grids__svg.out | 14 + share/extensions/tests/data/refs/dpiswitcher.out | 41 + .../data/refs/dpiswitcher__--id__p1__--id__r3.out | 41 + .../tests/data/refs/dpiswitcher__--switcher__0.out | 40 + .../tests/data/refs/dpiswitcher__--switcher__1.out | 40 + .../draw_from_triangle__--id__p1__--id__r3.out | 41 + .../refs/dxf12_outlines__clips_and_masks__svg.out | 932 + .../dxf12_outlines__dxf_nested_transforms__svg.out | 296 + .../dxf12_outlines__preserved-transforms__svg.out | 224 + .../refs/dxf12_outlines__scale_not_unity__svg.out | 272 + .../data/refs/dxf12_outlines__shapes__svg.out | 1424 + ...ut__--textscale__1__411__CADTextHeight__dxf.out | 2 + .../data/refs/dxf_input__CADTextHeight__dxf.out | 2 + .../tests/data/refs/dxf_input__color__dxf.out | 2 + .../refs/dxf_input__dxf_multiple_inserts__dxf.out | 2 + .../data/refs/dxf_input__dxf_polylines__dxf.out | 2 + .../data/refs/dxf_input__dxf_with_arc__dxf.out | 2 + .../data/refs/dxf_input__no_block_section__dxf.out | 2 + .../tests/data/refs/dxf_input__test2_r12__dxf.out | 2 + .../tests/data/refs/dxf_input__test2_r13__dxf.out | 1599 + .../tests/data/refs/dxf_input__test2_r14__dxf.out | 1587 + .../data/refs/dxf_input__test_extrude__dxf.out | 2 + .../tests/data/refs/dxf_input__test_r12__dxf.out | 2 + .../tests/data/refs/dxf_input__test_r14__dxf.out | 2 + share/extensions/tests/data/refs/dxf_outlines.out | 3416 ++ .../tests/data/refs/dxf_outlines__--POLY__true.out | 2884 ++ .../tests/data/refs/dxf_outlines__--ROBO__true.out | 3356 ++ .../data/refs/dxf_outlines__--id__p1__--id__r3.out | 3416 ++ .../tests/data/refs/edge3d__--id__p1__--id__r3.out | 44 + .../tests/data/refs/export_gimp_palette.out | 13 + .../export_gimp_palette__--id__p1__--id__r3.out | 6 + .../data/refs/extrude__--id__c1__--id__c2.out | 18 + .../extrude__--id__c1__--id__c2__-m__polygons.out | 18 + .../refs/extrude__--id__c1__--id__c2__-m__snug.out | 18 + .../data/refs/extrude__--id__p1__--id__p2.out | 41 + .../extrude__--id__p1__--id__p2__-m__lines.out | 18 + .../refs/extrude__--id__p1__--id__p2__-m__snug.out | 18 + .../extrude__--id__p3__--id__p4__-m__lines.out | 18 + .../extrude__--id__p3__--id__p4__-m__polygons.out | 18 + .../refs/extrude__--id__p3__--id__p4__-m__snug.out | 18 + .../data/refs/extrude__--id__r1__--id__r2.out | 18 + .../refs/extrude__--id__r1__--id__r2__-m__snug.out | 18 + .../extrude__--id__r1__--id__r2__-s__False.out | 18 + share/extensions/tests/data/refs/fig_input.out | 22 + share/extensions/tests/data/refs/flatten.out | 0 .../data/refs/flatten__--id__p1__--id__r3.out | 41 + ...proportion__0__5__--guide__true__--unit__cm.out | 2 + ...20__--height__20__--depth__2__2__--unit__cm.out | 2 + .../data/refs/fractalize__--id__p1__--id__p2.out | 41 + ..._--stroke_color____F00__--z_position__split.out | 41 + ..._--stroke_color____F00__--z_position__split.out | 41 + ..._--stroke_color____F00__--z_position__split.out | 41 + ...___AAA__--stroke_color____F00__--clip__True.out | 41 + .../frame__663c52a8114abe50f0559d9ccefab2e9.out | 41 + ...i__True__--ybottom__-1__0__--drawaxis__True.out | 40 + .../refs/generate_voronoi__--id__r3__--id__p1.out | 41 + share/extensions/tests/data/refs/gimp_xcf.out | Bin 0 -> 70038 bytes .../data/refs/gimp_xcf__-d__true__-r__true.out | Bin 0 -> 126005 bytes ...cartesian__154bd7ce1662209647ba2825e6d83cbc.out | 41 + ...cartesian__841ec156c192e3f468b6774927a90789.out | 41 + ...__0__--subdivs_th__1__--subsubdivs_th__0__3.out | 41 + ...polar__--a_subdivs_cent__1__--a_labels__deg.out | 41 + ...d__r3__--a_subdivs_cent__1__--a_labels__deg.out | 41 + .../extensions/tests/data/refs/guides_creator.out | 14 + ...l__True__--ur__True__--ll__True__--lr__True.out | 14 + ...l__True__--ur__True__--ll__True__--lr__True.out | 14 + ...e__--margins_preset__book_alternating_right.out | 14 + ...ns_preset__book_right__--vert__3__--horz__2.out | 35 + ...ue__--margins_preset__book_alternating_left.out | 14 + ...-vertical_guides__4__--horizontal_guides__5.out | 35 + ...t_from_edges__True__--guides_preset__golden.out | 35 + ...horizontal_guides__3__--pages__1____3-7__12.out | 14 + ...-vertical_guides__6__--horizontal_guides__8.out | 34 + ...s_creator__0cec5b2a62929d8e2c1469e6e5047e77.out | 40 + ...s_creator__19bbe6630a0a22a9d7a6a65b25eb1c9f.out | 40 + ...s_creator__251d15df598c899ffbdc546ced9e2faa.out | 40 + ...s_creator__3b35068c24255b2144616d98c2a077bd.out | 40 + ...s_creator__8f473fd113caab10b556f9cfe804e05e.out | 34 + ...s_creator__92c07724de24b2568187779e17d89f83.out | 40 + ...s_creator__ca9cfba4b80367070f0d70d13c501131.out | 40 + ...--ignore__true__--directory__TMP_DIR__img__.out | Bin 0 -> 133120 bytes ...image__f____oo__--directory__TMP_DIR__img__.out | Bin 0 -> 71680 bytes ...-image__output__--directory__TMP_DIR__img__.out | Bin 0 -> 30720 bytes .../data/refs/handles__--id__curve__--id__quad.out | 10 + share/extensions/tests/data/refs/hershey.out | 52 + .../tests/data/refs/hershey_encoding.out | 13 + .../tests/data/refs/hershey_fonttable.out | 13 + .../tests/data/refs/hershey_glyphtable.out | 13 + .../tests/data/refs/hershey_loadfont.out | 17 + .../tests/data/refs/hershey_partialselection.out | 22 + .../tests/data/refs/hershey_preservetext.out | 22 + share/extensions/tests/data/refs/hpgl_input.out | 2 + ...__20__--orientation__90__hpgl_multipen__svg.out | 1 + ...--speed__20__--orientation__90__shapes__svg.out | 1 + .../tests/data/refs/image_attributes.out | 18 + ...timizeSpeed__--tab____tab_image_rendering__.out | 18 + ...atio__xMinYMin__--tab____tab_aspect_ratio__.out | 18 + share/extensions/tests/data/refs/image_embed.out | 18 + ...embed__--id__image174__--selectedonly__True.out | 18 + ...-selectedonly__False__--filepath__TMP_DIR__.out | Bin 0 -> 128 bytes ...-id__embeded_image01__--filepath__TMP_DIR__.out | Bin 0 -> 128 bytes share/extensions/tests/data/refs/ink2canvas.out | 162 + .../tests/data/refs/ink2canvas__--id__alpha.out | 288 + .../tests/data/refs/ink2canvas__--id__path31.out | 49 + .../tests/data/refs/ink2canvas__--id__rect3898.out | 124 + .../tests/data/refs/inkex_extensions_color.out | 38 + .../inkex_extensions_color__--id__color_svg.out | 38 + .../data/refs/inkex_extensions_color__--id__r1.out | 38 + .../inkex_extensions_color__--id__r1__--id__r2.out | 38 + .../data/refs/inkex_extensions_color__--id__r2.out | 38 + .../data/refs/inkex_extensions_color__--id__r3.out | 38 + .../data/refs/inkex_extensions_color__--id__r4.out | 42 + .../tests/data/refs/inkscape_follow_link.out | 0 .../inkscape_follow_link__--id__p1__--id__r3.out | 0 .../interp__3ed855778ec06e18dc5f0d8329e9d085.out | 97 + .../interp__bf1a5fd7b7c87a9e06cf0b9659d389ed.out | 97 + ..._c1__--id__c2__--id__c3__--att__style__fill.out | 41 + ...al__10__--att-other-type__ValueInterpolator.out | 27 + ..._--start-val____050505__--end-val____000000.out | 27 + ..._--start-val____181818__--end-val____000000.out | 27 + ...__scale__--start-val__0__2__--end-val__0__9.out | 27 + ...orm__trans-x__--start-val__0__--end-val__20.out | 27 + ...art-val__0__02__--end-val__0__1__--unit__mm.out | 27 + ...erp_att_g__--id__layer1__--att__style__fill.out | 41 + ...erp_att_g__e692b471578dc63d4bf1ba375b8b650c.out | 27 + ...autotexts__--autoText__slideTitle__--id__t1.out | 41 + ...fade__--effectOut__pop__--effectOutOrder__2.out | 41 + ...ts__--id__p1__--id__r3__--effectOutOrder__2.out | 0 ...ssyink_export__--resolution__1__--type__png.out | Bin 0 -> 960 bytes .../tests/data/refs/jessyink_install.out | 2766 ++ .../refs/jessyink_install__--id__p1__--id__r3.out | 2766 ++ ...drawing_undo__ENTER__--index_nextPage__LEFT.out | 61 + ...__a__--drawing_undo__b__--index_nextPage__c.out | 61 + .../tests/data/refs/jessyink_master_slide.out | 0 .../jessyink_master_slide__--id__p1__--id__r3.out | 0 ...yink_mouse_handler__--mouseSetting__default.out | 0 ...mouse_handler__--mouseSetting__draggingZoom.out | 475 + ...yink_mouse_handler__--mouseSetting__noclick.out | 94 + .../tests/data/refs/jessyink_summary.out | 10 + .../jessyink_transitions__--layerName__Slide2.out | 0 .../tests/data/refs/jessyink_uninstall.out | 39 + .../extensions/tests/data/refs/jessyink_video.out | 61 + .../jessyink_view__--id__r3__--viewOrder__1.out | 41 + ...-dist__gaussian__--end__false__--ctrl__true.out | 41 + ...dist__lognorm__--radiusx__100__--ctrl__true.out | 41 + ...-dist__pareto__--radiusy__100__--ctrl__true.out | 41 + ...s__--id__p1__--dist__uniform__--ctrl__false.out | 41 + share/extensions/tests/data/refs/layer2png.out | 0 .../data/refs/layer2png__--id__p1__--id__r3.out | 0 .../data/refs/layers2svgfont__font_layers__svg.out | 3 + ...layers2svgfont__font_layers_apostrophe__svg.out | 19 + share/extensions/tests/data/refs/lindenmayer.out | 41 + .../data/refs/lindenmayer__--id__p1__--id__r3.out | 41 + ...E__--order__3__--langle__120__--rangle__120.out | 41 + ...__F__--order__1__--langle__60__--rangle__60.out | 41 + share/extensions/tests/data/refs/lorem_ipsum.out | 49 + .../tests/data/refs/lorem_ipsum__--id__r1.out | 49 + .../refs/lorem_ipsum__--id__r1__--svg2__false.out | 42 + .../tests/data/refs/lorem_ipsum__--id__t4.out | 41 + .../tests/data/refs/lorem_ipsum__--svg2__false.out | 41 + .../tests/data/refs/lorem_ipsum__--svg2__true.out | 42 + ...__custom____--id__dimension__--type__stroke.out | 26 + ...__object____--id__dimension__--type__stroke.out | 26 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 34 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 34 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 34 + ...__--fontsize__20__--unit__mm__--scale__1__1.out | 41 + .../data/refs/merge_styles__--id__c2__--id__c3.out | 46 + .../tests/data/refs/motion__--id__c3__--id__p2.out | 41 + ...oke__True__--id__path23053__--id__path28636.out | 8 + .../extensions/tests/data/refs/new_glyph_layer.out | 0 .../refs/new_glyph_layer__--id__p1__--id__r3.out | 0 .../tests/data/refs/next_glyph_layer.out | 0 .../refs/next_glyph_layer__--id__p1__--id__r3.out | 0 ...ue__--font-color__black__--what__22__11__67.out | 13 + ...ue__--font-color__black__--what__22__11__67.out | 13 + ...ue__--font-color__black__--what__22__11__67.out | 13 + ...nicechart__3afa80cf55d99e9c0ea691c780458309.out | 13 + share/extensions/tests/data/refs/output_scour.out | 40 + ...__-s__8__--isoscale__True__--drawaxis__True.out | 40 + ...__-s__8__--isoscale__True__--drawaxis__True.out | 0 .../path_envelope__--id__obj__--id__envelope.out | 20 + .../path_envelope__--id__text__--id__envelope.out | 6 + .../path_mesh_m2p__--id__mesh1__--mode__faces.out | 78 + ...th_mesh_m2p__--id__mesh1__--mode__gridlines.out | 78 + ..._mesh_m2p__--id__mesh1__--mode__meshpatches.out | 78 + ...path_mesh_m2p__--id__mesh1__--mode__outline.out | 78 + .../path_mesh_p2m__--id__path1__--id__path9.out | 78 + .../tests/data/refs/path_number_nodes__--id__D.out | 33 + .../refs/path_number_nodes__--id__p1__--id__r3.out | 40 + ...h_to_absolute__--id__c1__--id__c2__--id__c3.out | 41 + ...ute__--id__p1__--id__p2__--id__s1__--id__u1.out | 41 + ...id__r1__--id__r2__--id__r3__--id__slicerect.out | 41 + ...d__r1__--id__r2__--id__r3__--id__slicerect1.out | 36 + ..._--kind__Snake__--id__g3427__--id__path2551.out | 101 + ...--kind__Ribbon__--id__g4054__--id__path4056.out | 117 + ...ertical__True__--id__g3961__--id__path10007.out | 108 + ..._--space__5__--id__path2408__--id__path2405.out | 98 + ..._--kind__Snake__--id__g5848__--id__path3336.out | 53 + ...d__path4608__--id__path4610__--id__path4612.out | 98 + ...kind__Snake__--id__text4418__--id__path4412.out | 121 + ...path8143__--stretch__False__--follow__False.out | 158 + ...e__copy__--grouppick__True__--pickmode__seq.out | 62 + ...ch__True__--rotate__True__--copymode__clone.out | 24 + ...-id__path8143__--stretch__True__--space__10.out | 74 + ...tch__True__--follow__True__--copymode__copy.out | 65 + .../tests/data/refs/pdflatex__--font_size__15.out | 88 + ...latex__--font_size__15__--standalone__False.out | 88 + ...mule________frac__1____sqrt__5______2______.out | 34 + ...mule________frac__1____sqrt__5______2______.out | 29 + .../pdflatex__0355ed68ae6ec25166e664512ef53660.out | 49 + .../tests/data/refs/perfectboundcover.out | 41 + .../perspective__--id__obj__--id__envelope.out | 20 + .../data/refs/perspective__--id__p1__--id__p2.out | 41 + .../perspective__--id__text__--id__envelope.out | 6 + ...ixelsnap__--id__p1__--id__r3__--snap_to__bl.out | 41 + ...id__path1434__--id__path1434__--snap_to__bl.out | 11 + ...id__path1434__--id__path1434__--snap_to__tl.out | 11 + ...--force__24__--speed__20__--orientation__90.out | 2 + ...--force__24__--speed__20__--orientation__90.out | 34 + ...--force__24__--speed__20__--orientation__90.out | 35 + share/extensions/tests/data/refs/plt_output.out | 1 + ...show__edg__--obj__methane__--cw_wound__True.out | 2 + ..._z__--r1_ang__45__--th__4__--cw_wound__True.out | 2 + ..._--r2_ax__y__--r2_ang__45__--cw_wound__True.out | 2 + ...1_ang__45__--z_sort__cent__--cw_wound__True.out | 2 + ...r1_ang__45__--z_sort__max__--cw_wound__True.out | 2 + ...le__great_stel_dodec__obj__--cw_wound__True.out | 2 + ...show__vtx__--obj__methane__--cw_wound__True.out | 2 + ...hedron_3d__31c852a9dcfffc92123ff370cba34361.out | 41 + .../tests/data/refs/prepare_file_save_as.out | 115 + .../tests/data/refs/previous_glyph_layer.out | 0 .../previous_glyph_layer__--id__p1__--id__r3.out | 0 .../tests/data/refs/print_win32_vector.out | 0 .../print_win32_vector__--id__p1__--id__r3.out | 0 .../extensions/tests/data/refs/printing_marks.out | 41 + .../refs/printing_marks__--id__p1__--id__r3.out | 41 + ...ing_marks__fcb9f72a813c7f3f65cc9dbdb50c294a.out | 41 + .../tests/data/refs/ps_input__test__eps.out | 82 + .../tests/data/refs/ps_input__test__ps.out | Bin 0 -> 2762 bytes ...er_barcode__--type__Code93__--text__3332222.out | 41 + .../render_barcode__--type__Ean2__--text__55.out | 41 + ...ender_barcode__--type__Upce__--text__123456.out | 41 + ...matrix__--symbol__rect8x32__--text__1234Foo.out | 2 + .../render_barcode_datamatrix__--symbol__sq10.out | 2 + ...amatrix__--symbol__sq144__--text__HelloTest.out | 2 + ...atamatrix__--symbol__sq96__--text__Sunshine.out | 2 + ...0__--drawtype__smooth__--smoothness__greedy.out | 2 + ...0__--drawtype__smooth__--smoothness__greedy.out | 2 + ...0__--drawtype__smooth__--smoothness__greedy.out | 2 + ...id__AirTransportation_Inv__--modulesize__10.out | 12 + ...reset__--pathtype__circle__--modulesize__10.out | 2 + ...0__--drawtype__smooth__--smoothness__greedy.out | 2 + ...type__selection__--id__r3__--modulesize__10.out | 41 + ...de_qrcode__a95852ad07710857e3fadaaa059140e8.out | 2 + ...de_qrcode__e3208cfbf8a72ec55b5335e55f8674db.out | 2 + .../tests/data/refs/render_gear_rack.out | 41 + .../refs/render_gear_rack__--id__p1__--id__r3.out | 41 + .../refs/render_gears__--centerdiameter__10__0.out | 41 + ...--id__p1__--id__r3__--centerdiameter__10__0.out | 41 + ...r_find__sans-serif__--fr_replace__monospace.out | 41 + .../refs/replace_font__--action__list_only.out | 1 + ...0__--id__g26580__--id__g21081__--id__g20854.out | 38 + ...--direction__tb__--xanchor__m__--yanchor__m.out | 41 + ...--direction__tb__--xanchor__m__--yanchor__m.out | 41 + ...--direction__tb__--xanchor__m__--yanchor__m.out | 41 + ...--direction__tb__--xanchor__m__--yanchor__m.out | 41 + .../restack__cde2e552c805941baaf79d0821ec1e63.out | 41 + .../tests/data/refs/rtree__--minimum__4__0.out | 41 + ...ch__--id__path3997__--ratio__0__--curve__50.out | 16 + ...h__--id__path3997__--ratio__25__--curve__25.out | 16 + ...ch__--id__path3997__--ratio__50__--curve__0.out | 16 + ...s_export_pdf__--pdf-version__13__--bleed__0.out | Bin 0 -> 14059 bytes .../refs/setup_typography_canvas__empty__svg.out | 15 + .../refs/setup_typography_canvas__shapes__svg.out | 41 + share/extensions/tests/data/refs/sk1_output.out | 126 + ...ph__--primaryr__60__0__--secondaryr__100__0.out | 41 + share/extensions/tests/data/refs/straightseg.out | 0 .../data/refs/straightseg__--id__p1__--id__r3.out | 41 + ...gcalendar__9cc828f60a4a546fd4e0fdf4dd392e96.out | 41 + .../tests/data/refs/svgfont2layers__--count__3.out | 20 + share/extensions/tests/data/refs/synfig_output.out | 3 + share/extensions/tests/data/refs/tar_layers.out | Bin 0 -> 13312 bytes .../data/refs/tar_layers__--id__p1__--id__r3.out | Bin 0 -> 13312 bytes ...50__--grid__true__--orientation__horizontal.out | 2 + ...0x50__--grid__true__--orientation__vertical.out | 2 + ...15mm__--background__black__--noborder__true.out | 2 + ...om__--width__100__--height__100__--unit__in.out | 2 + .../refs/template_dvd_cover__-s__10__-b__10.out | 2 + ...amless_pattern__--width__100__--height__100.out | 90 + .../extensions/tests/data/refs/test_color_list.out | 10 + .../data/refs/test_color_list__--id__color_svg.out | 10 + .../tests/data/refs/test_color_list__--id__r1.out | 3 + .../refs/test_color_list__--id__r1__--id__r2.out | 10 + .../tests/data/refs/test_color_list__--id__r2.out | 6 + .../tests/data/refs/test_color_list__--id__r3.out | 8 + .../tests/data/refs/test_color_list__--id__r4.out | 10 + share/extensions/tests/data/refs/text_braille.out | 41 + ...t__--xanchor__center_x__--yanchor__center_y.out | 8 + ...r__--xanchor__center_x__--yanchor__center_y.out | 8 + ...l__--xanchor__center_x__--yanchor__center_y.out | 8 + ...b__--xanchor__center_x__--yanchor__center_y.out | 8 + share/extensions/tests/data/refs/text_flipcase.out | 41 + .../extensions/tests/data/refs/text_lowercase.out | 41 + share/extensions/tests/data/refs/text_merge.out | 41 + .../extensions/tests/data/refs/text_randomcase.out | 41 + .../tests/data/refs/text_sentencecase.out | 41 + ...ext_split__5478757cb04224bacfa3c641fea954ba.out | 28 + ...ext_split__74947d6e9e9ee89a80bbec0bfacc6dfb.out | 28 + ...ext_split__897ab8b3c516acacaf68391a51eb8836.out | 27 + ...ext_split__ad318803d098b3903561d44825a36ea0.out | 45 + ...ext_split__c242adcac78228419d3c065a99727bfb.out | 44 + ...ext_split__d8b155ac58a7424471f416b64f21669f.out | 27 + ...ext_split__dd77d3cc0134ad62833e05ca73e38896.out | 27 + .../extensions/tests/data/refs/text_titlecase.out | 41 + .../extensions/tests/data/refs/text_uppercase.out | 41 + share/extensions/tests/data/refs/triangle.out | 41 + .../data/refs/triangle__--id__p1__--id__r3.out | 41 + share/extensions/tests/data/refs/ungroup_deep.out | 33 + .../tests/data/refs/ungroup_deep__--id__g13.out | 16 + ..._deep__--id__g1935__--id__g6577__--id__g115.out | 19 + .../tests/data/refs/ungroup_deep__--id__layer2.out | 39 + ...__--diagram-type__Voronoi__--clip-box__Page.out | 79 + ...oth__--delaunay-fill-options__delaunay-fill.out | 81 + ...ronoi2svg__083b27d59093207e6210e1001eb9d5df.out | 41 + ...ronoi2svg__6d561032e7d7e60e607c75e562f677a4.out | 91 + .../web_interactive_mockup__--id__p1__--id__r3.out | 266 + ...--id__p1__--id__r3__--att__fill__--val__red.out | 266 + .../refs/web_transmit_att__--id__p1__--id__r3.out | 266 + .../webslicer_create_group__--id__slicerect1.out | 41 + .../tests/data/refs/webslicer_create_rect.out | 41 + .../webslicer_create_rect__--id__p1__--id__r3.out | 41 + .../data/refs/webslicer_export__--dir__TMP_DIR.out | 0 .../whirl__--id__p1__--id__r3__--whirl__1__0.out | 41 + .../tests/data/refs/wireframe_sphere.out | 41 + .../refs/wireframe_sphere__--id__p1__--id__r3.out | 41 + share/extensions/tests/data/refs/wmf_output.out | Bin 0 -> 4698 bytes .../extensions/tests/data/svg/clips_and_masks.svg | 87 + share/extensions/tests/data/svg/colors.svg | 39 + .../tests/data/svg/complextransform.test.svg | 71 + share/extensions/tests/data/svg/css.svg | 94 + share/extensions/tests/data/svg/curves.svg | 72 + share/extensions/tests/data/svg/dash.svg | 40 + .../extensions/tests/data/svg/dash_zerolength.svg | 34 + .../tests/data/svg/deep-ungroup-complex.svg | 158 + .../tests/data/svg/default-inkscape-SVG.svg | 37 + .../data/svg/default-inkscape-SVG_scoured.svg | 12 + .../tests/data/svg/default-plain-SVG.svg | 29 + share/extensions/tests/data/svg/diff.svg | 281 + .../extensions/tests/data/svg/doc_ai_conv_m_in.svg | 24 + .../tests/data/svg/doc_ai_conv_mm_in.svg | 24 + .../tests/data/svg/dpiswitcher_96dpi.svg | 169 + .../tests/data/svg/dxf_nested_transforms.svg | 69 + share/extensions/tests/data/svg/edge3d.svg | 31 + .../tests/data/svg/ellipse_group_comment.svg | 21 + share/extensions/tests/data/svg/embed.svg | 120 + share/extensions/tests/data/svg/empty.svg | 13 + share/extensions/tests/data/svg/empty_mm.svg | 14 + .../extensions/tests/data/svg/empty_multipage.svg | 90 + share/extensions/tests/data/svg/extrude.svg | 129 + share/extensions/tests/data/svg/font.svg | 27 + share/extensions/tests/data/svg/font_layers.svg | 3 + .../tests/data/svg/font_layers_apostrophe.svg | 12 + .../tests/data/svg/gradient_with_mixed_offsets.svg | 26 + .../tests/data/svg/group_interpolate.svg | 110 + share/extensions/tests/data/svg/guides.svg | 233 + .../tests/data/svg/guides_millimeter.svg | 89 + share/extensions/tests/data/svg/hershey_input.svg | 1082 + .../tests/data/svg/hershey_trivial_input.svg | 124 + share/extensions/tests/data/svg/hpgl_multipen.svg | 43 + share/extensions/tests/data/svg/images.svg | 73 + .../extensions/tests/data/svg/images_multiple.svg | 31 + .../tests/data/svg/img/color_overlay_a.png | Bin 0 -> 6932 bytes .../tests/data/svg/img/color_overlay_b.png | Bin 0 -> 6760 bytes .../extensions/tests/data/svg/img/color_pad_a.png | Bin 0 -> 3109 bytes .../extensions/tests/data/svg/img/color_pad_b.png | Bin 0 -> 3109 bytes .../extensions/tests/data/svg/img/color_pad_c.png | Bin 0 -> 3109 bytes share/extensions/tests/data/svg/img/green.png | Bin 0 -> 128 bytes share/extensions/tests/data/svg/img/linecap.png | Bin 0 -> 7361 bytes .../tests/data/svg/img/subfolder/linecap.png | Bin 0 -> 7361 bytes share/extensions/tests/data/svg/inkweb-debug.js | 367 + share/extensions/tests/data/svg/inkwebjs-move.svg | 128 + share/extensions/tests/data/svg/interp_shapes.svg | 210 + share/extensions/tests/data/svg/markers.svg | 55 + share/extensions/tests/data/svg/mesh.svg | 240 + .../tests/data/svg/minimal-blank-prepare.svg | 1 + share/extensions/tests/data/svg/minimal-blank.svg | 1 + share/extensions/tests/data/svg/motion_tests.svg | 73 + .../tests/data/svg/multilayered-test.svg | 156 + .../tests/data/svg/multiple_closed_subpaths.svg | 49 + .../tests/data/svg/paths_open_closed.svg | 67 + .../tests/data/svg/pattern_along_path.svg | 498 + .../svg/pattern_along_path_clone_transform.svg | 116 + share/extensions/tests/data/svg/perspective.svg | 33 + .../tests/data/svg/perspective_groups.svg | 78 + .../extensions/tests/data/svg/pixelsnap_simple.svg | 69 + .../tests/data/svg/preserved-transforms.svg | 59 + .../extensions/tests/data/svg/restack_grouped.svg | 215 + .../tests/data/svg/rubber-stretch-test.svg | 66 + .../extensions/tests/data/svg/scale_not_unity.svg | 65 + share/extensions/tests/data/svg/scatter.svg | 106 + .../extensions/tests/data/svg/shapes-clipboard.svg | 288 + share/extensions/tests/data/svg/shapes.svg | 284 + share/extensions/tests/data/svg/shapes_cmyk.svg | 302 + .../extensions/tests/data/svg/simple_patterns.svg | 85 + .../tests/data/svg/simpletransform.test.svg | 8 + share/extensions/tests/data/svg/single_box.svg | 62 + share/extensions/tests/data/svg/slicer.svg | 75 + .../tests/data/svg/style_inheritance.svg | 75 + .../extensions/tests/data/svg/styling-css-04-f.svg | 134 + .../tests/data/svg/styling-inherit-01-b.svg | 59 + share/extensions/tests/data/svg/symbol.svg | 46 + share/extensions/tests/data/svg/text_on_arc.svg | 19 + share/extensions/tests/data/svg/text_types.svg | 256 + .../tests/data/svg/three_pages_and_two_grids.svg | 90 + .../tests/data/svg/transformed-layer.svg | 19 + share/extensions/tests/data/svg/with-lpe.svg | 30 + share/extensions/tests/data/ui/app-test.ui | 50 + share/extensions/tests/data/ui/listing-app.ui | 71 + share/extensions/tests/data/ui/window-test.ui | 91 + share/extensions/tests/test_addnodes.py | 47 + share/extensions/tests/test_color_HSL_adjust.py | 33 + share/extensions/tests/test_color_blackandwhite.py | 33 + share/extensions/tests/test_color_brighter.py | 27 + share/extensions/tests/test_color_custom.py | 50 + share/extensions/tests/test_color_darker.py | 28 + share/extensions/tests/test_color_desaturate.py | 26 + share/extensions/tests/test_color_grayscale.py | 26 + share/extensions/tests/test_color_lesshue.py | 28 + share/extensions/tests/test_color_lesslight.py | 28 + .../extensions/tests/test_color_lesssaturation.py | 28 + share/extensions/tests/test_color_list.py | 12 + share/extensions/tests/test_color_morehue.py | 29 + share/extensions/tests/test_color_morelight.py | 28 + .../extensions/tests/test_color_moresaturation.py | 28 + share/extensions/tests/test_color_negative.py | 26 + share/extensions/tests/test_color_randomize.py | 93 + share/extensions/tests/test_color_removeblue.py | 26 + share/extensions/tests/test_color_removegreen.py | 26 + share/extensions/tests/test_color_removered.py | 26 + share/extensions/tests/test_color_replace.py | 39 + share/extensions/tests/test_color_rgbbarrel.py | 27 + share/extensions/tests/test_convert2dashes.py | 23 + share/extensions/tests/test_deprecated_simple.py | 216 + share/extensions/tests/test_dhw_input.py | 18 + share/extensions/tests/test_dimension.py | 17 + share/extensions/tests/test_doc_ai_convert.py | 15 + share/extensions/tests/test_docinfo.py | 12 + share/extensions/tests/test_dpiswitcher.py | 33 + share/extensions/tests/test_draw_from_triangle.py | 10 + share/extensions/tests/test_dxf12_outlines.py | 17 + share/extensions/tests/test_dxf_input.py | 71 + share/extensions/tests/test_dxf_outlines.py | 76 + share/extensions/tests/test_edge3d.py | 28 + share/extensions/tests/test_export_gimp_palette.py | 10 + share/extensions/tests/test_extrude.py | 53 + share/extensions/tests/test_fig_input.py | 11 + share/extensions/tests/test_flatten.py | 9 + share/extensions/tests/test_foldablebox.py | 12 + share/extensions/tests/test_fractalize.py | 8 + share/extensions/tests/test_frame.py | 200 + share/extensions/tests/test_funcplot.py | 13 + share/extensions/tests/test_generate_voronoi.py | 12 + share/extensions/tests/test_gimp_xcf.py | 26 + share/extensions/tests/test_grid_cartesian.py | 31 + share/extensions/tests/test_grid_isometric.py | 11 + share/extensions/tests/test_grid_polar.py | 13 + share/extensions/tests/test_guides_creator.py | 109 + share/extensions/tests/test_guillotine.py | 75 + share/extensions/tests/test_handles.py | 10 + share/extensions/tests/test_hershey.py | 77 + share/extensions/tests/test_hpgl_decoder.py | 25 + share/extensions/tests/test_hpgl_input.py | 9 + share/extensions/tests/test_hpgl_output.py | 9 + share/extensions/tests/test_image_attributes.py | 17 + share/extensions/tests/test_image_embed.py | 15 + share/extensions/tests/test_image_extract.py | 196 + share/extensions/tests/test_ink2canvas_svg.py | 38 + share/extensions/tests/test_inkex.py | 73 + share/extensions/tests/test_inkex_base.py | 210 + share/extensions/tests/test_inkex_bezier.py | 10 + share/extensions/tests/test_inkex_bounding_box.py | 699 + share/extensions/tests/test_inkex_colors.py | 187 + share/extensions/tests/test_inkex_command.py | 45 + share/extensions/tests/test_inkex_cubic_paths.py | 74 + share/extensions/tests/test_inkex_deprecated.py | 42 + share/extensions/tests/test_inkex_elements.py | 816 + share/extensions/tests/test_inkex_elements_base.py | 448 + .../tests/test_inkex_elements_filters.py | 20 + .../tests/test_inkex_elements_selections.py | 134 + share/extensions/tests/test_inkex_extensions.py | 69 + .../test_inkex_extensions_GenerateExtension.py | 41 + share/extensions/tests/test_inkex_gui.py | 174 + share/extensions/tests/test_inkex_gui_asyncme.py | 124 + share/extensions/tests/test_inkex_gui_listview.py | 253 + share/extensions/tests/test_inkex_gui_pixmaps.py | 232 + share/extensions/tests/test_inkex_gui_window.py | 102 + share/extensions/tests/test_inkex_inx.py | 144 + share/extensions/tests/test_inkex_paths.py | 950 + share/extensions/tests/test_inkex_styles.py | 235 + .../extensions/tests/test_inkex_styles_complex.py | 465 + share/extensions/tests/test_inkex_svg.py | 610 + share/extensions/tests/test_inkex_tester.py | 30 + share/extensions/tests/test_inkex_transforms.py | 801 + share/extensions/tests/test_inkex_tween.py | 215 + share/extensions/tests/test_inkex_units.py | 71 + share/extensions/tests/test_inkex_utils.py | 186 + .../extensions/tests/test_inkscape_follow_link.py | 7 + share/extensions/tests/test_inkwebeffect.py | 7 + share/extensions/tests/test_interp.py | 40 + share/extensions/tests/test_interp_att_g.py | 67 + share/extensions/tests/test_jessyink_autotexts.py | 9 + share/extensions/tests/test_jessyink_effects.py | 12 + share/extensions/tests/test_jessyink_export.py | 10 + share/extensions/tests/test_jessyink_install.py | 7 + .../extensions/tests/test_jessyink_keybindings.py | 11 + .../extensions/tests/test_jessyink_masterslide.py | 7 + .../extensions/tests/test_jessyink_mousehandler.py | 14 + share/extensions/tests/test_jessyink_summary.py | 11 + .../extensions/tests/test_jessyink_transitions.py | 8 + share/extensions/tests/test_jessyink_uninstall.py | 8 + share/extensions/tests/test_jessyink_video.py | 9 + share/extensions/tests/test_jessyink_view.py | 8 + share/extensions/tests/test_jitternodes.py | 13 + share/extensions/tests/test_layer2png.py | 42 + share/extensions/tests/test_layers2svgfont.py | 9 + share/extensions/tests/test_layout_nup.py | 7 + share/extensions/tests/test_lindenmayer.py | 22 + share/extensions/tests/test_lorem_ipsum.py | 21 + share/extensions/tests/test_markers_strokepaint.py | 26 + share/extensions/tests/test_measure.py | 33 + share/extensions/tests/test_media_zip.py | 56 + share/extensions/tests/test_merge_styles.py | 10 + share/extensions/tests/test_motion.py | 30 + share/extensions/tests/test_new_glyph_layer.py | 7 + share/extensions/tests/test_next_glyph_layer.py | 7 + share/extensions/tests/test_nicechart.py | 23 + share/extensions/tests/test_output_scour.py | 11 + share/extensions/tests/test_param_curves.py | 13 + share/extensions/tests/test_path_envelope.py | 18 + share/extensions/tests/test_path_mesh.py | 31 + share/extensions/tests/test_path_number_nodes.py | 14 + share/extensions/tests/test_path_to_absolute.py | 19 + share/extensions/tests/test_pathalongpath.py | 77 + share/extensions/tests/test_pathscatter.py | 41 + share/extensions/tests/test_pdflatex.py | 56 + share/extensions/tests/test_perfectboundcover.py | 8 + share/extensions/tests/test_perspective.py | 17 + share/extensions/tests/test_pixelsnap.py | 36 + share/extensions/tests/test_plotter.py | 27 + share/extensions/tests/test_polyhedron_3d.py | 53 + .../extensions/tests/test_prepare_file_save_as.py | 10 + .../extensions/tests/test_previous_glyph_layer.py | 7 + share/extensions/tests/test_print_win32_vector.py | 31 + share/extensions/tests/test_printing_marks.py | 34 + share/extensions/tests/test_ps_input.py | 18 + share/extensions/tests/test_render_alphabetsoup.py | 7 + share/extensions/tests/test_render_barcode.py | 103 + .../tests/test_render_barcode_datamatrix.py | 14 + .../extensions/tests/test_render_barcode_qrcode.py | 101 + share/extensions/tests/test_render_gear_rack.py | 9 + share/extensions/tests/test_render_gears.py | 13 + share/extensions/tests/test_replace_font.py | 26 + share/extensions/tests/test_restack.py | 40 + share/extensions/tests/test_rtree.py | 13 + share/extensions/tests/test_rubberstretch.py | 13 + share/extensions/tests/test_scribus_pdf.py | 15 + .../tests/test_setup_typography_canvas.py | 11 + share/extensions/tests/test_spirograph.py | 10 + share/extensions/tests/test_straightseg.py | 11 + share/extensions/tests/test_svgcalendar.py | 122 + share/extensions/tests/test_svgfont2layers.py | 9 + share/extensions/tests/test_synfig_fileformat.py | 7 + share/extensions/tests/test_synfig_output.py | 22 + share/extensions/tests/test_tar_layers.py | 9 + share/extensions/tests/test_template.py | 14 + share/extensions/tests/test_template_dvd_cover.py | 9 + .../tests/test_template_seamless_pattern.py | 10 + share/extensions/tests/test_text_braille.py | 9 + share/extensions/tests/test_text_extract.py | 16 + share/extensions/tests/test_text_flipcase.py | 8 + share/extensions/tests/test_text_lowercase.py | 57 + share/extensions/tests/test_text_merge.py | 8 + share/extensions/tests/test_text_randomcase.py | 8 + share/extensions/tests/test_text_sentencecase.py | 8 + share/extensions/tests/test_text_split.py | 36 + share/extensions/tests/test_text_titlecase.py | 70 + share/extensions/tests/test_text_uppercase.py | 45 + share/extensions/tests/test_triangle.py | 9 + share/extensions/tests/test_ungroup_deep.py | 32 + share/extensions/tests/test_voronoi.py | 9 + share/extensions/tests/test_voronoi2svg.py | 53 + .../tests/test_web_interactive_mockup.py | 8 + share/extensions/tests/test_web_set_att.py | 8 + share/extensions/tests/test_web_transmit_att.py | 8 + .../tests/test_webslicer_create_group.py | 8 + .../extensions/tests/test_webslicer_create_rect.py | 7 + share/extensions/tests/test_webslicer_export.py | 12 + share/extensions/tests/test_whirl.py | 11 + share/extensions/tests/test_wireframe_sphere.py | 9 + share/extensions/text_braille.inx | 14 + share/extensions/text_braille.py | 25 + share/extensions/text_extract.inx | 30 + share/extensions/text_extract.py | 81 + share/extensions/text_flipcase.inx | 16 + share/extensions/text_flipcase.py | 16 + share/extensions/text_lowercase.inx | 16 + share/extensions/text_lowercase.py | 15 + share/extensions/text_merge.inx | 32 + share/extensions/text_merge.py | 129 + share/extensions/text_randomcase.inx | 16 + share/extensions/text_randomcase.py | 32 + share/extensions/text_sentencecase.inx | 16 + share/extensions/text_sentencecase.py | 38 + share/extensions/text_split.inx | 35 + share/extensions/text_split.py | 313 + share/extensions/text_titlecase.inx | 16 + share/extensions/text_titlecase.py | 33 + share/extensions/text_uppercase.inx | 16 + share/extensions/text_uppercase.py | 15 + share/extensions/tools/generate_argparse_conf.py | 69 + share/extensions/tox.ini | 29 + share/extensions/triangle.inx | 27 + share/extensions/triangle.py | 223 + share/extensions/ungroup_deep.inx | 18 + share/extensions/ungroup_deep.py | 205 + share/extensions/voronoi.py | 859 + share/extensions/voronoi2svg.inx | 39 + share/extensions/voronoi2svg.py | 310 + share/extensions/web_interactive_mockup.inx | 38 + share/extensions/web_interactive_mockup.py | 52 + share/extensions/web_set_att.inx | 50 + share/extensions/web_set_att.py | 80 + share/extensions/web_transmit_att.inx | 48 + share/extensions/web_transmit_att.py | 64 + share/extensions/webslicer_create_group.inx | 37 + share/extensions/webslicer_create_group.py | 65 + share/extensions/webslicer_create_rect.inx | 71 + share/extensions/webslicer_create_rect.py | 109 + share/extensions/webslicer_effect.py | 55 + share/extensions/webslicer_export.inx | 27 + share/extensions/webslicer_export.py | 470 + share/extensions/whirl.inx | 16 + share/extensions/whirl.py | 69 + share/extensions/wireframe_sphere.inx | 20 + share/extensions/wireframe_sphere.py | 209 + share/extensions/xaml2svg.inx | 14 + share/extensions/xaml2svg.xsl | 107 + share/extensions/xaml2svg/animation.xsl | 141 + share/extensions/xaml2svg/brushes.xsl | 244 + share/extensions/xaml2svg/canvas.xsl | 80 + share/extensions/xaml2svg/geometry.xsl | 272 + share/extensions/xaml2svg/properties.xsl | 286 + share/extensions/xaml2svg/shapes.xsl | 171 + share/extensions/xaml2svg/transform.xsl | 120 + 1419 files changed, 367602 insertions(+) create mode 100644 share/extensions/.darglint create mode 100644 share/extensions/.gitmodules create mode 100644 share/extensions/.pre-commit-config.yaml create mode 100644 share/extensions/.pylintrc create mode 100644 share/extensions/CONTRIBUTING.md create mode 100644 share/extensions/LICENSE.txt create mode 100644 share/extensions/MANIFEST.in create mode 100644 share/extensions/Poly3DObjects/cube.obj create mode 100644 share/extensions/Poly3DObjects/cuboct.obj create mode 100644 share/extensions/Poly3DObjects/dodec.obj create mode 100644 share/extensions/Poly3DObjects/great_dodec.obj create mode 100644 share/extensions/Poly3DObjects/great_rhombicosidodec.obj create mode 100644 share/extensions/Poly3DObjects/great_rhombicuboct.obj create mode 100644 share/extensions/Poly3DObjects/great_stel_dodec.obj create mode 100644 share/extensions/Poly3DObjects/icos.obj create mode 100644 share/extensions/Poly3DObjects/icosidodec.obj create mode 100644 share/extensions/Poly3DObjects/jessens_orthog_icos.obj create mode 100644 share/extensions/Poly3DObjects/methane.obj create mode 100644 share/extensions/Poly3DObjects/oct.obj create mode 100644 share/extensions/Poly3DObjects/rh_axes.obj create mode 100644 share/extensions/Poly3DObjects/rhomb_dodec.obj create mode 100644 share/extensions/Poly3DObjects/rhomb_triacont.obj create mode 100644 share/extensions/Poly3DObjects/small_rhombicosidodec.obj create mode 100644 share/extensions/Poly3DObjects/small_rhombicuboct.obj create mode 100644 share/extensions/Poly3DObjects/small_triam_icos.obj create mode 100644 share/extensions/Poly3DObjects/snub_cube.obj create mode 100644 share/extensions/Poly3DObjects/snub_dodec.obj create mode 100644 share/extensions/Poly3DObjects/szilassi.obj create mode 100644 share/extensions/Poly3DObjects/tet.obj create mode 100644 share/extensions/Poly3DObjects/trunc_cube.obj create mode 100644 share/extensions/Poly3DObjects/trunc_dodec.obj create mode 100644 share/extensions/Poly3DObjects/trunc_icos.obj create mode 100644 share/extensions/Poly3DObjects/trunc_oct.obj create mode 100644 share/extensions/Poly3DObjects/trunc_tet.obj create mode 100644 share/extensions/README.md create mode 100644 share/extensions/TESTING.md create mode 100644 share/extensions/addnodes.inx create mode 100755 share/extensions/addnodes.py create mode 100644 share/extensions/aisvg.inx create mode 100644 share/extensions/aisvg.xslt create mode 100644 share/extensions/alphabet_soup/2.svg create mode 100644 share/extensions/alphabet_soup/3.svg create mode 100644 share/extensions/alphabet_soup/6.svg create mode 100644 share/extensions/alphabet_soup/7.svg create mode 100644 share/extensions/alphabet_soup/Cblob.svg create mode 100644 share/extensions/alphabet_soup/Chook.svg create mode 100644 share/extensions/alphabet_soup/Ctail.svg create mode 100644 share/extensions/alphabet_soup/Delta.svg create mode 100644 share/extensions/alphabet_soup/Eb.svg create mode 100644 share/extensions/alphabet_soup/Eserif.svg create mode 100644 share/extensions/alphabet_soup/Et.svg create mode 100644 share/extensions/alphabet_soup/G.svg create mode 100644 share/extensions/alphabet_soup/IBSerif.svg create mode 100644 share/extensions/alphabet_soup/ITSerif.svg create mode 100644 share/extensions/alphabet_soup/Lb.svg create mode 100644 share/extensions/alphabet_soup/Lt.svg create mode 100644 share/extensions/alphabet_soup/Ocross.svg create mode 100644 share/extensions/alphabet_soup/Oterm.svg create mode 100644 share/extensions/alphabet_soup/P.svg create mode 100644 share/extensions/alphabet_soup/Q.svg create mode 100644 share/extensions/alphabet_soup/Rblock.svg create mode 100644 share/extensions/alphabet_soup/Tb.svg create mode 100644 share/extensions/alphabet_soup/Tt.svg create mode 100644 share/extensions/alphabet_soup/U.svg create mode 100644 share/extensions/alphabet_soup/Vser.svg create mode 100644 share/extensions/alphabet_soup/Xh.svg create mode 100644 share/extensions/alphabet_soup/Xne.svg create mode 100644 share/extensions/alphabet_soup/Xnw.svg create mode 100644 share/extensions/alphabet_soup/Xvb.svg create mode 100644 share/extensions/alphabet_soup/Xvt.svg create mode 100644 share/extensions/alphabet_soup/a.svg create mode 100644 share/extensions/alphabet_soup/abase.svg create mode 100644 share/extensions/alphabet_soup/acap.svg create mode 100644 share/extensions/alphabet_soup/b.svg create mode 100644 share/extensions/alphabet_soup/bar.svg create mode 100644 share/extensions/alphabet_soup/bar2.svg create mode 100644 share/extensions/alphabet_soup/barcap.svg create mode 100644 share/extensions/alphabet_soup/c.svg create mode 100644 share/extensions/alphabet_soup/cross.svg create mode 100644 share/extensions/alphabet_soup/cserif.svg create mode 100644 share/extensions/alphabet_soup/e.svg create mode 100644 share/extensions/alphabet_soup/epsilon.svg create mode 100644 share/extensions/alphabet_soup/f.svg create mode 100644 share/extensions/alphabet_soup/gamma.svg create mode 100644 share/extensions/alphabet_soup/h.svg create mode 100644 share/extensions/alphabet_soup/h2.svg create mode 100644 share/extensions/alphabet_soup/hcap.svg create mode 100644 share/extensions/alphabet_soup/idot.svg create mode 100644 share/extensions/alphabet_soup/j.svg create mode 100644 share/extensions/alphabet_soup/k.svg create mode 100644 share/extensions/alphabet_soup/l.svg create mode 100644 share/extensions/alphabet_soup/lserif.svg create mode 100644 share/extensions/alphabet_soup/m.svg create mode 100644 share/extensions/alphabet_soup/mcap.svg create mode 100644 share/extensions/alphabet_soup/n.svg create mode 100644 share/extensions/alphabet_soup/o.svg create mode 100644 share/extensions/alphabet_soup/ocap.svg create mode 100644 share/extensions/alphabet_soup/question.svg create mode 100644 share/extensions/alphabet_soup/r.svg create mode 100644 share/extensions/alphabet_soup/rcap.svg create mode 100644 share/extensions/alphabet_soup/s.svg create mode 100644 share/extensions/alphabet_soup/serif.svg create mode 100644 share/extensions/alphabet_soup/t.svg create mode 100644 share/extensions/alphabet_soup/tserif.svg create mode 100644 share/extensions/alphabet_soup/v.svg create mode 100644 share/extensions/alphabet_soup/vcap.svg create mode 100644 share/extensions/alphabet_soup/vserl.svg create mode 100644 share/extensions/alphabet_soup/vserr.svg create mode 100644 share/extensions/alphabet_soup/x.svg create mode 100644 share/extensions/alphabet_soup/y.svg create mode 100644 share/extensions/alphabet_soup/yogh.svg create mode 100644 share/extensions/alphabet_soup/z.svg create mode 100644 share/extensions/barcode/Base.py create mode 100644 share/extensions/barcode/BaseEan.py create mode 100644 share/extensions/barcode/Code128.py create mode 100644 share/extensions/barcode/Code25i.py create mode 100644 share/extensions/barcode/Code39.py create mode 100644 share/extensions/barcode/Code39Ext.py create mode 100644 share/extensions/barcode/Code93.py create mode 100644 share/extensions/barcode/Ean13.py create mode 100644 share/extensions/barcode/Ean2.py create mode 100644 share/extensions/barcode/Ean5.py create mode 100644 share/extensions/barcode/Ean8.py create mode 100644 share/extensions/barcode/Rm4scc.py create mode 100644 share/extensions/barcode/Upca.py create mode 100644 share/extensions/barcode/Upce.py create mode 100644 share/extensions/barcode/__init__.py create mode 100644 share/extensions/color_blackandwhite.inx create mode 100755 share/extensions/color_blackandwhite.py create mode 100644 share/extensions/color_brighter.inx create mode 100755 share/extensions/color_brighter.py create mode 100644 share/extensions/color_custom.inx create mode 100755 share/extensions/color_custom.py create mode 100644 share/extensions/color_darker.inx create mode 100755 share/extensions/color_darker.py create mode 100644 share/extensions/color_desaturate.inx create mode 100755 share/extensions/color_desaturate.py create mode 100644 share/extensions/color_grayscale.inx create mode 100755 share/extensions/color_grayscale.py create mode 100644 share/extensions/color_hsl_adjust.inx create mode 100755 share/extensions/color_hsl_adjust.py create mode 100644 share/extensions/color_lesshue.inx create mode 100755 share/extensions/color_lesshue.py create mode 100644 share/extensions/color_lesslight.inx create mode 100755 share/extensions/color_lesslight.py create mode 100644 share/extensions/color_lesssaturation.inx create mode 100755 share/extensions/color_lesssaturation.py create mode 100644 share/extensions/color_list.inx create mode 100755 share/extensions/color_list.py create mode 100644 share/extensions/color_morehue.inx create mode 100755 share/extensions/color_morehue.py create mode 100644 share/extensions/color_morelight.inx create mode 100755 share/extensions/color_morelight.py create mode 100644 share/extensions/color_moresaturation.inx create mode 100755 share/extensions/color_moresaturation.py create mode 100644 share/extensions/color_negative.inx create mode 100755 share/extensions/color_negative.py create mode 100644 share/extensions/color_randomize.inx create mode 100755 share/extensions/color_randomize.py create mode 100644 share/extensions/color_removeblue.inx create mode 100755 share/extensions/color_removeblue.py create mode 100644 share/extensions/color_removegreen.inx create mode 100755 share/extensions/color_removegreen.py create mode 100644 share/extensions/color_removered.inx create mode 100755 share/extensions/color_removered.py create mode 100644 share/extensions/color_replace.inx create mode 100755 share/extensions/color_replace.py create mode 100644 share/extensions/color_rgbbarrel.inx create mode 100755 share/extensions/color_rgbbarrel.py create mode 100644 share/extensions/colors.xml create mode 100644 share/extensions/convert2dashes.inx create mode 100755 share/extensions/convert2dashes.py create mode 100644 share/extensions/dhw_input.inx create mode 100755 share/extensions/dhw_input.py create mode 100644 share/extensions/dimension.inx create mode 100755 share/extensions/dimension.py create mode 100644 share/extensions/doc_ai_convert.inx create mode 100644 share/extensions/doc_ai_convert.py create mode 100644 share/extensions/docinfo.inx create mode 100755 share/extensions/docinfo.py create mode 100644 share/extensions/docs/Makefile create mode 100644 share/extensions/docs/_templates/versions.html create mode 100644 share/extensions/docs/authors/index.rst create mode 100644 share/extensions/docs/authors/interpreters.rst create mode 100644 share/extensions/docs/authors/inx-overview.rst create mode 100644 share/extensions/docs/authors/inx-widgets.rst create mode 100644 share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png create mode 100644 share/extensions/docs/authors/samples/unit_camera.svg create mode 100644 share/extensions/docs/authors/samples/units1.svg create mode 100644 share/extensions/docs/authors/samples/units2.svg create mode 100644 share/extensions/docs/authors/submit.rst create mode 100644 share/extensions/docs/authors/unit-tests.rst create mode 100644 share/extensions/docs/authors/units.rst create mode 100644 share/extensions/docs/authors/update1.0.rst create mode 100644 share/extensions/docs/authors/update1.2.rst create mode 100644 share/extensions/docs/authors/widgets/bool.png create mode 100644 share/extensions/docs/authors/widgets/color.png create mode 100644 share/extensions/docs/authors/widgets/float.png create mode 100644 share/extensions/docs/authors/widgets/image.png create mode 100644 share/extensions/docs/authors/widgets/integer.png create mode 100644 share/extensions/docs/authors/widgets/label.png create mode 100644 share/extensions/docs/authors/widgets/notebook.png create mode 100644 share/extensions/docs/authors/widgets/optiongroup.png create mode 100644 share/extensions/docs/authors/widgets/path.png create mode 100644 share/extensions/docs/authors/widgets/separator.png create mode 100644 share/extensions/docs/authors/widgets/spacer.png create mode 100644 share/extensions/docs/authors/widgets/string.png create mode 100644 share/extensions/docs/conf.py create mode 100644 share/extensions/docs/dev/getting-started.rst create mode 100644 share/extensions/docs/dev/index.rst create mode 100644 share/extensions/docs/favicon.svg create mode 100644 share/extensions/docs/index.rst create mode 100644 share/extensions/docs/make.bat create mode 100644 share/extensions/docs/source/index.rst create mode 100644 share/extensions/docs/tutorial/index.rst create mode 100644 share/extensions/docs/tutorial/my-first-effect-extension.rst create mode 100644 share/extensions/docs/tutorial/my-first-import-extension.rst create mode 100644 share/extensions/docs/tutorial/my-first-text-extension.rst create mode 100644 share/extensions/docs/tutorial/resources/Call_Extension_Failure.png create mode 100644 share/extensions/docs/tutorial/resources/Inkscape_Recognizes_Our_Extension.gif create mode 100644 share/extensions/docs/tutorial/resources/Smiles_Format.gif create mode 100644 share/extensions/docs/tutorial/resources/Text_Ext_Moment_of_truth.gif create mode 100644 share/extensions/docs/tutorial/resources/call_extension_success.gif create mode 100644 share/extensions/docs/tutorial/resources/make_red_extension.zip create mode 100644 share/extensions/docs/tutorial/resources/stroke-parity-widget.png create mode 100644 share/extensions/docs/tutorial/resources/stroke_parity_extension.zip create mode 100644 share/extensions/docs/tutorial/resources/template_effect.zip create mode 100644 share/extensions/docs/tutorial/resources/vanillin.smi create mode 100644 share/extensions/docs/tutorial/simple-path-extension.rst create mode 100644 share/extensions/doxygen-main.dox create mode 100644 share/extensions/dpi90to96.inx create mode 100644 share/extensions/dpi96to90.inx create mode 100755 share/extensions/dpiswitcher.py create mode 100644 share/extensions/draw_from_triangle.inx create mode 100755 share/extensions/draw_from_triangle.py create mode 100644 share/extensions/dxf12_outlines.inx create mode 100755 share/extensions/dxf12_outlines.py create mode 100755 share/extensions/dxf14_footer.txt create mode 100755 share/extensions/dxf14_header.txt create mode 100755 share/extensions/dxf14_style.txt create mode 100644 share/extensions/dxf_input.inx create mode 100644 share/extensions/dxf_input.py create mode 100644 share/extensions/dxf_input_text_scale_factor.svg create mode 100644 share/extensions/dxf_outlines.inx create mode 100755 share/extensions/dxf_outlines.py create mode 100644 share/extensions/edge3d.inx create mode 100755 share/extensions/edge3d.py create mode 100644 share/extensions/eps_input.inx create mode 100644 share/extensions/export_gimp_palette.inx create mode 100755 share/extensions/export_gimp_palette.py create mode 100644 share/extensions/extrude.inx create mode 100755 share/extensions/extrude.py create mode 100644 share/extensions/fig_input.inx create mode 100755 share/extensions/fig_input.py create mode 100644 share/extensions/flatten.inx create mode 100755 share/extensions/flatten.py create mode 100644 share/extensions/foldablebox.inx create mode 100755 share/extensions/foldablebox.py create mode 100644 share/extensions/fontfix.conf create mode 100644 share/extensions/fractalize.inx create mode 100755 share/extensions/fractalize.py create mode 100644 share/extensions/frame.inx create mode 100755 share/extensions/frame.py create mode 100644 share/extensions/funcplot.inx create mode 100755 share/extensions/funcplot.py create mode 100644 share/extensions/generate_voronoi.inx create mode 100755 share/extensions/generate_voronoi.py create mode 100755 share/extensions/genpofiles.sh create mode 100644 share/extensions/gimp_xcf.inx create mode 100755 share/extensions/gimp_xcf.py create mode 100644 share/extensions/grid_cartesian.inx create mode 100755 share/extensions/grid_cartesian.py create mode 100644 share/extensions/grid_isometric.inx create mode 100755 share/extensions/grid_isometric.py create mode 100644 share/extensions/grid_polar.inx create mode 100755 share/extensions/grid_polar.py create mode 100644 share/extensions/guides_creator.inx create mode 100755 share/extensions/guides_creator.py create mode 100644 share/extensions/guillotine.inx create mode 100755 share/extensions/guillotine.py create mode 100644 share/extensions/handles.inx create mode 100755 share/extensions/handles.py create mode 100755 share/extensions/hershey.inx create mode 100644 share/extensions/hershey.py create mode 100644 share/extensions/hpgl_decoder.py create mode 100644 share/extensions/hpgl_encoder.py create mode 100644 share/extensions/hpgl_input.inx create mode 100755 share/extensions/hpgl_input.py create mode 100644 share/extensions/hpgl_output.inx create mode 100755 share/extensions/hpgl_output.py create mode 100644 share/extensions/image_attributes.inx create mode 100755 share/extensions/image_attributes.py create mode 100644 share/extensions/image_embed.inx create mode 100755 share/extensions/image_embed.py create mode 100644 share/extensions/image_embed_selected.inx create mode 100644 share/extensions/image_extract.inx create mode 100755 share/extensions/image_extract.py create mode 100644 share/extensions/image_extract_selected.inx create mode 100644 share/extensions/ink2canvas.inx create mode 100755 share/extensions/ink2canvas.py create mode 100644 share/extensions/ink2canvas_lib/__init__.py create mode 100644 share/extensions/ink2canvas_lib/canvas.py create mode 100644 share/extensions/ink2canvas_lib/svg.py create mode 100644 share/extensions/inkex/__init__.py create mode 100644 share/extensions/inkex/base.py create mode 100644 share/extensions/inkex/bezier.py create mode 100644 share/extensions/inkex/colors.py create mode 100644 share/extensions/inkex/command.py create mode 100644 share/extensions/inkex/css.py create mode 100644 share/extensions/inkex/deprecated-simple/README.rst create mode 100644 share/extensions/inkex/deprecated-simple/bezmisc.py create mode 100644 share/extensions/inkex/deprecated-simple/cspsubdiv.py create mode 100644 share/extensions/inkex/deprecated-simple/cubicsuperpath.py create mode 100644 share/extensions/inkex/deprecated-simple/ffgeom.py create mode 100755 share/extensions/inkex/deprecated-simple/run_command.py create mode 100644 share/extensions/inkex/deprecated-simple/simplepath.py create mode 100644 share/extensions/inkex/deprecated-simple/simplestyle.py create mode 100644 share/extensions/inkex/deprecated-simple/simpletransform.py create mode 100644 share/extensions/inkex/deprecated/__init__.py create mode 100644 share/extensions/inkex/deprecated/deprecatedeffect.py create mode 100644 share/extensions/inkex/deprecated/main.py create mode 100644 share/extensions/inkex/deprecated/meta.py create mode 100644 share/extensions/inkex/elements/__init__.py create mode 100644 share/extensions/inkex/elements/_base.py create mode 100644 share/extensions/inkex/elements/_filters.py create mode 100644 share/extensions/inkex/elements/_groups.py create mode 100644 share/extensions/inkex/elements/_image.py create mode 100644 share/extensions/inkex/elements/_meta.py create mode 100644 share/extensions/inkex/elements/_parser.py create mode 100644 share/extensions/inkex/elements/_polygons.py create mode 100644 share/extensions/inkex/elements/_selected.py create mode 100644 share/extensions/inkex/elements/_svg.py create mode 100644 share/extensions/inkex/elements/_text.py create mode 100644 share/extensions/inkex/elements/_use.py create mode 100644 share/extensions/inkex/elements/_utils.py create mode 100644 share/extensions/inkex/extensions.py create mode 100644 share/extensions/inkex/gui/README.md create mode 100644 share/extensions/inkex/gui/__init__.py create mode 100644 share/extensions/inkex/gui/app.py create mode 100644 share/extensions/inkex/gui/asyncme.py create mode 100644 share/extensions/inkex/gui/listview.py create mode 100644 share/extensions/inkex/gui/pixmap.py create mode 100644 share/extensions/inkex/gui/tester.py create mode 100644 share/extensions/inkex/gui/window.py create mode 100644 share/extensions/inkex/interfaces/IElement.py create mode 100644 share/extensions/inkex/interfaces/__init__.py create mode 100644 share/extensions/inkex/inx.py create mode 100644 share/extensions/inkex/localization.py create mode 100644 share/extensions/inkex/paths.py create mode 100644 share/extensions/inkex/ports.py create mode 100644 share/extensions/inkex/properties.py create mode 100644 share/extensions/inkex/styles.py create mode 100644 share/extensions/inkex/tester/__init__.py create mode 100644 share/extensions/inkex/tester/decorators.py create mode 100644 share/extensions/inkex/tester/filters.py create mode 100644 share/extensions/inkex/tester/inx.py create mode 100644 share/extensions/inkex/tester/mock.py create mode 100644 share/extensions/inkex/tester/svg.py create mode 100644 share/extensions/inkex/tester/word.py create mode 100644 share/extensions/inkex/tester/xmldiff.py create mode 100644 share/extensions/inkex/transforms.py create mode 100644 share/extensions/inkex/turtle.py create mode 100644 share/extensions/inkex/tween.py create mode 100644 share/extensions/inkex/units.py create mode 100644 share/extensions/inkex/utils.py create mode 100644 share/extensions/inkscape.extension.rng create mode 100644 share/extensions/inkscape.extension.schema create mode 100644 share/extensions/inkscape_follow_link.inx create mode 100755 share/extensions/inkscape_follow_link.py create mode 100644 share/extensions/inkweb.js create mode 100755 share/extensions/inkwebeffect.py create mode 100644 share/extensions/interp.inx create mode 100755 share/extensions/interp.py create mode 100644 share/extensions/interp_att_g.inx create mode 100755 share/extensions/interp_att_g.py create mode 100644 share/extensions/jessyInk.js create mode 100644 share/extensions/jessyInk_core_mouseHandler_noclick.js create mode 100644 share/extensions/jessyInk_core_mouseHandler_zoomControl.js create mode 100644 share/extensions/jessyink_autotexts.inx create mode 100755 share/extensions/jessyink_autotexts.py create mode 100644 share/extensions/jessyink_effects.inx create mode 100755 share/extensions/jessyink_effects.py create mode 100644 share/extensions/jessyink_export.inx create mode 100755 share/extensions/jessyink_export.py create mode 100644 share/extensions/jessyink_install.inx create mode 100755 share/extensions/jessyink_install.py create mode 100644 share/extensions/jessyink_key_bindings.inx create mode 100755 share/extensions/jessyink_key_bindings.py create mode 100644 share/extensions/jessyink_master_slide.inx create mode 100755 share/extensions/jessyink_master_slide.py create mode 100644 share/extensions/jessyink_mouse_handler.inx create mode 100755 share/extensions/jessyink_mouse_handler.py create mode 100644 share/extensions/jessyink_summary.inx create mode 100755 share/extensions/jessyink_summary.py create mode 100644 share/extensions/jessyink_transitions.inx create mode 100755 share/extensions/jessyink_transitions.py create mode 100644 share/extensions/jessyink_uninstall.inx create mode 100755 share/extensions/jessyink_uninstall.py create mode 100644 share/extensions/jessyink_video.inx create mode 100755 share/extensions/jessyink_video.py create mode 100644 share/extensions/jessyink_video.svg create mode 100644 share/extensions/jessyink_view.inx create mode 100755 share/extensions/jessyink_view.py create mode 100644 share/extensions/jitternodes.inx create mode 100755 share/extensions/jitternodes.py create mode 100644 share/extensions/layer2png.inx create mode 100755 share/extensions/layer2png.py create mode 100644 share/extensions/layers2svgfont.inx create mode 100755 share/extensions/layers2svgfont.py create mode 100644 share/extensions/layout_nup.inx create mode 100755 share/extensions/layout_nup.py create mode 100644 share/extensions/lindenmayer.inx create mode 100755 share/extensions/lindenmayer.py create mode 100644 share/extensions/lorem_ipsum.inx create mode 100755 share/extensions/lorem_ipsum.py create mode 100644 share/extensions/markers_strokepaint.inx create mode 100755 share/extensions/markers_strokepaint.py create mode 100644 share/extensions/measure.inx create mode 100755 share/extensions/measure.py create mode 100644 share/extensions/media_zip.inx create mode 100755 share/extensions/media_zip.py create mode 100644 share/extensions/merge_styles.inx create mode 100755 share/extensions/merge_styles.py create mode 100644 share/extensions/motion.inx create mode 100755 share/extensions/motion.py create mode 100644 share/extensions/new_glyph_layer.inx create mode 100755 share/extensions/new_glyph_layer.py create mode 100644 share/extensions/next_glyph_layer.inx create mode 100755 share/extensions/next_glyph_layer.py create mode 100644 share/extensions/nicechart.inx create mode 100755 share/extensions/nicechart.py create mode 100644 share/extensions/other/clipart/LICENSE.txt create mode 100644 share/extensions/other/clipart/MANIFEST.in create mode 100644 share/extensions/other/clipart/README.md create mode 100644 share/extensions/other/clipart/import_sources.py create mode 100644 share/extensions/other/clipart/import_web_image.inx create mode 100755 share/extensions/other/clipart/import_web_image.py create mode 100644 share/extensions/other/clipart/import_web_image.svg create mode 100644 share/extensions/other/clipart/import_web_image.ui create mode 100755 share/extensions/other/clipart/import_web_image_cli.py create mode 100644 share/extensions/other/clipart/licenses/asl.svg create mode 100644 share/extensions/other/clipart/licenses/bsd.svg create mode 100644 share/extensions/other/clipart/licenses/cc-by-nc-sa.svg create mode 100644 share/extensions/other/clipart/licenses/cc-by-nc.svg create mode 100644 share/extensions/other/clipart/licenses/cc-by-nd.svg create mode 100644 share/extensions/other/clipart/licenses/cc-by-sa.png create mode 100644 share/extensions/other/clipart/licenses/cc-by-sa.svg create mode 100644 share/extensions/other/clipart/licenses/cc-by.svg create mode 100644 share/extensions/other/clipart/licenses/cc0.svg create mode 100644 share/extensions/other/clipart/licenses/gpl.svg create mode 100644 share/extensions/other/clipart/licenses/mit.svg create mode 100644 share/extensions/other/clipart/licenses/perm-by.svg create mode 100644 share/extensions/other/clipart/licenses/perm-nc.svg create mode 100644 share/extensions/other/clipart/licenses/perm-nd.svg create mode 100644 share/extensions/other/clipart/licenses/perm-ne.svg create mode 100644 share/extensions/other/clipart/licenses/perm-notice.svg create mode 100644 share/extensions/other/clipart/licenses/perm-pd.svg create mode 100644 share/extensions/other/clipart/licenses/perm-sa.svg create mode 100644 share/extensions/other/clipart/licenses/unknown.svg create mode 100644 share/extensions/other/clipart/pyproject.toml create mode 100644 share/extensions/other/clipart/sources/bioicons.py create mode 100644 share/extensions/other/clipart/sources/bioicons.svg create mode 100644 share/extensions/other/clipart/sources/inkscape-web.py create mode 100644 share/extensions/other/clipart/sources/inkscape-web.svg create mode 100644 share/extensions/other/clipart/sources/ocal.py create mode 100644 share/extensions/other/clipart/sources/ocal.svg create mode 100644 share/extensions/other/clipart/sources/reactome.py create mode 100644 share/extensions/other/clipart/sources/reactome.svg create mode 100644 share/extensions/other/clipart/sources/wikimedia.py create mode 100644 share/extensions/other/clipart/sources/wikimedia.svg create mode 100644 share/extensions/other/gcodetools/.darglint create mode 100644 share/extensions/other/gcodetools/.pylintrc create mode 100644 share/extensions/other/gcodetools/LICENSE.txt create mode 100644 share/extensions/other/gcodetools/MANIFEST.in create mode 100644 share/extensions/other/gcodetools/README.md create mode 100644 share/extensions/other/gcodetools/TESTING.md create mode 100755 share/extensions/other/gcodetools/gcodetools.py create mode 100644 share/extensions/other/gcodetools/gcodetools_about.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_area.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_dxf_points.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_engraving.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_graffiti.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_lathe.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_orientation_points.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx create mode 100644 share/extensions/other/gcodetools/gcodetools_tools_library.inx create mode 100755 share/extensions/other/gcodetools/genpofiles.sh create mode 100644 share/extensions/other/gcodetools/setup.cfg create mode 100644 share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out create mode 100644 share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out create mode 100644 share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out create mode 100644 share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out create mode 100644 share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg create mode 100644 share/extensions/other/gcodetools/tests/data/svg/shapes.svg create mode 100644 share/extensions/other/gcodetools/tests/dev_requirements.txt create mode 100644 share/extensions/other/gcodetools/tests/test_gcodetools.py create mode 100644 share/extensions/other/gcodetools/tests/test_inkex_inx.py create mode 100644 share/extensions/other/gcodetools/tox.ini create mode 100644 share/extensions/other/inkman/MANIFEST.in create mode 100644 share/extensions/other/inkman/inkman/__init__.py create mode 100644 share/extensions/other/inkman/inkman/archive.py create mode 100644 share/extensions/other/inkman/inkman/backfoot.py create mode 100644 share/extensions/other/inkman/inkman/data/__init__.py create mode 100644 share/extensions/other/inkman/inkman/data/gui.ui create mode 100644 share/extensions/other/inkman/inkman/data/info.ui create mode 100644 share/extensions/other/inkman/inkman/data/package.json create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/__init__.py create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/default.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/docs.png create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/icon.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/not-found.png create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg create mode 100644 share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg create mode 100644 share/extensions/other/inkman/inkman/factory.py create mode 100644 share/extensions/other/inkman/inkman/gui/__init__.py create mode 100644 share/extensions/other/inkman/inkman/gui/info.py create mode 100644 share/extensions/other/inkman/inkman/gui/main.py create mode 100644 share/extensions/other/inkman/inkman/package.py create mode 100644 share/extensions/other/inkman/inkman/remote.py create mode 100644 share/extensions/other/inkman/inkman/target.py create mode 100644 share/extensions/other/inkman/inkman/targets.py create mode 100644 share/extensions/other/inkman/inkman/utils.py create mode 100644 share/extensions/other/inkman/manage_extensions.inx create mode 100755 share/extensions/other/inkman/manage_extensions.py create mode 100644 share/extensions/other/inkman/pyproject.toml create mode 100644 share/extensions/output_scour.inx create mode 100755 share/extensions/output_scour.py create mode 100644 share/extensions/output_scour.svg create mode 100644 share/extensions/param_curves.inx create mode 100755 share/extensions/param_curves.py create mode 100644 share/extensions/path_envelope.inx create mode 100755 share/extensions/path_envelope.py create mode 100644 share/extensions/path_mesh_m2p.inx create mode 100755 share/extensions/path_mesh_m2p.py create mode 100644 share/extensions/path_mesh_p2m.inx create mode 100755 share/extensions/path_mesh_p2m.py create mode 100644 share/extensions/path_number_nodes.inx create mode 100755 share/extensions/path_number_nodes.py create mode 100644 share/extensions/path_to_absolute.inx create mode 100755 share/extensions/path_to_absolute.py create mode 100644 share/extensions/pathalongpath.inx create mode 100755 share/extensions/pathalongpath.py create mode 100755 share/extensions/pathmodifier.py create mode 100644 share/extensions/pathscatter.inx create mode 100755 share/extensions/pathscatter.py create mode 100644 share/extensions/pdflatex.inx create mode 100755 share/extensions/pdflatex.py create mode 100644 share/extensions/perfectboundcover.inx create mode 100755 share/extensions/perfectboundcover.py create mode 100644 share/extensions/perspective.inx create mode 100755 share/extensions/perspective.py create mode 100644 share/extensions/pixelsnap.inx create mode 100755 share/extensions/pixelsnap.py create mode 100644 share/extensions/plotter.inx create mode 100755 share/extensions/plotter.py create mode 100644 share/extensions/poetry.lock create mode 100644 share/extensions/polyhedron_3d.inx create mode 100755 share/extensions/polyhedron_3d.py create mode 100644 share/extensions/prepare_file_save_as.inx create mode 100755 share/extensions/prepare_file_save_as.py create mode 100644 share/extensions/previous_glyph_layer.inx create mode 100755 share/extensions/previous_glyph_layer.py create mode 100644 share/extensions/print_win32_vector.inx create mode 100755 share/extensions/print_win32_vector.py create mode 100644 share/extensions/printing_marks.inx create mode 100755 share/extensions/printing_marks.py create mode 100644 share/extensions/ps_input.inx create mode 100755 share/extensions/ps_input.py create mode 100644 share/extensions/pyproject.toml create mode 100644 share/extensions/raster_output_jpg.inx create mode 100644 share/extensions/raster_output_jpg.py create mode 100644 share/extensions/raster_output_jpg.svg create mode 100644 share/extensions/raster_output_png.inx create mode 100755 share/extensions/raster_output_png.py create mode 100644 share/extensions/raster_output_tiff.inx create mode 100755 share/extensions/raster_output_tiff.py create mode 100644 share/extensions/raster_output_webp.inx create mode 100755 share/extensions/raster_output_webp.py create mode 100644 share/extensions/render_alphabetsoup.inx create mode 100755 share/extensions/render_alphabetsoup.py create mode 100755 share/extensions/render_alphabetsoup_config.py create mode 100644 share/extensions/render_barcode.inx create mode 100755 share/extensions/render_barcode.py create mode 100644 share/extensions/render_barcode_datamatrix.inx create mode 100755 share/extensions/render_barcode_datamatrix.py create mode 100644 share/extensions/render_barcode_qrcode.inx create mode 100755 share/extensions/render_barcode_qrcode.py create mode 100644 share/extensions/render_gear_rack.inx create mode 100755 share/extensions/render_gear_rack.py create mode 100644 share/extensions/render_gears.inx create mode 100755 share/extensions/render_gears.py create mode 100644 share/extensions/replace_font.inx create mode 100755 share/extensions/replace_font.py create mode 100644 share/extensions/restack.inx create mode 100755 share/extensions/restack.py create mode 100644 share/extensions/rtree.inx create mode 100755 share/extensions/rtree.py create mode 100644 share/extensions/rubberstretch.inx create mode 100755 share/extensions/rubberstretch.py create mode 100644 share/extensions/scribus_export_pdf.inx create mode 100644 share/extensions/scribus_export_pdf.py create mode 100644 share/extensions/seamless_pattern.svg create mode 100644 share/extensions/setup_typography_canvas.inx create mode 100755 share/extensions/setup_typography_canvas.py create mode 100644 share/extensions/spirograph.inx create mode 100755 share/extensions/spirograph.py create mode 100644 share/extensions/straightseg.inx create mode 100755 share/extensions/straightseg.py create mode 100644 share/extensions/svg2fxg.inx create mode 100644 share/extensions/svg2fxg.xsl create mode 100644 share/extensions/svg2xaml.inx create mode 100644 share/extensions/svg2xaml.xsl create mode 100644 share/extensions/svg_fonts/EMSAllure.svg create mode 100644 share/extensions/svg_fonts/EMSElfin.svg create mode 100644 share/extensions/svg_fonts/EMSFelix.svg create mode 100644 share/extensions/svg_fonts/EMSNixish.svg create mode 100644 share/extensions/svg_fonts/EMSNixishItalic.svg create mode 100644 share/extensions/svg_fonts/EMSOsmotron.svg create mode 100644 share/extensions/svg_fonts/EMSReadability.svg create mode 100644 share/extensions/svg_fonts/EMSReadabilityItalic.svg create mode 100644 share/extensions/svg_fonts/EMSTech.svg create mode 100644 share/extensions/svg_fonts/HersheyGothEnglish.svg create mode 100644 share/extensions/svg_fonts/HersheySans1.svg create mode 100644 share/extensions/svg_fonts/HersheySansMed.svg create mode 100644 share/extensions/svg_fonts/HersheyScript1.svg create mode 100644 share/extensions/svg_fonts/HersheyScriptMed.svg create mode 100644 share/extensions/svg_fonts/HersheySerifBold.svg create mode 100644 share/extensions/svg_fonts/HersheySerifBoldItalic.svg create mode 100644 share/extensions/svg_fonts/HersheySerifMed.svg create mode 100644 share/extensions/svg_fonts/HersheySerifMedItalic.svg create mode 100644 share/extensions/svg_fonts/OFL.txt create mode 100644 share/extensions/svgcalendar.inx create mode 100755 share/extensions/svgcalendar.py create mode 100644 share/extensions/svgfont2layers.inx create mode 100755 share/extensions/svgfont2layers.py create mode 100755 share/extensions/synfig_fileformat.py create mode 100644 share/extensions/synfig_output.inx create mode 100755 share/extensions/synfig_output.py create mode 100755 share/extensions/synfig_prepare.py create mode 100644 share/extensions/tar_layers.inx create mode 100755 share/extensions/tar_layers.py create mode 100755 share/extensions/template.py create mode 100644 share/extensions/template_business_card.inx create mode 100644 share/extensions/template_desktop.inx create mode 100644 share/extensions/template_dvd_cover.inx create mode 100755 share/extensions/template_dvd_cover.py create mode 100644 share/extensions/template_envelope.inx create mode 100644 share/extensions/template_generic.inx create mode 100644 share/extensions/template_icon.inx create mode 100644 share/extensions/template_page.inx create mode 100644 share/extensions/template_seamless_pattern.inx create mode 100755 share/extensions/template_seamless_pattern.py create mode 100644 share/extensions/template_video.inx create mode 100644 share/extensions/tests/README.md create mode 100644 share/extensions/tests/__init__.py create mode 100755 share/extensions/tests/add_pylint.py create mode 100644 share/extensions/tests/data/README.md create mode 100644 share/extensions/tests/data/batches/barcodes.dat create mode 100644 share/extensions/tests/data/cmd/fig2dev/5d879c5bf2edd4bc478d8bef487538b9.msg create mode 100644 share/extensions/tests/data/cmd/gimp/a8418e80d6e849cc2e91b1baecbfada4.msg create mode 100644 share/extensions/tests/data/cmd/gimp/ba387a2bf0dfa5d22b061bfbe6fae05b.msg create mode 100644 share/extensions/tests/data/cmd/gswin64c/488450070287cd66d418d312b70b4285.msg create mode 100644 share/extensions/tests/data/cmd/gswin64c/67ad522b1b2203d1e9355c8bcb6bacfc.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/03dd4e9c9ee257c7ae161057ebe7c8a3.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/054966b8da855f76de0c1c5c2615c696.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/0ac64d7c051206284e72bf3e0800186d.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/106011cd22941d59371660c2b4abf75c.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/12146d0ed761a6686175edea7c8df347.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/1b0252977bd9eafe0af2686834decd6e.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/1c734cd0171b9097039996e1bd63ed6f.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/1f50fa6d71e2543dd18dfc807fe56018.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/21e5197995b5aa619151b61ebee79f23.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/2911a62f9cfb6cf1e950992909bf7efb.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/2aee6b61724952541d5114e64953ae32.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/37d9cfceb38aade8eda7ad77e4ad0c29.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/4b7027944d0833efa65b5f203a16a5d0.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/51125b32a740b8441210140690d55f8e.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/586740f52b3a497fe4ba77501ad443f4.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/67e526c4c1e53207e5e46274e8cdfcc0.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/683466390d1961f2c66be46d75893e9c.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/6bb74fec5efd21cdad5bc4e0bb7b7b40.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/7b45b58536327cfdced28568323b9f2c.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/7c51bb494fcde6ed09463674eed1e75f.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/7e16d346b278485f0e308b7c8eda301d.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/7f8bea1476711ae5f57b9d30111ec50b.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/88e23ddddb7b44e469a8309d48b71594.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/8d81a6ce40b41366bc5784c8b8e3f3e3.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/9216316249e241e47bf118e187386687.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/925a03cfc32f34622997616ca335c846.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/96e4049adf5290ee08bfbcd580bd8dd1.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/994e3f169976a1af54f6590723d399ee.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/9f18b1246e864e6f3945f8cd64d6ca14.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/a274e3a1c2d893233fa49b8ad9850098.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/b493ad11b50db40a61c857109f083621.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/bf3e6cfcbb81940d4f7d667750681b0c.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/c1bf37c2aa47000fc9941d96b415218c.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/d475a74656cd1f8ba68e095b0ec7c469.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/da3b4e4db182a123e61e1317b2e4578b.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/ee1fdaa387bcb73ee6f7a2359fa9bd62.msg create mode 100644 share/extensions/tests/data/cmd/inkscape/fbabf7cf387f29c12ae11a51af0a9926.msg create mode 100644 share/extensions/tests/data/cmd/pdflatex/6cb19641894666183e4e3e0dbf0d0098.msg create mode 100644 share/extensions/tests/data/cmd/pdflatex/93c25fa37a5c8216644b4392a3d3654e.msg create mode 100644 share/extensions/tests/data/cmd/pdflatex/acb704059fd20b4a9a5c69387a391c7d.msg create mode 100644 share/extensions/tests/data/cmd/pdflatex/b78a310017b7056b187bd023af227d1e.msg create mode 100644 share/extensions/tests/data/cmd/pdflatex/fa0bf1f8c5a5eafc88832c60950b0a40.msg create mode 100644 share/extensions/tests/data/cmd/ps2pdf/754c0d01b6fab11719df7fe755bd3be8.msg create mode 100644 share/extensions/tests/data/cmd/ps2pdf/82b68f6250bfc65d80157a71522c62fb.msg create mode 100644 share/extensions/tests/data/cmd/scribus/cbaa8e934937d1d6b0355b525b5351e5.msg create mode 100644 share/extensions/tests/data/cmd/scribus/e1f8033066a1e79d574f64111d5b92af.msg create mode 100644 share/extensions/tests/data/io/CADTextHeight.dxf create mode 100644 share/extensions/tests/data/io/PAGE_001.DHW create mode 100644 share/extensions/tests/data/io/PGLT_161.DHW create mode 100644 share/extensions/tests/data/io/PGLT_162.DHW create mode 100644 share/extensions/tests/data/io/PGLT_163.DHW create mode 100644 share/extensions/tests/data/io/color.dxf create mode 100644 share/extensions/tests/data/io/dxf_multiple_inserts.dxf create mode 100644 share/extensions/tests/data/io/dxf_polylines.dxf create mode 100644 share/extensions/tests/data/io/dxf_with_arc.dxf create mode 100644 share/extensions/tests/data/io/nicechart_01.csv create mode 100644 share/extensions/tests/data/io/no_block_section.dxf create mode 100644 share/extensions/tests/data/io/test.eps create mode 100644 share/extensions/tests/data/io/test.fig create mode 100644 share/extensions/tests/data/io/test.hpgl create mode 100644 share/extensions/tests/data/io/test.ps create mode 100644 share/extensions/tests/data/io/test2_r12.dxf create mode 100644 share/extensions/tests/data/io/test2_r13.dxf create mode 100644 share/extensions/tests/data/io/test2_r14.dxf create mode 100644 share/extensions/tests/data/io/test_extrude.dxf create mode 100644 share/extensions/tests/data/io/test_r12.dxf create mode 100644 share/extensions/tests/data/io/test_r14.dxf create mode 100644 share/extensions/tests/data/refs/addnodes.out create mode 100644 share/extensions/tests/data/refs/addnodes__--id__p1__--id__r3__--max__2__0.out create mode 100644 share/extensions/tests/data/refs/addnodes__--id__rect723__--id__rect723-5__--id__path747__--id__path1080__--id__path1115__--method__bynum__--segments__3.out create mode 100644 share/extensions/tests/data/refs/color_randomize__-y__0__-t__0__-m__0__-o__100__--id__layer_group_rect_uu2__--id__layer_group_path__--id__root_rect_uu.out create mode 100644 share/extensions/tests/data/refs/color_randomize__-y__50__-t__50__-m__50__-o__100__--id__r1__--id__r2__--id__r3__--id__r4__--id__r5__--id__r6.out create mode 100644 share/extensions/tests/data/refs/color_replace__--id__rect184.out create mode 100644 share/extensions/tests/data/refs/color_replace__--id__rect184__--id__rect184-8.out create mode 100644 share/extensions/tests/data/refs/convert2dashes.out create mode 100644 share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash__svg.out create mode 100644 share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash_zerolength__svg.out create mode 100644 share/extensions/tests/data/refs/dhw_input__PAGE_001__DHW.out create mode 100644 share/extensions/tests/data/refs/dhw_input__PGLT_161__DHW.out create mode 100644 share/extensions/tests/data/refs/dhw_input__PGLT_162__DHW.out create mode 100644 share/extensions/tests/data/refs/dhw_input__PGLT_163__DHW.out create mode 100644 share/extensions/tests/data/refs/dimension__--id__circle1.out create mode 100644 share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--type__visual__--xoffset__100__0__--yoffset__100__0.out create mode 100644 share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--xoffset__100__0__--yoffset__100__0.out create mode 100644 share/extensions/tests/data/refs/dm2svg.out create mode 100644 share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_m_in__svg.out create mode 100644 share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_mm_in__svg.out create mode 100644 share/extensions/tests/data/refs/doc_ai_convert__shapes__svg.out create mode 100644 share/extensions/tests/data/refs/docinfo__guides__svg.out create mode 100644 share/extensions/tests/data/refs/docinfo__three_pages_and_two_grids__svg.out create mode 100644 share/extensions/tests/data/refs/dpiswitcher.out create mode 100644 share/extensions/tests/data/refs/dpiswitcher__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/dpiswitcher__--switcher__0.out create mode 100644 share/extensions/tests/data/refs/dpiswitcher__--switcher__1.out create mode 100644 share/extensions/tests/data/refs/draw_from_triangle__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/dxf12_outlines__clips_and_masks__svg.out create mode 100644 share/extensions/tests/data/refs/dxf12_outlines__dxf_nested_transforms__svg.out create mode 100644 share/extensions/tests/data/refs/dxf12_outlines__preserved-transforms__svg.out create mode 100644 share/extensions/tests/data/refs/dxf12_outlines__scale_not_unity__svg.out create mode 100644 share/extensions/tests/data/refs/dxf12_outlines__shapes__svg.out create mode 100644 share/extensions/tests/data/refs/dxf_input__--textscale__1__411__CADTextHeight__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__CADTextHeight__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__color__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__dxf_multiple_inserts__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__dxf_polylines__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__dxf_with_arc__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__no_block_section__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test2_r12__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test2_r13__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test2_r14__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test_extrude__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test_r12__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_input__test_r14__dxf.out create mode 100644 share/extensions/tests/data/refs/dxf_outlines.out create mode 100644 share/extensions/tests/data/refs/dxf_outlines__--POLY__true.out create mode 100644 share/extensions/tests/data/refs/dxf_outlines__--ROBO__true.out create mode 100644 share/extensions/tests/data/refs/dxf_outlines__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/edge3d__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/export_gimp_palette.out create mode 100644 share/extensions/tests/data/refs/export_gimp_palette__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__c1__--id__c2.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__polygons.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__snug.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p1__--id__p2.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__lines.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__snug.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__lines.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__polygons.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__snug.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__r1__--id__r2.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-m__snug.out create mode 100644 share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-s__False.out create mode 100644 share/extensions/tests/data/refs/fig_input.out create mode 100644 share/extensions/tests/data/refs/flatten.out create mode 100644 share/extensions/tests/data/refs/flatten__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/foldablebox__--proportion__0__5__--guide__true__--unit__cm.out create mode 100644 share/extensions/tests/data/refs/foldablebox__--width__20__--height__20__--depth__2__2__--unit__cm.out create mode 100644 share/extensions/tests/data/refs/fractalize__--id__p1__--id__p2.out create mode 100644 share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_absolute__20__--fill_color____AAA__--stroke_color____F00__--z_position__split.out create mode 100644 share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out create mode 100644 share/extensions/tests/data/refs/frame__--id__t3__--type__rect__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out create mode 100644 share/extensions/tests/data/refs/frame__--id__u1__--fill_color____AAA__--stroke_color____F00__--clip__True.out create mode 100644 share/extensions/tests/data/refs/frame__663c52a8114abe50f0559d9ccefab2e9.out create mode 100644 share/extensions/tests/data/refs/funcplot__--id__p1__--id__r3__--times2pi__True__--ybottom__-1__0__--drawaxis__True.out create mode 100644 share/extensions/tests/data/refs/generate_voronoi__--id__r3__--id__p1.out create mode 100644 share/extensions/tests/data/refs/gimp_xcf.out create mode 100644 share/extensions/tests/data/refs/gimp_xcf__-d__true__-r__true.out create mode 100644 share/extensions/tests/data/refs/grid_cartesian__154bd7ce1662209647ba2825e6d83cbc.out create mode 100644 share/extensions/tests/data/refs/grid_cartesian__841ec156c192e3f468b6774927a90789.out create mode 100644 share/extensions/tests/data/refs/grid_isometric__--dx__10__0__--subdivs_th__1__--subsubdivs_th__0__3.out create mode 100644 share/extensions/tests/data/refs/grid_polar__--a_subdivs_cent__1__--a_labels__deg.out create mode 100644 share/extensions/tests/data/refs/grid_polar__--id__p1__--id__r3__--a_subdivs_cent__1__--a_labels__deg.out create mode 100644 share/extensions/tests/data/refs/guides_creator.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__False__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__True__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_alternating_right.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_right__--vert__3__--horz__2.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__True__--margins_preset__book_alternating_left.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__custom__--vertical_guides__4__--horizontal_guides__5.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__golden.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--vertical_guides__4__--horizontal_guides__3__--pages__1____3-7__12.out create mode 100644 share/extensions/tests/data/refs/guides_creator__--vertical_guides__6__--horizontal_guides__8.out create mode 100644 share/extensions/tests/data/refs/guides_creator__0cec5b2a62929d8e2c1469e6e5047e77.out create mode 100644 share/extensions/tests/data/refs/guides_creator__19bbe6630a0a22a9d7a6a65b25eb1c9f.out create mode 100644 share/extensions/tests/data/refs/guides_creator__251d15df598c899ffbdc546ced9e2faa.out create mode 100644 share/extensions/tests/data/refs/guides_creator__3b35068c24255b2144616d98c2a077bd.out create mode 100644 share/extensions/tests/data/refs/guides_creator__8f473fd113caab10b556f9cfe804e05e.out create mode 100644 share/extensions/tests/data/refs/guides_creator__92c07724de24b2568187779e17d89f83.out create mode 100644 share/extensions/tests/data/refs/guides_creator__ca9cfba4b80367070f0d70d13c501131.out create mode 100644 share/extensions/tests/data/refs/guillotine__--ignore__true__--directory__TMP_DIR__img__.out create mode 100644 share/extensions/tests/data/refs/guillotine__--image__f____oo__--directory__TMP_DIR__img__.out create mode 100644 share/extensions/tests/data/refs/guillotine__--image__output__--directory__TMP_DIR__img__.out create mode 100644 share/extensions/tests/data/refs/handles__--id__curve__--id__quad.out create mode 100644 share/extensions/tests/data/refs/hershey.out create mode 100755 share/extensions/tests/data/refs/hershey_encoding.out create mode 100755 share/extensions/tests/data/refs/hershey_fonttable.out create mode 100755 share/extensions/tests/data/refs/hershey_glyphtable.out create mode 100755 share/extensions/tests/data/refs/hershey_loadfont.out create mode 100755 share/extensions/tests/data/refs/hershey_partialselection.out create mode 100755 share/extensions/tests/data/refs/hershey_preservetext.out create mode 100644 share/extensions/tests/data/refs/hpgl_input.out create mode 100644 share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__hpgl_multipen__svg.out create mode 100644 share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__shapes__svg.out create mode 100644 share/extensions/tests/data/refs/image_attributes.out create mode 100644 share/extensions/tests/data/refs/image_attributes__--id__embeded_image01__--image_rendering__optimizeSpeed__--tab____tab_image_rendering__.out create mode 100644 share/extensions/tests/data/refs/image_attributes__--id__image174__--aspect_ratio__xMinYMin__--tab____tab_aspect_ratio__.out create mode 100644 share/extensions/tests/data/refs/image_embed.out create mode 100644 share/extensions/tests/data/refs/image_embed__--id__image174__--selectedonly__True.out create mode 100644 share/extensions/tests/data/refs/image_extract__--selectedonly__False__--filepath__TMP_DIR__.out create mode 100644 share/extensions/tests/data/refs/image_extract__--selectedonly__True__--id__embeded_image01__--filepath__TMP_DIR__.out create mode 100644 share/extensions/tests/data/refs/ink2canvas.out create mode 100644 share/extensions/tests/data/refs/ink2canvas__--id__alpha.out create mode 100644 share/extensions/tests/data/refs/ink2canvas__--id__path31.out create mode 100644 share/extensions/tests/data/refs/ink2canvas__--id__rect3898.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__color_svg.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__r1.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__r1__--id__r2.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__r2.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__r3.out create mode 100644 share/extensions/tests/data/refs/inkex_extensions_color__--id__r4.out create mode 100644 share/extensions/tests/data/refs/inkscape_follow_link.out create mode 100644 share/extensions/tests/data/refs/inkscape_follow_link__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/interp__3ed855778ec06e18dc5f0d8329e9d085.out create mode 100644 share/extensions/tests/data/refs/interp__bf1a5fd7b7c87a9e06cf0b9659d389ed.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__c1__--id__c2__--id__c3__--att__style__fill.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__other__--att-other__width__--start-val__5__--end-val__10__--att-other-type__ValueInterpolator.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____050505__--end-val____000000.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____181818__--end-val____000000.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__scale__--start-val__0__2__--end-val__0__9.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__trans-x__--start-val__0__--end-val__20.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__width__--start-val__0__02__--end-val__0__1__--unit__mm.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__--id__layer1__--att__style__fill.out create mode 100644 share/extensions/tests/data/refs/interp_att_g__e692b471578dc63d4bf1ba375b8b650c.out create mode 100644 share/extensions/tests/data/refs/jessyink_autotexts__--autoText__slideTitle__--id__t1.out create mode 100644 share/extensions/tests/data/refs/jessyink_effects__--id__p1__--effectIn__fade__--effectOut__pop__--effectOutOrder__2.out create mode 100644 share/extensions/tests/data/refs/jessyink_effects__--id__p1__--id__r3__--effectOutOrder__2.out create mode 100644 share/extensions/tests/data/refs/jessyink_export__--resolution__1__--type__png.out create mode 100644 share/extensions/tests/data/refs/jessyink_install.out create mode 100644 share/extensions/tests/data/refs/jessyink_install__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__SPACE__--drawing_undo__ENTER__--index_nextPage__LEFT.out create mode 100644 share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__a__--drawing_undo__b__--index_nextPage__c.out create mode 100644 share/extensions/tests/data/refs/jessyink_master_slide.out create mode 100644 share/extensions/tests/data/refs/jessyink_master_slide__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__default.out create mode 100644 share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__draggingZoom.out create mode 100644 share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__noclick.out create mode 100644 share/extensions/tests/data/refs/jessyink_summary.out create mode 100644 share/extensions/tests/data/refs/jessyink_transitions__--layerName__Slide2.out create mode 100644 share/extensions/tests/data/refs/jessyink_uninstall.out create mode 100644 share/extensions/tests/data/refs/jessyink_video.out create mode 100644 share/extensions/tests/data/refs/jessyink_view__--id__r3__--viewOrder__1.out create mode 100644 share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__gaussian__--end__false__--ctrl__true.out create mode 100644 share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__lognorm__--radiusx__100__--ctrl__true.out create mode 100644 share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__pareto__--radiusy__100__--ctrl__true.out create mode 100644 share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__uniform__--ctrl__false.out create mode 100644 share/extensions/tests/data/refs/layer2png.out create mode 100644 share/extensions/tests/data/refs/layer2png__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/layers2svgfont__font_layers__svg.out create mode 100644 share/extensions/tests/data/refs/layers2svgfont__font_layers_apostrophe__svg.out create mode 100644 share/extensions/tests/data/refs/lindenmayer.out create mode 100644 share/extensions/tests/data/refs/lindenmayer__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/lindenmayer__--rules__F__F-E__F__E-F__E__EE__--axiom__F-E-E__--order__3__--langle__120__--rangle__120.out create mode 100644 share/extensions/tests/data/refs/lindenmayer__--rules__F__F__F--F__F__--axiom__F__--order__1__--langle__60__--rangle__60.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum__--id__r1.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum__--id__r1__--svg2__false.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum__--id__t4.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum__--svg2__false.out create mode 100644 share/extensions/tests/data/refs/lorem_ipsum__--svg2__true.out create mode 100644 share/extensions/tests/data/refs/markers_strokepaint__--tab____custom____--id__dimension__--type__stroke.out create mode 100644 share/extensions/tests/data/refs/markers_strokepaint__--tab____object____--id__dimension__--type__stroke.out create mode 100644 share/extensions/tests/data/refs/measure__--id__p1__--id__p2__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_bbox__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_end__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--type__area__--id__p1__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--type__cofm__--id__D__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/measure__--type__cofm__--id__c3__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out create mode 100644 share/extensions/tests/data/refs/merge_styles__--id__c2__--id__c3.out create mode 100644 share/extensions/tests/data/refs/motion__--id__c3__--id__p2.out create mode 100644 share/extensions/tests/data/refs/motion__--magnitude__2__--angle__45__--fillwithstroke__True__--id__path23053__--id__path28636.out create mode 100644 share/extensions/tests/data/refs/new_glyph_layer.out create mode 100644 share/extensions/tests/data/refs/new_glyph_layer__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/next_glyph_layer.out create mode 100644 share/extensions/tests/data/refs/next_glyph_layer__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out create mode 100644 share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__pie__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out create mode 100644 share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__stbar__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out create mode 100644 share/extensions/tests/data/refs/nicechart__3afa80cf55d99e9c0ea691c780458309.out create mode 100644 share/extensions/tests/data/refs/output_scour.out create mode 100644 share/extensions/tests/data/refs/param_curves__--id__p1__--id__r3__-s__8__--isoscale__True__--drawaxis__True.out create mode 100644 share/extensions/tests/data/refs/param_curves__-s__8__--isoscale__True__--drawaxis__True.out create mode 100644 share/extensions/tests/data/refs/path_envelope__--id__obj__--id__envelope.out create mode 100644 share/extensions/tests/data/refs/path_envelope__--id__text__--id__envelope.out create mode 100644 share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__faces.out create mode 100644 share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__gridlines.out create mode 100644 share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__meshpatches.out create mode 100644 share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__outline.out create mode 100644 share/extensions/tests/data/refs/path_mesh_p2m__--id__path1__--id__path9.out create mode 100644 share/extensions/tests/data/refs/path_number_nodes__--id__D.out create mode 100644 share/extensions/tests/data/refs/path_number_nodes__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/path_to_absolute__--id__c1__--id__c2__--id__c3.out create mode 100644 share/extensions/tests/data/refs/path_to_absolute__--id__p1__--id__p2__--id__s1__--id__u1.out create mode 100644 share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect.out create mode 100644 share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect1.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated__--kind__Snake__--id__g3427__--id__path2551.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--id__g4054__--id__path4056.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--vertical__True__--id__g3961__--id__path10007.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Snake__--noffset__5__--space__5__--id__path2408__--id__path2405.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Single__--duplicate__True__--kind__Snake__--id__g5848__--id__path3336.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__path4585__--id__path4608__--id__path4610__--id__path4612.out create mode 100644 share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__text4418__--id__path4412.out create mode 100644 share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__False__--follow__False.out create mode 100644 share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--copymode__copy__--grouppick__True__--pickmode__seq.out create mode 100644 share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--rotate__True__--copymode__clone.out create mode 100644 share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--space__10.out create mode 100644 share/extensions/tests/data/refs/pathscatter__--id__path3990__--id__path3982__--stretch__True__--follow__True__--copymode__copy.out create mode 100644 share/extensions/tests/data/refs/pdflatex__--font_size__15.out create mode 100644 share/extensions/tests/data/refs/pdflatex__--font_size__15__--standalone__False.out create mode 100644 share/extensions/tests/data/refs/pdflatex__--font_size__20__--formule________frac__1____sqrt__5______2______.out create mode 100644 share/extensions/tests/data/refs/pdflatex__--font_size__20__--standalone__False__--formule________frac__1____sqrt__5______2______.out create mode 100644 share/extensions/tests/data/refs/pdflatex__0355ed68ae6ec25166e664512ef53660.out create mode 100644 share/extensions/tests/data/refs/perfectboundcover.out create mode 100644 share/extensions/tests/data/refs/perspective__--id__obj__--id__envelope.out create mode 100644 share/extensions/tests/data/refs/perspective__--id__p1__--id__p2.out create mode 100644 share/extensions/tests/data/refs/perspective__--id__text__--id__envelope.out create mode 100644 share/extensions/tests/data/refs/pixelsnap__--id__p1__--id__r3__--snap_to__bl.out create mode 100644 share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__bl.out create mode 100644 share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__tl.out create mode 100644 share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__DMPL__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out create mode 100644 share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__KNK__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out create mode 100644 share/extensions/tests/data/refs/plotter__--serialPort____test____--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out create mode 100644 share/extensions/tests/data/refs/plt_output.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__methane__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__oct__--r1_ax__z__--r1_ang__45__--th__4__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__x__--r1_ang__45__--r2_ax__y__--r2_ang__45__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__y__--r1_ang__45__--z_sort__cent__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__z__--r1_ang__45__--z_sort__max__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__from_file__--spec_file__great_stel_dodec__obj__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__--show__vtx__--obj__methane__--cw_wound__True.out create mode 100644 share/extensions/tests/data/refs/polyhedron_3d__31c852a9dcfffc92123ff370cba34361.out create mode 100644 share/extensions/tests/data/refs/prepare_file_save_as.out create mode 100644 share/extensions/tests/data/refs/previous_glyph_layer.out create mode 100644 share/extensions/tests/data/refs/previous_glyph_layer__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/print_win32_vector.out create mode 100644 share/extensions/tests/data/refs/print_win32_vector__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/printing_marks.out create mode 100644 share/extensions/tests/data/refs/printing_marks__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/printing_marks__fcb9f72a813c7f3f65cc9dbdb50c294a.out create mode 100644 share/extensions/tests/data/refs/ps_input__test__eps.out create mode 100644 share/extensions/tests/data/refs/ps_input__test__ps.out create mode 100644 share/extensions/tests/data/refs/render_barcode__--type__Code93__--text__3332222.out create mode 100644 share/extensions/tests/data/refs/render_barcode__--type__Ean2__--text__55.out create mode 100644 share/extensions/tests/data/refs/render_barcode__--type__Upce__--text__123456.out create mode 100644 share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__rect8x32__--text__1234Foo.out create mode 100644 share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq10.out create mode 100644 share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq144__--text__HelloTest.out create mode 100644 share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq96__--text__Sunshine.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__0123456789__--typenumber__0__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__Blue__Front__Yard__--typenumber__3__--correctionlevel__1__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__BreadRolls__--typenumber__2__--encoding__utf8__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__ThingOne__--drawtype__symbol__--correctionlevel__2__--symbolid__AirTransportation_Inv__--modulesize__10.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__Waterfall__--typenumber__1__--drawtype__pathpreset__--pathtype__circle__--modulesize__10.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__groupid__--groupid__testid__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__--text__test__--drawtype__selection__--id__r3__--modulesize__10.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__a95852ad07710857e3fadaaa059140e8.out create mode 100644 share/extensions/tests/data/refs/render_barcode_qrcode__e3208cfbf8a72ec55b5335e55f8674db.out create mode 100644 share/extensions/tests/data/refs/render_gear_rack.out create mode 100644 share/extensions/tests/data/refs/render_gear_rack__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/render_gears__--centerdiameter__10__0.out create mode 100644 share/extensions/tests/data/refs/render_gears__--id__p1__--id__r3__--centerdiameter__10__0.out create mode 100644 share/extensions/tests/data/refs/replace_font__--action__find_replace__--fr_find__sans-serif__--fr_replace__monospace.out create mode 100644 share/extensions/tests/data/refs/replace_font__--action__list_only.out create mode 100644 share/extensions/tests/data/refs/restack__--id__g20858__--id__g21085__--id__g20940__--id__g26580__--id__g21081__--id__g20854.out create mode 100644 share/extensions/tests/data/refs/restack__--tab__positional__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out create mode 100644 share/extensions/tests/data/refs/restack__--tab__z_order__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out create mode 100644 share/extensions/tests/data/refs/restack__--tab__z_order__--id__r2__--id__t5__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out create mode 100644 share/extensions/tests/data/refs/restack__--tab__z_order__--id__r3__--id__p1__--id__t5__--id__r2__--direction__tb__--xanchor__m__--yanchor__m.out create mode 100644 share/extensions/tests/data/refs/restack__cde2e552c805941baaf79d0821ec1e63.out create mode 100644 share/extensions/tests/data/refs/rtree__--minimum__4__0.out create mode 100644 share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__0__--curve__50.out create mode 100644 share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__25__--curve__25.out create mode 100644 share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__50__--curve__0.out create mode 100644 share/extensions/tests/data/refs/scribus_export_pdf__--pdf-version__13__--bleed__0.out create mode 100644 share/extensions/tests/data/refs/setup_typography_canvas__empty__svg.out create mode 100644 share/extensions/tests/data/refs/setup_typography_canvas__shapes__svg.out create mode 100644 share/extensions/tests/data/refs/sk1_output.out create mode 100644 share/extensions/tests/data/refs/spirograph__--primaryr__60__0__--secondaryr__100__0.out create mode 100644 share/extensions/tests/data/refs/straightseg.out create mode 100644 share/extensions/tests/data/refs/straightseg__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/svgcalendar__9cc828f60a4a546fd4e0fdf4dd392e96.out create mode 100644 share/extensions/tests/data/refs/svgfont2layers__--count__3.out create mode 100644 share/extensions/tests/data/refs/synfig_output.out create mode 100644 share/extensions/tests/data/refs/tar_layers.out create mode 100644 share/extensions/tests/data/refs/tar_layers__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__horizontal.out create mode 100644 share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__vertical.out create mode 100644 share/extensions/tests/data/refs/template__--size__5mmx15mm__--background__black__--noborder__true.out create mode 100644 share/extensions/tests/data/refs/template__--size__custom__--width__100__--height__100__--unit__in.out create mode 100644 share/extensions/tests/data/refs/template_dvd_cover__-s__10__-b__10.out create mode 100644 share/extensions/tests/data/refs/template_seamless_pattern__--width__100__--height__100.out create mode 100644 share/extensions/tests/data/refs/test_color_list.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__color_svg.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__r1.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__r1__--id__r2.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__r2.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__r3.out create mode 100644 share/extensions/tests/data/refs/test_color_list__--id__r4.out create mode 100644 share/extensions/tests/data/refs/text_braille.out create mode 100644 share/extensions/tests/data/refs/text_extract__--direction__bt__--xanchor__center_x__--yanchor__center_y.out create mode 100644 share/extensions/tests/data/refs/text_extract__--direction__lr__--xanchor__center_x__--yanchor__center_y.out create mode 100644 share/extensions/tests/data/refs/text_extract__--direction__rl__--xanchor__center_x__--yanchor__center_y.out create mode 100644 share/extensions/tests/data/refs/text_extract__--direction__tb__--xanchor__center_x__--yanchor__center_y.out create mode 100644 share/extensions/tests/data/refs/text_flipcase.out create mode 100644 share/extensions/tests/data/refs/text_lowercase.out create mode 100644 share/extensions/tests/data/refs/text_merge.out create mode 100644 share/extensions/tests/data/refs/text_randomcase.out create mode 100644 share/extensions/tests/data/refs/text_sentencecase.out create mode 100644 share/extensions/tests/data/refs/text_split__5478757cb04224bacfa3c641fea954ba.out create mode 100644 share/extensions/tests/data/refs/text_split__74947d6e9e9ee89a80bbec0bfacc6dfb.out create mode 100644 share/extensions/tests/data/refs/text_split__897ab8b3c516acacaf68391a51eb8836.out create mode 100644 share/extensions/tests/data/refs/text_split__ad318803d098b3903561d44825a36ea0.out create mode 100644 share/extensions/tests/data/refs/text_split__c242adcac78228419d3c065a99727bfb.out create mode 100644 share/extensions/tests/data/refs/text_split__d8b155ac58a7424471f416b64f21669f.out create mode 100644 share/extensions/tests/data/refs/text_split__dd77d3cc0134ad62833e05ca73e38896.out create mode 100644 share/extensions/tests/data/refs/text_titlecase.out create mode 100644 share/extensions/tests/data/refs/text_uppercase.out create mode 100644 share/extensions/tests/data/refs/triangle.out create mode 100644 share/extensions/tests/data/refs/triangle__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/ungroup_deep.out create mode 100644 share/extensions/tests/data/refs/ungroup_deep__--id__g13.out create mode 100644 share/extensions/tests/data/refs/ungroup_deep__--id__g1935__--id__g6577__--id__g115.out create mode 100644 share/extensions/tests/data/refs/ungroup_deep__--id__layer2.out create mode 100644 share/extensions/tests/data/refs/voronoi2svg__--id__c1__--id__c2__--id__c3__--id__p1__--id__p2__--id__s1__--diagram-type__Voronoi__--clip-box__Page.out create mode 100644 share/extensions/tests/data/refs/voronoi2svg__--id__r1__--id__r3__--id__c1__--id__c3__--id__s1__--diagram-type__Both__--delaunay-fill-options__delaunay-fill.out create mode 100644 share/extensions/tests/data/refs/voronoi2svg__083b27d59093207e6210e1001eb9d5df.out create mode 100644 share/extensions/tests/data/refs/voronoi2svg__6d561032e7d7e60e607c75e562f677a4.out create mode 100644 share/extensions/tests/data/refs/web_interactive_mockup__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/web_set_att__--id__p1__--id__r3__--att__fill__--val__red.out create mode 100644 share/extensions/tests/data/refs/web_transmit_att__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/webslicer_create_group__--id__slicerect1.out create mode 100644 share/extensions/tests/data/refs/webslicer_create_rect.out create mode 100644 share/extensions/tests/data/refs/webslicer_create_rect__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/webslicer_export__--dir__TMP_DIR.out create mode 100644 share/extensions/tests/data/refs/whirl__--id__p1__--id__r3__--whirl__1__0.out create mode 100644 share/extensions/tests/data/refs/wireframe_sphere.out create mode 100644 share/extensions/tests/data/refs/wireframe_sphere__--id__p1__--id__r3.out create mode 100644 share/extensions/tests/data/refs/wmf_output.out create mode 100644 share/extensions/tests/data/svg/clips_and_masks.svg create mode 100644 share/extensions/tests/data/svg/colors.svg create mode 100644 share/extensions/tests/data/svg/complextransform.test.svg create mode 100644 share/extensions/tests/data/svg/css.svg create mode 100644 share/extensions/tests/data/svg/curves.svg create mode 100644 share/extensions/tests/data/svg/dash.svg create mode 100644 share/extensions/tests/data/svg/dash_zerolength.svg create mode 100644 share/extensions/tests/data/svg/deep-ungroup-complex.svg create mode 100644 share/extensions/tests/data/svg/default-inkscape-SVG.svg create mode 100644 share/extensions/tests/data/svg/default-inkscape-SVG_scoured.svg create mode 100644 share/extensions/tests/data/svg/default-plain-SVG.svg create mode 100644 share/extensions/tests/data/svg/diff.svg create mode 100644 share/extensions/tests/data/svg/doc_ai_conv_m_in.svg create mode 100644 share/extensions/tests/data/svg/doc_ai_conv_mm_in.svg create mode 100644 share/extensions/tests/data/svg/dpiswitcher_96dpi.svg create mode 100644 share/extensions/tests/data/svg/dxf_nested_transforms.svg create mode 100644 share/extensions/tests/data/svg/edge3d.svg create mode 100644 share/extensions/tests/data/svg/ellipse_group_comment.svg create mode 100644 share/extensions/tests/data/svg/embed.svg create mode 100644 share/extensions/tests/data/svg/empty.svg create mode 100644 share/extensions/tests/data/svg/empty_mm.svg create mode 100644 share/extensions/tests/data/svg/empty_multipage.svg create mode 100644 share/extensions/tests/data/svg/extrude.svg create mode 100644 share/extensions/tests/data/svg/font.svg create mode 100644 share/extensions/tests/data/svg/font_layers.svg create mode 100644 share/extensions/tests/data/svg/font_layers_apostrophe.svg create mode 100644 share/extensions/tests/data/svg/gradient_with_mixed_offsets.svg create mode 100644 share/extensions/tests/data/svg/group_interpolate.svg create mode 100644 share/extensions/tests/data/svg/guides.svg create mode 100644 share/extensions/tests/data/svg/guides_millimeter.svg create mode 100755 share/extensions/tests/data/svg/hershey_input.svg create mode 100755 share/extensions/tests/data/svg/hershey_trivial_input.svg create mode 100644 share/extensions/tests/data/svg/hpgl_multipen.svg create mode 100644 share/extensions/tests/data/svg/images.svg create mode 100644 share/extensions/tests/data/svg/images_multiple.svg create mode 100644 share/extensions/tests/data/svg/img/color_overlay_a.png create mode 100644 share/extensions/tests/data/svg/img/color_overlay_b.png create mode 100644 share/extensions/tests/data/svg/img/color_pad_a.png create mode 100644 share/extensions/tests/data/svg/img/color_pad_b.png create mode 100644 share/extensions/tests/data/svg/img/color_pad_c.png create mode 100644 share/extensions/tests/data/svg/img/green.png create mode 100644 share/extensions/tests/data/svg/img/linecap.png create mode 100644 share/extensions/tests/data/svg/img/subfolder/linecap.png create mode 100644 share/extensions/tests/data/svg/inkweb-debug.js create mode 100644 share/extensions/tests/data/svg/inkwebjs-move.svg create mode 100644 share/extensions/tests/data/svg/interp_shapes.svg create mode 100644 share/extensions/tests/data/svg/markers.svg create mode 100644 share/extensions/tests/data/svg/mesh.svg create mode 100644 share/extensions/tests/data/svg/minimal-blank-prepare.svg create mode 100644 share/extensions/tests/data/svg/minimal-blank.svg create mode 100644 share/extensions/tests/data/svg/motion_tests.svg create mode 100644 share/extensions/tests/data/svg/multilayered-test.svg create mode 100644 share/extensions/tests/data/svg/multiple_closed_subpaths.svg create mode 100644 share/extensions/tests/data/svg/paths_open_closed.svg create mode 100644 share/extensions/tests/data/svg/pattern_along_path.svg create mode 100644 share/extensions/tests/data/svg/pattern_along_path_clone_transform.svg create mode 100644 share/extensions/tests/data/svg/perspective.svg create mode 100644 share/extensions/tests/data/svg/perspective_groups.svg create mode 100644 share/extensions/tests/data/svg/pixelsnap_simple.svg create mode 100644 share/extensions/tests/data/svg/preserved-transforms.svg create mode 100644 share/extensions/tests/data/svg/restack_grouped.svg create mode 100644 share/extensions/tests/data/svg/rubber-stretch-test.svg create mode 100644 share/extensions/tests/data/svg/scale_not_unity.svg create mode 100644 share/extensions/tests/data/svg/scatter.svg create mode 100644 share/extensions/tests/data/svg/shapes-clipboard.svg create mode 100644 share/extensions/tests/data/svg/shapes.svg create mode 100644 share/extensions/tests/data/svg/shapes_cmyk.svg create mode 100644 share/extensions/tests/data/svg/simple_patterns.svg create mode 100644 share/extensions/tests/data/svg/simpletransform.test.svg create mode 100644 share/extensions/tests/data/svg/single_box.svg create mode 100644 share/extensions/tests/data/svg/slicer.svg create mode 100644 share/extensions/tests/data/svg/style_inheritance.svg create mode 100755 share/extensions/tests/data/svg/styling-css-04-f.svg create mode 100755 share/extensions/tests/data/svg/styling-inherit-01-b.svg create mode 100644 share/extensions/tests/data/svg/symbol.svg create mode 100644 share/extensions/tests/data/svg/text_on_arc.svg create mode 100644 share/extensions/tests/data/svg/text_types.svg create mode 100644 share/extensions/tests/data/svg/three_pages_and_two_grids.svg create mode 100644 share/extensions/tests/data/svg/transformed-layer.svg create mode 100644 share/extensions/tests/data/svg/with-lpe.svg create mode 100644 share/extensions/tests/data/ui/app-test.ui create mode 100644 share/extensions/tests/data/ui/listing-app.ui create mode 100644 share/extensions/tests/data/ui/window-test.ui create mode 100644 share/extensions/tests/test_addnodes.py create mode 100644 share/extensions/tests/test_color_HSL_adjust.py create mode 100644 share/extensions/tests/test_color_blackandwhite.py create mode 100644 share/extensions/tests/test_color_brighter.py create mode 100644 share/extensions/tests/test_color_custom.py create mode 100644 share/extensions/tests/test_color_darker.py create mode 100644 share/extensions/tests/test_color_desaturate.py create mode 100644 share/extensions/tests/test_color_grayscale.py create mode 100644 share/extensions/tests/test_color_lesshue.py create mode 100644 share/extensions/tests/test_color_lesslight.py create mode 100644 share/extensions/tests/test_color_lesssaturation.py create mode 100644 share/extensions/tests/test_color_list.py create mode 100644 share/extensions/tests/test_color_morehue.py create mode 100644 share/extensions/tests/test_color_morelight.py create mode 100644 share/extensions/tests/test_color_moresaturation.py create mode 100644 share/extensions/tests/test_color_negative.py create mode 100644 share/extensions/tests/test_color_randomize.py create mode 100644 share/extensions/tests/test_color_removeblue.py create mode 100644 share/extensions/tests/test_color_removegreen.py create mode 100644 share/extensions/tests/test_color_removered.py create mode 100644 share/extensions/tests/test_color_replace.py create mode 100644 share/extensions/tests/test_color_rgbbarrel.py create mode 100644 share/extensions/tests/test_convert2dashes.py create mode 100644 share/extensions/tests/test_deprecated_simple.py create mode 100644 share/extensions/tests/test_dhw_input.py create mode 100644 share/extensions/tests/test_dimension.py create mode 100644 share/extensions/tests/test_doc_ai_convert.py create mode 100644 share/extensions/tests/test_docinfo.py create mode 100644 share/extensions/tests/test_dpiswitcher.py create mode 100644 share/extensions/tests/test_draw_from_triangle.py create mode 100644 share/extensions/tests/test_dxf12_outlines.py create mode 100644 share/extensions/tests/test_dxf_input.py create mode 100644 share/extensions/tests/test_dxf_outlines.py create mode 100644 share/extensions/tests/test_edge3d.py create mode 100644 share/extensions/tests/test_export_gimp_palette.py create mode 100644 share/extensions/tests/test_extrude.py create mode 100644 share/extensions/tests/test_fig_input.py create mode 100644 share/extensions/tests/test_flatten.py create mode 100644 share/extensions/tests/test_foldablebox.py create mode 100644 share/extensions/tests/test_fractalize.py create mode 100644 share/extensions/tests/test_frame.py create mode 100644 share/extensions/tests/test_funcplot.py create mode 100644 share/extensions/tests/test_generate_voronoi.py create mode 100644 share/extensions/tests/test_gimp_xcf.py create mode 100644 share/extensions/tests/test_grid_cartesian.py create mode 100644 share/extensions/tests/test_grid_isometric.py create mode 100644 share/extensions/tests/test_grid_polar.py create mode 100644 share/extensions/tests/test_guides_creator.py create mode 100644 share/extensions/tests/test_guillotine.py create mode 100644 share/extensions/tests/test_handles.py create mode 100644 share/extensions/tests/test_hershey.py create mode 100644 share/extensions/tests/test_hpgl_decoder.py create mode 100644 share/extensions/tests/test_hpgl_input.py create mode 100644 share/extensions/tests/test_hpgl_output.py create mode 100644 share/extensions/tests/test_image_attributes.py create mode 100644 share/extensions/tests/test_image_embed.py create mode 100644 share/extensions/tests/test_image_extract.py create mode 100644 share/extensions/tests/test_ink2canvas_svg.py create mode 100644 share/extensions/tests/test_inkex.py create mode 100644 share/extensions/tests/test_inkex_base.py create mode 100644 share/extensions/tests/test_inkex_bezier.py create mode 100644 share/extensions/tests/test_inkex_bounding_box.py create mode 100644 share/extensions/tests/test_inkex_colors.py create mode 100644 share/extensions/tests/test_inkex_command.py create mode 100644 share/extensions/tests/test_inkex_cubic_paths.py create mode 100644 share/extensions/tests/test_inkex_deprecated.py create mode 100644 share/extensions/tests/test_inkex_elements.py create mode 100644 share/extensions/tests/test_inkex_elements_base.py create mode 100644 share/extensions/tests/test_inkex_elements_filters.py create mode 100644 share/extensions/tests/test_inkex_elements_selections.py create mode 100644 share/extensions/tests/test_inkex_extensions.py create mode 100644 share/extensions/tests/test_inkex_extensions_GenerateExtension.py create mode 100644 share/extensions/tests/test_inkex_gui.py create mode 100644 share/extensions/tests/test_inkex_gui_asyncme.py create mode 100644 share/extensions/tests/test_inkex_gui_listview.py create mode 100644 share/extensions/tests/test_inkex_gui_pixmaps.py create mode 100644 share/extensions/tests/test_inkex_gui_window.py create mode 100644 share/extensions/tests/test_inkex_inx.py create mode 100644 share/extensions/tests/test_inkex_paths.py create mode 100644 share/extensions/tests/test_inkex_styles.py create mode 100644 share/extensions/tests/test_inkex_styles_complex.py create mode 100644 share/extensions/tests/test_inkex_svg.py create mode 100644 share/extensions/tests/test_inkex_tester.py create mode 100644 share/extensions/tests/test_inkex_transforms.py create mode 100644 share/extensions/tests/test_inkex_tween.py create mode 100644 share/extensions/tests/test_inkex_units.py create mode 100644 share/extensions/tests/test_inkex_utils.py create mode 100644 share/extensions/tests/test_inkscape_follow_link.py create mode 100644 share/extensions/tests/test_inkwebeffect.py create mode 100644 share/extensions/tests/test_interp.py create mode 100644 share/extensions/tests/test_interp_att_g.py create mode 100644 share/extensions/tests/test_jessyink_autotexts.py create mode 100644 share/extensions/tests/test_jessyink_effects.py create mode 100644 share/extensions/tests/test_jessyink_export.py create mode 100644 share/extensions/tests/test_jessyink_install.py create mode 100644 share/extensions/tests/test_jessyink_keybindings.py create mode 100644 share/extensions/tests/test_jessyink_masterslide.py create mode 100644 share/extensions/tests/test_jessyink_mousehandler.py create mode 100644 share/extensions/tests/test_jessyink_summary.py create mode 100644 share/extensions/tests/test_jessyink_transitions.py create mode 100644 share/extensions/tests/test_jessyink_uninstall.py create mode 100644 share/extensions/tests/test_jessyink_video.py create mode 100644 share/extensions/tests/test_jessyink_view.py create mode 100644 share/extensions/tests/test_jitternodes.py create mode 100644 share/extensions/tests/test_layer2png.py create mode 100644 share/extensions/tests/test_layers2svgfont.py create mode 100644 share/extensions/tests/test_layout_nup.py create mode 100644 share/extensions/tests/test_lindenmayer.py create mode 100644 share/extensions/tests/test_lorem_ipsum.py create mode 100644 share/extensions/tests/test_markers_strokepaint.py create mode 100644 share/extensions/tests/test_measure.py create mode 100644 share/extensions/tests/test_media_zip.py create mode 100644 share/extensions/tests/test_merge_styles.py create mode 100644 share/extensions/tests/test_motion.py create mode 100644 share/extensions/tests/test_new_glyph_layer.py create mode 100644 share/extensions/tests/test_next_glyph_layer.py create mode 100644 share/extensions/tests/test_nicechart.py create mode 100644 share/extensions/tests/test_output_scour.py create mode 100644 share/extensions/tests/test_param_curves.py create mode 100644 share/extensions/tests/test_path_envelope.py create mode 100644 share/extensions/tests/test_path_mesh.py create mode 100644 share/extensions/tests/test_path_number_nodes.py create mode 100644 share/extensions/tests/test_path_to_absolute.py create mode 100644 share/extensions/tests/test_pathalongpath.py create mode 100644 share/extensions/tests/test_pathscatter.py create mode 100644 share/extensions/tests/test_pdflatex.py create mode 100644 share/extensions/tests/test_perfectboundcover.py create mode 100644 share/extensions/tests/test_perspective.py create mode 100644 share/extensions/tests/test_pixelsnap.py create mode 100644 share/extensions/tests/test_plotter.py create mode 100644 share/extensions/tests/test_polyhedron_3d.py create mode 100644 share/extensions/tests/test_prepare_file_save_as.py create mode 100644 share/extensions/tests/test_previous_glyph_layer.py create mode 100644 share/extensions/tests/test_print_win32_vector.py create mode 100644 share/extensions/tests/test_printing_marks.py create mode 100644 share/extensions/tests/test_ps_input.py create mode 100644 share/extensions/tests/test_render_alphabetsoup.py create mode 100644 share/extensions/tests/test_render_barcode.py create mode 100644 share/extensions/tests/test_render_barcode_datamatrix.py create mode 100644 share/extensions/tests/test_render_barcode_qrcode.py create mode 100644 share/extensions/tests/test_render_gear_rack.py create mode 100644 share/extensions/tests/test_render_gears.py create mode 100644 share/extensions/tests/test_replace_font.py create mode 100644 share/extensions/tests/test_restack.py create mode 100644 share/extensions/tests/test_rtree.py create mode 100644 share/extensions/tests/test_rubberstretch.py create mode 100644 share/extensions/tests/test_scribus_pdf.py create mode 100644 share/extensions/tests/test_setup_typography_canvas.py create mode 100644 share/extensions/tests/test_spirograph.py create mode 100644 share/extensions/tests/test_straightseg.py create mode 100644 share/extensions/tests/test_svgcalendar.py create mode 100644 share/extensions/tests/test_svgfont2layers.py create mode 100644 share/extensions/tests/test_synfig_fileformat.py create mode 100644 share/extensions/tests/test_synfig_output.py create mode 100644 share/extensions/tests/test_tar_layers.py create mode 100644 share/extensions/tests/test_template.py create mode 100644 share/extensions/tests/test_template_dvd_cover.py create mode 100644 share/extensions/tests/test_template_seamless_pattern.py create mode 100644 share/extensions/tests/test_text_braille.py create mode 100644 share/extensions/tests/test_text_extract.py create mode 100644 share/extensions/tests/test_text_flipcase.py create mode 100644 share/extensions/tests/test_text_lowercase.py create mode 100644 share/extensions/tests/test_text_merge.py create mode 100644 share/extensions/tests/test_text_randomcase.py create mode 100644 share/extensions/tests/test_text_sentencecase.py create mode 100644 share/extensions/tests/test_text_split.py create mode 100644 share/extensions/tests/test_text_titlecase.py create mode 100644 share/extensions/tests/test_text_uppercase.py create mode 100644 share/extensions/tests/test_triangle.py create mode 100644 share/extensions/tests/test_ungroup_deep.py create mode 100644 share/extensions/tests/test_voronoi.py create mode 100644 share/extensions/tests/test_voronoi2svg.py create mode 100644 share/extensions/tests/test_web_interactive_mockup.py create mode 100644 share/extensions/tests/test_web_set_att.py create mode 100644 share/extensions/tests/test_web_transmit_att.py create mode 100644 share/extensions/tests/test_webslicer_create_group.py create mode 100644 share/extensions/tests/test_webslicer_create_rect.py create mode 100644 share/extensions/tests/test_webslicer_export.py create mode 100644 share/extensions/tests/test_whirl.py create mode 100644 share/extensions/tests/test_wireframe_sphere.py create mode 100644 share/extensions/text_braille.inx create mode 100755 share/extensions/text_braille.py create mode 100644 share/extensions/text_extract.inx create mode 100755 share/extensions/text_extract.py create mode 100644 share/extensions/text_flipcase.inx create mode 100755 share/extensions/text_flipcase.py create mode 100644 share/extensions/text_lowercase.inx create mode 100755 share/extensions/text_lowercase.py create mode 100644 share/extensions/text_merge.inx create mode 100755 share/extensions/text_merge.py create mode 100644 share/extensions/text_randomcase.inx create mode 100755 share/extensions/text_randomcase.py create mode 100644 share/extensions/text_sentencecase.inx create mode 100755 share/extensions/text_sentencecase.py create mode 100644 share/extensions/text_split.inx create mode 100755 share/extensions/text_split.py create mode 100644 share/extensions/text_titlecase.inx create mode 100755 share/extensions/text_titlecase.py create mode 100644 share/extensions/text_uppercase.inx create mode 100755 share/extensions/text_uppercase.py create mode 100644 share/extensions/tools/generate_argparse_conf.py create mode 100644 share/extensions/tox.ini create mode 100644 share/extensions/triangle.inx create mode 100755 share/extensions/triangle.py create mode 100644 share/extensions/ungroup_deep.inx create mode 100755 share/extensions/ungroup_deep.py create mode 100755 share/extensions/voronoi.py create mode 100644 share/extensions/voronoi2svg.inx create mode 100755 share/extensions/voronoi2svg.py create mode 100644 share/extensions/web_interactive_mockup.inx create mode 100755 share/extensions/web_interactive_mockup.py create mode 100644 share/extensions/web_set_att.inx create mode 100755 share/extensions/web_set_att.py create mode 100644 share/extensions/web_transmit_att.inx create mode 100755 share/extensions/web_transmit_att.py create mode 100644 share/extensions/webslicer_create_group.inx create mode 100755 share/extensions/webslicer_create_group.py create mode 100644 share/extensions/webslicer_create_rect.inx create mode 100755 share/extensions/webslicer_create_rect.py create mode 100755 share/extensions/webslicer_effect.py create mode 100644 share/extensions/webslicer_export.inx create mode 100755 share/extensions/webslicer_export.py create mode 100644 share/extensions/whirl.inx create mode 100755 share/extensions/whirl.py create mode 100644 share/extensions/wireframe_sphere.inx create mode 100755 share/extensions/wireframe_sphere.py create mode 100644 share/extensions/xaml2svg.inx create mode 100644 share/extensions/xaml2svg.xsl create mode 100644 share/extensions/xaml2svg/animation.xsl create mode 100644 share/extensions/xaml2svg/brushes.xsl create mode 100644 share/extensions/xaml2svg/canvas.xsl create mode 100644 share/extensions/xaml2svg/geometry.xsl create mode 100644 share/extensions/xaml2svg/properties.xsl create mode 100644 share/extensions/xaml2svg/shapes.xsl create mode 100644 share/extensions/xaml2svg/transform.xsl (limited to 'share/extensions') diff --git a/share/extensions/.darglint b/share/extensions/.darglint new file mode 100644 index 0000000..4447949 --- /dev/null +++ b/share/extensions/.darglint @@ -0,0 +1,3 @@ +[darglint] +docstring_style=google +strictness=short \ No newline at end of file diff --git a/share/extensions/.gitmodules b/share/extensions/.gitmodules new file mode 100644 index 0000000..938c258 --- /dev/null +++ b/share/extensions/.gitmodules @@ -0,0 +1,9 @@ +[submodule "other/gcodetools"] + path = other/gcodetools + url = https://gitlab.com/inkscape/extras/extensions-gcodetools.git +[submodule "other/inkman"] + path = other/inkman + url = https://gitlab.com/inkscape/extras/extension-manager.git +[submodule "other/clipart"] + path = other/clipart + url = https://gitlab.com/inkscape/extras/inkscape-import-clipart.git diff --git a/share/extensions/.pre-commit-config.yaml b/share/extensions/.pre-commit-config.yaml new file mode 100644 index 0000000..38cf86a --- /dev/null +++ b/share/extensions/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +- repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black \ No newline at end of file diff --git a/share/extensions/.pylintrc b/share/extensions/.pylintrc new file mode 100644 index 0000000..b2e02b0 --- /dev/null +++ b/share/extensions/.pylintrc @@ -0,0 +1,374 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +init-hook='import sys; sys.path.append("pythonenv/lib/python3.6/site-packages"); sys.path.append("../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../../pythonenv/lib/python3.6/site-packages");' + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist=lxml,numpy + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,superfluous-parens,missing-super-argument,model-missing-unicode + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=88 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,x,y,z,ex,Run,_,__,js,rx,ry,x1,y1,x2,y2,cx,cy,dx,dy,r,x3,x4,y3,y4,dr,c + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[ELIF] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). This supports can work +# with qualified names. +ignored-classes=SQLObject,WSGIRequest + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=8 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/share/extensions/CONTRIBUTING.md b/share/extensions/CONTRIBUTING.md new file mode 100644 index 0000000..e2319d7 --- /dev/null +++ b/share/extensions/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +See https://inkscape.gitlab.io/extensions/documentation/dev/getting-started.html for hints to +setup your development environment. \ No newline at end of file diff --git a/share/extensions/LICENSE.txt b/share/extensions/LICENSE.txt new file mode 100644 index 0000000..b83f24b --- /dev/null +++ b/share/extensions/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/share/extensions/MANIFEST.in b/share/extensions/MANIFEST.in new file mode 100644 index 0000000..2f29cde --- /dev/null +++ b/share/extensions/MANIFEST.in @@ -0,0 +1,2 @@ +include *.py +include *.inx diff --git a/share/extensions/Poly3DObjects/cube.obj b/share/extensions/Poly3DObjects/cube.obj new file mode 100644 index 0000000..b577ce1 --- /dev/null +++ b/share/extensions/Poly3DObjects/cube.obj @@ -0,0 +1,19 @@ +#Name:Cube +#Type:Face-specified +#Direction:Clockwise + +v -0.5 -0.5 -0.5 +v -0.5 -0.5 0.5 +v -0.5 0.5 -0.5 +v -0.5 0.5 0.5 +v 0.5 -0.5 -0.5 +v 0.5 -0.5 0.5 +v 0.5 0.5 -0.5 +v 0.5 0.5 0.5 + +f 8 4 2 6 +f 8 6 5 7 +f 8 7 3 4 +f 4 3 1 2 +f 1 3 7 5 +f 2 1 5 6 \ No newline at end of file diff --git a/share/extensions/Poly3DObjects/cuboct.obj b/share/extensions/Poly3DObjects/cuboct.obj new file mode 100644 index 0000000..709606b --- /dev/null +++ b/share/extensions/Poly3DObjects/cuboct.obj @@ -0,0 +1,30 @@ +#Name:Cuboctahedron +#Type:Face_specified + +v -1. 0 0 +v -0.5 -0.5 -0.70710678 +v -0.5 -0.5 0.70710678 +v -0.5 0.5 -0.70710678 +v -0.5 0.5 0.70710678 +v 0 -1. 0 +v 0 1. 0 +v 0.5 -0.5 -0.70710678 +v 0.5 -0.5 0.70710678 +v 0.5 0.5 -0.70710678 +v 0.5 0.5 0.70710678 +v 1. 0 0 + +f 12 11 9 +f 3 5 1 +f 6 9 3 +f 5 11 7 +f 8 10 12 +f 1 4 2 +f 2 8 6 +f 7 10 4 +f 4 10 8 2 +f 3 9 11 5 +f 9 6 8 12 +f 3 1 2 6 +f 5 7 4 1 +f 11 12 10 7 diff --git a/share/extensions/Poly3DObjects/dodec.obj b/share/extensions/Poly3DObjects/dodec.obj new file mode 100644 index 0000000..5b66f09 --- /dev/null +++ b/share/extensions/Poly3DObjects/dodec.obj @@ -0,0 +1,36 @@ +#NameDodecahedron +#Type:Face_specified + +v 0 0 1.4012585 +v 0 0 -1.4012585 +v 0.17841104 -1.3090170 0.46708618 +v 0.17841104 1.3090170 0.46708618 +v 0.46708618 -0.80901699 -1.0444364 +v 0.46708618 0.80901699 -1.0444364 +v 1.0444364 -0.80901699 0.46708618 +v 1.0444364 0.80901699 0.46708618 +v -1.2228475 -0.5 0.46708618 +v -1.2228475 0.5 0.46708618 +v 1.2228475 -0.5 -0.46708618 +v 1.2228475 0.5 -0.46708618 +v -0.93417236 0 -1.0444364 +v -0.46708618 -0.80901699 1.0444364 +v -0.46708618 0.80901699 1.0444364 +v 0.93417236 0 1.0444364 +v -1.0444364 -0.80901699 -0.46708618 +v -1.0444364 0.80901699 -0.46708618 +v -0.17841104 -1.3090170 -0.46708618 +v -0.17841104 1.3090170 -0.46708618 + +f 15 10 9 14 1 +f 2 6 12 11 5 +f 5 11 7 3 19 +f 11 12 8 16 7 +f 12 6 20 4 8 +f 6 2 13 18 20 +f 2 5 19 17 13 +f 4 20 18 10 15 +f 18 13 17 9 10 +f 17 19 3 14 9 +f 3 7 16 1 14 +f 16 8 4 15 1 diff --git a/share/extensions/Poly3DObjects/great_dodec.obj b/share/extensions/Poly3DObjects/great_dodec.obj new file mode 100644 index 0000000..2d12f02 --- /dev/null +++ b/share/extensions/Poly3DObjects/great_dodec.obj @@ -0,0 +1,96 @@ +#Name:Great Dodecahedron +#Type:Face_specified + +v 0. 0. -0.951057 +v 0. 0. 0.951057 +v -0.425325 -0.309017 -0.100406 +v -0.425325 0.309017 -0.100406 +v 0.425325 -0.309017 0.100406 +v 0.425325 0.309017 0.100406 +v -0.688191 -0.5 0.425325 +v -0.688191 0.5 0.425325 +v 0.688191 -0.5 -0.425325 +v 0.688191 0.5 -0.425325 +v -0.850651 0. -0.425325 +v 0.850651 0. 0.425325 +v -0.100406 -0.309017 0.425325 +v -0.100406 0.309017 0.425325 +v 0.100406 -0.309017 -0.425325 +v 0.100406 0.309017 -0.425325 +v -0.32492 0. 0.425325 +v -0.16246 -0.5 0.100406 +v -0.16246 0.5 0.100406 +v 0.16246 -0.5 -0.100406 +v 0.16246 0.5 -0.100406 +v 0.32492 0. -0.425325 +v -0.525731 0. 0.100406 +v -0.262866 -0.809017 -0.425325 +v -0.262866 0.190983 -0.425325 +v -0.262866 -0.190983 -0.425325 +v -0.262866 0.809017 -0.425325 +v 0.262866 -0.809017 0.425325 +v 0.262866 0.190983 0.425325 +v 0.262866 -0.190983 0.425325 +v 0.262866 0.809017 0.425325 +v 0.525731 0. -0.100406 + +f 14 2 31 +f 14 31 8 +f 14 8 2 +f 17 2 8 +f 17 8 7 +f 17 7 2 +f 13 2 7 +f 13 7 28 +f 13 28 2 +f 30 2 28 +f 30 28 12 +f 30 12 2 +f 29 2 12 +f 29 12 31 +f 29 31 2 +f 15 9 24 +f 15 24 1 +f 15 1 9 +f 22 10 9 +f 22 9 1 +f 22 1 10 +f 16 27 10 +f 16 10 1 +f 16 1 27 +f 25 11 27 +f 25 27 1 +f 25 1 11 +f 26 24 11 +f 26 11 1 +f 26 1 24 +f 19 31 27 +f 19 27 8 +f 19 8 31 +f 23 8 11 +f 23 11 7 +f 23 7 8 +f 18 7 24 +f 18 24 28 +f 18 28 7 +f 5 28 9 +f 5 9 12 +f 5 12 28 +f 6 12 10 +f 6 10 31 +f 6 31 12 +f 20 9 28 +f 20 28 24 +f 20 24 9 +f 32 10 12 +f 32 12 9 +f 32 9 10 +f 21 27 31 +f 21 31 10 +f 21 10 27 +f 4 11 8 +f 4 8 27 +f 4 27 11 +f 3 24 7 +f 3 7 11 +f 3 11 24 diff --git a/share/extensions/Poly3DObjects/great_rhombicosidodec.obj b/share/extensions/Poly3DObjects/great_rhombicosidodec.obj new file mode 100644 index 0000000..88bdccc --- /dev/null +++ b/share/extensions/Poly3DObjects/great_rhombicosidodec.obj @@ -0,0 +1,185 @@ +#Name:Great Rhombicosidodecahedron +#Type:face_specified +v -1. -1.30902 -3.42705 +v -1. -1.30902 3.42705 +v -1. 1.30902 -3.42705 +v -1. 1.30902 3.42705 +v -0.5 -0.5 -3.73607 +v -0.5 -0.5 3.73607 +v -0.5 0.5 -3.73607 +v -0.5 0.5 3.73607 +v -0.5 -3.73607 -0.5 +v -0.5 -3.73607 0.5 +v -0.5 -2.11803 -3.11803 +v -0.5 -2.11803 3.11803 +v -0.5 3.73607 -0.5 +v -0.5 3.73607 0.5 +v -0.5 2.11803 -3.11803 +v -0.5 2.11803 3.11803 +v 0.5 -0.5 -3.73607 +v 0.5 -0.5 3.73607 +v 0.5 0.5 -3.73607 +v 0.5 0.5 3.73607 +v 0.5 -3.73607 -0.5 +v 0.5 -3.73607 0.5 +v 0.5 -2.11803 -3.11803 +v 0.5 -2.11803 3.11803 +v 0.5 3.73607 -0.5 +v 0.5 3.73607 0.5 +v 0.5 2.11803 -3.11803 +v 0.5 2.11803 3.11803 +v 1. -1.30902 -3.42705 +v 1. -1.30902 3.42705 +v 1. 1.30902 -3.42705 +v 1. 1.30902 3.42705 +v -3.42705 -1. -1.30902 +v -3.42705 -1. 1.30902 +v -3.42705 1. -1.30902 +v -3.42705 1. 1.30902 +v -2.92705 -1.80902 -1.61803 +v -2.92705 -1.80902 1.61803 +v -2.92705 1.80902 -1.61803 +v -2.92705 1.80902 1.61803 +v -1.80902 -1.61803 -2.92705 +v -1.80902 -1.61803 2.92705 +v -1.80902 1.61803 -2.92705 +v -1.80902 1.61803 2.92705 +v -1.30902 -3.42705 -1. +v -1.30902 -3.42705 1. +v -1.30902 -2.42705 -2.61803 +v -1.30902 -2.42705 2.61803 +v -1.30902 2.42705 -2.61803 +v -1.30902 2.42705 2.61803 +v -1.30902 3.42705 -1. +v -1.30902 3.42705 1. +v -2.61803 -1.30902 -2.42705 +v -2.61803 -1.30902 2.42705 +v -2.61803 1.30902 -2.42705 +v -2.61803 1.30902 2.42705 +v -3.73607 -0.5 -0.5 +v -3.73607 -0.5 0.5 +v -3.73607 0.5 -0.5 +v -3.73607 0.5 0.5 +v -1.61803 -2.92705 -1.80902 +v -1.61803 -2.92705 1.80902 +v -1.61803 2.92705 -1.80902 +v -1.61803 2.92705 1.80902 +v -3.11803 -0.5 -2.11803 +v -3.11803 -0.5 2.11803 +v -3.11803 0.5 -2.11803 +v -3.11803 0.5 2.11803 +v -2.11803 -3.11803 -0.5 +v -2.11803 -3.11803 0.5 +v -2.11803 3.11803 -0.5 +v -2.11803 3.11803 0.5 +v -2.42705 -2.61803 -1.30902 +v -2.42705 -2.61803 1.30902 +v -2.42705 2.61803 -1.30902 +v -2.42705 2.61803 1.30902 +v 1.61803 -2.92705 -1.80902 +v 1.61803 -2.92705 1.80902 +v 1.61803 2.92705 -1.80902 +v 1.61803 2.92705 1.80902 +v 2.42705 -2.61803 -1.30902 +v 2.42705 -2.61803 1.30902 +v 2.42705 2.61803 -1.30902 +v 2.42705 2.61803 1.30902 +v 3.73607 -0.5 -0.5 +v 3.73607 -0.5 0.5 +v 3.73607 0.5 -0.5 +v 3.73607 0.5 0.5 +v 2.11803 -3.11803 -0.5 +v 2.11803 -3.11803 0.5 +v 2.11803 3.11803 -0.5 +v 2.11803 3.11803 0.5 +v 1.30902 -3.42705 -1. +v 1.30902 -3.42705 1. +v 1.30902 -2.42705 -2.61803 +v 1.30902 -2.42705 2.61803 +v 1.30902 2.42705 -2.61803 +v 1.30902 2.42705 2.61803 +v 1.30902 3.42705 -1. +v 1.30902 3.42705 1. +v 2.61803 -1.30902 -2.42705 +v 2.61803 -1.30902 2.42705 +v 2.61803 1.30902 -2.42705 +v 2.61803 1.30902 2.42705 +v 3.11803 -0.5 -2.11803 +v 3.11803 -0.5 2.11803 +v 3.11803 0.5 -2.11803 +v 3.11803 0.5 2.11803 +v 1.80902 -1.61803 -2.92705 +v 1.80902 -1.61803 2.92705 +v 1.80902 1.61803 -2.92705 +v 1.80902 1.61803 2.92705 +v 2.92705 -1.80902 -1.61803 +v 2.92705 -1.80902 1.61803 +v 2.92705 1.80902 -1.61803 +v 2.92705 1.80902 1.61803 +v 3.42705 -1. -1.30902 +v 3.42705 -1. 1.30902 +v 3.42705 1. -1.30902 +v 3.42705 1. 1.30902 + +f 2 6 8 4 44 56 68 66 54 42 +f 109 29 17 19 31 111 103 107 105 101 +f 24 30 18 6 2 12 +f 7 3 15 27 31 19 +f 58 57 33 37 73 69 70 74 38 34 +f 84 116 120 88 87 119 115 83 91 92 +f 90 89 81 113 117 85 86 118 114 82 +f 36 40 76 72 71 75 39 35 59 60 +f 5 17 29 23 11 1 +f 4 8 20 32 28 16 +f 67 55 43 3 7 5 1 41 53 65 +f 18 30 110 102 106 108 104 112 32 20 +f 79 83 115 103 111 97 +f 38 74 62 48 42 54 +f 4 16 50 44 +f 23 29 109 95 +f 96 110 30 24 +f 43 49 15 3 +f 53 41 47 61 73 37 +f 98 112 104 116 84 80 +f 69 45 9 10 46 70 +f 26 100 92 91 99 25 +f 82 114 102 110 96 78 +f 55 39 75 63 49 43 +f 1 11 47 41 +f 28 32 112 98 +f 61 47 11 23 95 77 93 21 9 45 +f 50 16 28 98 80 100 26 14 52 64 +f 97 111 31 27 +f 42 48 12 2 +f 44 50 64 76 40 56 +f 77 95 109 101 113 81 +f 63 51 13 25 99 79 97 27 15 49 +f 46 10 22 94 78 96 24 12 48 62 +f 52 14 13 51 71 72 +f 22 21 93 89 90 94 +f 115 119 107 103 +f 34 38 54 66 +f 71 51 63 75 +f 94 90 82 78 +f 114 118 106 102 +f 35 39 55 67 +f 70 46 62 74 +f 99 91 83 79 +f 65 53 37 33 +f 104 108 120 116 +f 77 81 89 93 +f 76 64 52 72 +f 59 35 67 65 33 57 +f 106 118 86 88 120 108 +f 68 56 40 36 +f 101 105 117 113 +f 80 84 92 100 +f 73 61 45 69 +f 34 66 68 36 60 58 +f 105 107 119 87 85 117 +f 7 19 17 5 +f 6 18 20 8 +f 14 26 25 13 +f 9 21 22 10 +f 58 60 59 57 +f 85 87 88 86 diff --git a/share/extensions/Poly3DObjects/great_rhombicuboct.obj b/share/extensions/Poly3DObjects/great_rhombicuboct.obj new file mode 100644 index 0000000..1ef7b4c --- /dev/null +++ b/share/extensions/Poly3DObjects/great_rhombicuboct.obj @@ -0,0 +1,77 @@ +#Name:Great Rhombicuboctahedron +#Type:face_specified +v -0.5 1.20711 -1.91421 +v -0.5 1.20711 1.91421 +v -0.5 -1.20711 -1.91421 +v -0.5 -1.20711 1.91421 +v -0.5 -1.91421 1.20711 +v -0.5 -1.91421 -1.20711 +v -0.5 1.91421 1.20711 +v -0.5 1.91421 -1.20711 +v 0.5 1.20711 -1.91421 +v 0.5 1.20711 1.91421 +v 0.5 -1.20711 -1.91421 +v 0.5 -1.20711 1.91421 +v 0.5 -1.91421 1.20711 +v 0.5 -1.91421 -1.20711 +v 0.5 1.91421 1.20711 +v 0.5 1.91421 -1.20711 +v 1.20711 -0.5 -1.91421 +v 1.20711 -0.5 1.91421 +v 1.20711 0.5 -1.91421 +v 1.20711 0.5 1.91421 +v 1.20711 -1.91421 -0.5 +v 1.20711 -1.91421 0.5 +v 1.20711 1.91421 -0.5 +v 1.20711 1.91421 0.5 +v -1.20711 -0.5 -1.91421 +v -1.20711 -0.5 1.91421 +v -1.20711 0.5 -1.91421 +v -1.20711 0.5 1.91421 +v -1.20711 -1.91421 -0.5 +v -1.20711 -1.91421 0.5 +v -1.20711 1.91421 -0.5 +v -1.20711 1.91421 0.5 +v -1.91421 -0.5 1.20711 +v -1.91421 -0.5 -1.20711 +v -1.91421 0.5 1.20711 +v -1.91421 0.5 -1.20711 +v -1.91421 1.20711 -0.5 +v -1.91421 1.20711 0.5 +v -1.91421 -1.20711 -0.5 +v -1.91421 -1.20711 0.5 +v 1.91421 -0.5 1.20711 +v 1.91421 -0.5 -1.20711 +v 1.91421 0.5 1.20711 +v 1.91421 0.5 -1.20711 +v 1.91421 1.20711 -0.5 +v 1.91421 1.20711 0.5 +v 1.91421 -1.20711 -0.5 +v 1.91421 -1.20711 0.5 + +f 44 42 17 19 +f 14 6 3 11 +f 34 36 27 25 +f 8 16 9 1 +f 20 18 41 43 +f 12 4 5 13 +f 26 28 35 33 +f 2 10 15 7 +f 45 23 24 46 +f 39 29 30 40 +f 48 22 21 47 +f 38 32 31 37 +f 9 19 17 11 3 25 27 1 +f 2 28 26 4 12 18 20 10 +f 41 48 47 42 44 45 46 43 +f 35 38 37 36 34 39 40 33 +f 15 24 23 16 8 31 32 7 +f 5 30 29 6 14 21 22 13 +f 46 24 15 10 20 43 +f 35 28 2 7 32 38 +f 41 18 12 13 22 48 +f 40 30 5 4 26 33 +f 44 19 9 16 23 45 +f 37 31 8 1 27 36 +f 47 21 14 11 17 42 +f 34 25 3 6 29 39 diff --git a/share/extensions/Poly3DObjects/great_stel_dodec.obj b/share/extensions/Poly3DObjects/great_stel_dodec.obj new file mode 100644 index 0000000..b0e5429 --- /dev/null +++ b/share/extensions/Poly3DObjects/great_stel_dodec.obj @@ -0,0 +1,96 @@ +#Name:Great Stellated Dodecahedron +#Type:face_specified + +v 0. 0. -0.951057 +v 0. 0. 0.951057 +v -0.425325 -1.30902 1.80171 +v -0.425325 1.30902 1.80171 +v 0.425325 -1.30902 -1.80171 +v 0.425325 1.30902 -1.80171 +v -0.688191 -0.5 0.425325 +v -0.688191 0.5 0.425325 +v -0.688191 -2.11803 0.425325 +v -0.688191 2.11803 0.425325 +v 0.688191 -0.5 -0.425325 +v 0.688191 0.5 -0.425325 +v 0.688191 -2.11803 -0.425325 +v 0.688191 2.11803 -0.425325 +v -0.850651 0. -0.425325 +v 0.850651 0. 0.425325 +v -1.11352 -0.809017 -1.80171 +v -1.11352 0.809017 -1.80171 +v 1.11352 -0.809017 1.80171 +v 1.11352 0.809017 1.80171 +v -1.80171 -1.30902 -0.425325 +v -1.80171 1.30902 -0.425325 +v 1.80171 -1.30902 0.425325 +v 1.80171 1.30902 0.425325 +v -2.22703 0. 0.425325 +v 2.22703 0. -0.425325 +v -0.262866 -0.809017 -0.425325 +v -0.262866 0.809017 -0.425325 +v 0.262866 -0.809017 0.425325 +v 0.262866 0.809017 0.425325 +v -1.37638 0. 1.80171 +v 1.37638 0. -1.80171 + +f 4 2 30 +f 4 30 8 +f 4 8 2 +f 31 2 8 +f 31 8 7 +f 31 7 2 +f 3 2 7 +f 3 7 29 +f 3 29 2 +f 19 2 29 +f 19 29 16 +f 19 16 2 +f 20 2 16 +f 20 16 30 +f 20 30 2 +f 5 11 27 +f 5 27 1 +f 5 1 11 +f 32 12 11 +f 32 11 1 +f 32 1 12 +f 6 28 12 +f 6 12 1 +f 6 1 28 +f 18 15 28 +f 18 28 1 +f 18 1 15 +f 17 27 15 +f 17 15 1 +f 17 1 27 +f 10 30 28 +f 10 28 8 +f 10 8 30 +f 25 8 15 +f 25 15 7 +f 25 7 8 +f 9 7 27 +f 9 27 29 +f 9 29 7 +f 23 29 11 +f 23 11 16 +f 23 16 29 +f 24 16 12 +f 24 12 30 +f 24 30 16 +f 13 11 29 +f 13 29 27 +f 13 27 11 +f 26 12 16 +f 26 16 11 +f 26 11 12 +f 14 28 30 +f 14 30 12 +f 14 12 28 +f 22 15 8 +f 22 8 28 +f 22 28 15 +f 21 27 7 +f 21 7 15 +f 21 15 27 diff --git a/share/extensions/Poly3DObjects/icos.obj b/share/extensions/Poly3DObjects/icos.obj new file mode 100644 index 0000000..ed55ea4 --- /dev/null +++ b/share/extensions/Poly3DObjects/icos.obj @@ -0,0 +1,36 @@ +#Name:Icosahedron +#Type:face_specified + +v 0 0 -0.95105652 +v 0 0 0.95105652 +v -0.85065081 0 -0.42532540 +v 0.85065081 0 0.42532540 +v 0.68819096 -0.50000000 -0.42532540 +v 0.68819096 0.50000000 -0.42532540 +v -0.68819096 -0.50000000 0.42532540 +v -0.68819096 0.50000000 0.42532540 +v -0.26286556 -0.80901699 -0.42532540 +v -0.26286556 0.80901699 -0.42532540 +v 0.26286556 -0.80901699 0.42532540 +v 0.26286556 0.80901699 0.42532540 + +f 2 12 8 +f 2 8 7 +f 2 7 11 +f 2 11 4 +f 2 4 12 +f 5 9 1 +f 6 5 1 +f 10 6 1 +f 3 10 1 +f 9 3 1 +f 12 10 8 +f 8 3 7 +f 7 9 11 +f 11 5 4 +f 4 6 12 +f 5 11 9 +f 6 4 5 +f 10 12 6 +f 3 8 10 +f 9 7 3 diff --git a/share/extensions/Poly3DObjects/icosidodec.obj b/share/extensions/Poly3DObjects/icosidodec.obj new file mode 100644 index 0000000..961bec2 --- /dev/null +++ b/share/extensions/Poly3DObjects/icosidodec.obj @@ -0,0 +1,65 @@ +#Name:Icosidodecahedron +#Type:face_specified +v 0. -1.61803 0. +v 0. 1.61803 0. +v 0.262866 -0.809017 -1.37638 +v 0.262866 0.809017 -1.37638 +v 0.425325 -1.30902 0.850651 +v 0.425325 1.30902 0.850651 +v 0.688191 -0.5 1.37638 +v 0.688191 0.5 1.37638 +v 1.11352 -0.809017 -0.850651 +v 1.11352 0.809017 -0.850651 +v -1.37638 0. -0.850651 +v -0.688191 -0.5 -1.37638 +v -0.688191 0.5 -1.37638 +v 1.37638 0. 0.850651 +v 0.951057 -1.30902 0. +v 0.951057 1.30902 0. +v 0.850651 0. -1.37638 +v -0.951057 -1.30902 0. +v -0.951057 1.30902 0. +v -1.53884 -0.5 0. +v -1.53884 0.5 0. +v 1.53884 -0.5 0. +v 1.53884 0.5 0. +v -0.850651 0. 1.37638 +v -1.11352 -0.809017 0.850651 +v -1.11352 0.809017 0.850651 +v -0.425325 -1.30902 -0.850651 +v -0.425325 1.30902 -0.850651 +v -0.262866 -0.809017 1.37638 +v -0.262866 0.809017 1.37638 + +f 30 24 29 7 8 +f 26 24 30 +f 25 29 24 +f 5 7 29 +f 14 8 7 +f 6 30 8 +f 16 2 6 +f 19 21 26 +f 20 18 25 +f 1 15 5 +f 22 23 14 +f 2 19 26 30 6 +f 21 20 25 24 26 +f 18 1 5 29 25 +f 15 22 14 7 5 +f 23 16 6 8 14 +f 12 13 4 17 3 +f 3 17 9 +f 17 4 10 +f 4 13 28 +f 13 12 11 +f 12 3 27 +f 27 1 18 +f 9 22 15 +f 10 16 23 +f 28 19 2 +f 11 20 21 +f 27 3 9 15 1 +f 9 17 10 23 22 +f 10 4 28 2 16 +f 28 13 11 21 19 +f 11 12 27 18 20 diff --git a/share/extensions/Poly3DObjects/jessens_orthog_icos.obj b/share/extensions/Poly3DObjects/jessens_orthog_icos.obj new file mode 100644 index 0000000..41aff7a --- /dev/null +++ b/share/extensions/Poly3DObjects/jessens_orthog_icos.obj @@ -0,0 +1,35 @@ +#Name:Jessen's Orthogonal Icosahedron +#Type:face_specified +v 0. -0.809017 0.5 +v 0. -0.809017 -0.5 +v 0. 0.809017 0.5 +v 0. 0.809017 -0.5 +v 0.5 0. -0.809017 +v 0.5 0. 0.809017 +v -0.5 0. -0.809017 +v -0.5 0. 0.809017 +v -0.809017 0.5 0. +v -0.809017 -0.5 0. +v 0.809017 0.5 0. +v 0.809017 -0.5 0. + +f 3 1 6 +f 6 1 12 +f 6 12 5 +f 11 3 6 +f 6 5 11 +f 12 1 10 +f 12 10 2 +f 5 12 2 +f 3 11 9 +f 1 3 8 +f 8 10 1 +f 7 2 10 +f 10 8 7 +f 3 9 8 +f 7 8 9 +f 5 2 4 +f 2 7 4 +f 7 9 4 +f 4 9 11 +f 5 4 11 \ No newline at end of file diff --git a/share/extensions/Poly3DObjects/methane.obj b/share/extensions/Poly3DObjects/methane.obj new file mode 100644 index 0000000..0b2d744 --- /dev/null +++ b/share/extensions/Poly3DObjects/methane.obj @@ -0,0 +1,13 @@ +#Name:Methane Molecule +#Type:edge_specified + +v 0 0 0 +v 0 0 0.61237244 +v -0.28867513 -0.50000000 -0.20412415 +v -0.28867513 0.50000000 -0.20412415 +v 0.57735027 0 -0.20412415 + +l 1 2 +l 1 3 +l 1 4 +l 1 5 diff --git a/share/extensions/Poly3DObjects/oct.obj b/share/extensions/Poly3DObjects/oct.obj new file mode 100644 index 0000000..f356b69 --- /dev/null +++ b/share/extensions/Poly3DObjects/oct.obj @@ -0,0 +1,17 @@ +#Name:Octahedron +#Type:face_specified +v -0.5 -0.5 0 +v -0.5 0.5 0 +v 0 0 -0.70710678 +v 0 0 0.70710678 +v 0.5 -0.5 0 +v 0.5 0.5 0 + +f 4 5 6 +f 4 6 2 +f 4 2 1 +f 4 1 5 +f 5 1 3 +f 5 3 6 +f 3 1 2 +f 6 3 2 diff --git a/share/extensions/Poly3DObjects/rh_axes.obj b/share/extensions/Poly3DObjects/rh_axes.obj new file mode 100644 index 0000000..cc6623f --- /dev/null +++ b/share/extensions/Poly3DObjects/rh_axes.obj @@ -0,0 +1,12 @@ +#Name:Right Handed Coordinate Axes +#Type:Edge_specified + +v 0 0 0 +v 1 0 0 +v 0 1 0 +v 0 0 1 + +l 1 2 +l 1 3 +l 1 4 + diff --git a/share/extensions/Poly3DObjects/rhomb_dodec.obj b/share/extensions/Poly3DObjects/rhomb_dodec.obj new file mode 100644 index 0000000..9fde9d6 --- /dev/null +++ b/share/extensions/Poly3DObjects/rhomb_dodec.obj @@ -0,0 +1,29 @@ +#Name:Rhombic Dodecahedron +#Type:face_specified +v -0.816497 -0.816497 0. +v -0.816497 0. -0.57735 +v -0.816497 0. 0.57735 +v -0.816497 0.816497 0. +v 0. -0.816497 -0.57735 +v 0. -0.816497 0.57735 +v 0. 0. -1.1547 +v 0. 0. 1.1547 +v 0. 0.816497 -0.57735 +v 0. 0.816497 0.57735 +v 0.816497 -0.816497 0. +v 0.816497 0. -0.57735 +v 0.816497 0. 0.57735 +v 0.816497 0.816497 0. + +f 2 1 3 4 +f 1 2 7 5 +f 6 8 3 1 +f 2 4 9 7 +f 8 10 4 3 +f 11 6 1 5 +f 9 4 10 14 +f 5 7 12 11 +f 11 13 8 6 +f 7 9 14 12 +f 13 14 10 8 +f 14 13 11 12 \ No newline at end of file diff --git a/share/extensions/Poly3DObjects/rhomb_triacont.obj b/share/extensions/Poly3DObjects/rhomb_triacont.obj new file mode 100644 index 0000000..70acebf --- /dev/null +++ b/share/extensions/Poly3DObjects/rhomb_triacont.obj @@ -0,0 +1,65 @@ +#Name:Rhombic Triacontahedron +#Type:face_specified +v 0. 0. -1.61803 +v 0. 0. 1.61803 +v 0.276393 -0.850651 1.17082 +v 0.276393 0.850651 1.17082 +v 0.894427 0. 1.17082 +v 1.17082 -0.850651 0.723607 +v 1.17082 -0.850651 -0.276393 +v 1.17082 0.850651 0.723607 +v 1.17082 0.850651 -0.276393 +v -0.894427 0. -1.17082 +v -0.447214 -1.37638 0.723607 +v -0.447214 -1.37638 -0.276393 +v -0.447214 1.37638 0.723607 +v -0.447214 1.37638 -0.276393 +v 0.447214 -1.37638 0.276393 +v 0.447214 -1.37638 -0.723607 +v 0.447214 1.37638 0.276393 +v 0.447214 1.37638 -0.723607 +v -1.44721 0. 0.723607 +v -1.44721 0. -0.276393 +v -0.723607 -0.525731 1.17082 +v -0.723607 0.525731 1.17082 +v 0.723607 -0.525731 -1.17082 +v 0.723607 0.525731 -1.17082 +v 1.44721 0. 0.276393 +v 1.44721 0. -0.723607 +v -1.17082 -0.850651 0.276393 +v -1.17082 -0.850651 -0.723607 +v -1.17082 0.850651 0.276393 +v -1.17082 0.850651 -0.723607 +v -0.276393 -0.850651 -1.17082 +v -0.276393 0.850651 -1.17082 + +f 16 15 11 12 +f 14 13 17 18 +f 10 28 20 30 +f 8 5 6 25 +f 12 28 31 16 +f 32 30 14 18 +f 6 3 11 15 +f 8 17 13 4 +f 11 21 19 27 +f 13 29 19 22 +f 7 16 23 26 +f 24 18 9 26 +f 12 11 27 28 +f 30 29 13 14 +f 7 6 15 16 +f 18 17 8 9 +f 2 22 19 21 +f 23 1 24 26 +f 3 2 21 11 +f 4 13 22 2 +f 16 31 1 23 +f 1 32 18 24 +f 31 28 10 1 +f 10 30 32 1 +f 6 5 2 3 +f 8 4 2 5 +f 28 27 19 20 +f 20 19 29 30 +f 26 25 6 7 +f 9 8 25 26 diff --git a/share/extensions/Poly3DObjects/small_rhombicosidodec.obj b/share/extensions/Poly3DObjects/small_rhombicosidodec.obj new file mode 100644 index 0000000..a209ba2 --- /dev/null +++ b/share/extensions/Poly3DObjects/small_rhombicosidodec.obj @@ -0,0 +1,127 @@ +#Name:Small Rhombicosidodecahedron +#Type:face_specified + +v -0.5 -0.5 -2.11803 +v -0.5 -0.5 2.11803 +v -0.5 0.5 -2.11803 +v -0.5 0.5 2.11803 +v -0.5 -2.11803 -0.5 +v -0.5 -2.11803 0.5 +v -0.5 2.11803 -0.5 +v -0.5 2.11803 0.5 +v 0. -1.30902 -1.80902 +v 0. -1.30902 1.80902 +v 0. 1.30902 -1.80902 +v 0. 1.30902 1.80902 +v 0.5 -0.5 -2.11803 +v 0.5 -0.5 2.11803 +v 0.5 0.5 -2.11803 +v 0.5 0.5 2.11803 +v 0.5 -2.11803 -0.5 +v 0.5 -2.11803 0.5 +v 0.5 2.11803 -0.5 +v 0.5 2.11803 0.5 +v -1.80902 0. -1.30902 +v -1.80902 0. 1.30902 +v -0.809017 -1.61803 -1.30902 +v -0.809017 -1.61803 1.30902 +v -0.809017 1.61803 -1.30902 +v -0.809017 1.61803 1.30902 +v -1.61803 -1.30902 -0.809017 +v -1.61803 -1.30902 0.809017 +v -1.61803 1.30902 -0.809017 +v -1.61803 1.30902 0.809017 +v -2.11803 -0.5 -0.5 +v -2.11803 -0.5 0.5 +v -2.11803 0.5 -0.5 +v -2.11803 0.5 0.5 +v -1.30902 -1.80902 0. +v -1.30902 -0.809017 -1.61803 +v -1.30902 -0.809017 1.61803 +v -1.30902 0.809017 -1.61803 +v -1.30902 0.809017 1.61803 +v -1.30902 1.80902 0. +v 0.809017 -1.61803 -1.30902 +v 0.809017 -1.61803 1.30902 +v 0.809017 1.61803 -1.30902 +v 0.809017 1.61803 1.30902 +v 1.61803 -1.30902 -0.809017 +v 1.61803 -1.30902 0.809017 +v 1.61803 1.30902 -0.809017 +v 1.61803 1.30902 0.809017 +v 2.11803 -0.5 -0.5 +v 2.11803 -0.5 0.5 +v 2.11803 0.5 -0.5 +v 2.11803 0.5 0.5 +v 1.30902 -1.80902 0. +v 1.30902 -0.809017 -1.61803 +v 1.30902 -0.809017 1.61803 +v 1.30902 0.809017 -1.61803 +v 1.30902 0.809017 1.61803 +v 1.30902 1.80902 0. +v 1.80902 0. -1.30902 +v 1.80902 0. 1.30902 + +f 36 23 27 +f 37 28 24 +f 40 8 7 +f 35 5 6 +f 38 29 25 +f 39 26 30 +f 10 14 2 +f 9 1 13 +f 12 4 16 +f 11 15 3 +f 54 45 41 +f 55 42 46 +f 58 19 20 +f 53 18 17 +f 56 43 47 +f 57 48 44 +f 34 32 22 +f 33 21 31 +f 59 51 49 +f 60 50 52 +f 27 31 21 36 +f 23 36 1 9 +f 10 2 37 24 +f 37 22 32 28 +f 8 40 30 26 +f 25 29 40 7 +f 35 27 23 5 +f 6 24 28 35 +f 3 38 25 11 +f 21 33 29 38 +f 39 30 34 22 +f 12 26 39 4 +f 55 14 10 42 +f 41 9 13 54 +f 57 44 12 16 +f 15 11 43 56 +f 45 54 59 49 +f 50 60 55 46 +f 48 58 20 44 +f 43 19 58 47 +f 53 17 41 45 +f 46 42 18 53 +f 59 56 47 51 +f 52 48 57 60 +f 31 32 34 33 +f 17 18 6 5 +f 1 3 15 13 +f 14 16 4 2 +f 7 8 20 19 +f 51 52 50 49 +f 3 1 36 21 38 +f 22 37 2 4 39 +f 29 33 34 30 40 +f 27 35 28 32 31 +f 42 10 24 6 18 +f 41 17 5 23 9 +f 20 8 26 12 44 +f 11 25 7 19 43 +f 56 59 54 13 15 +f 57 16 14 55 60 +f 58 48 52 51 47 +f 49 50 46 53 45 + diff --git a/share/extensions/Poly3DObjects/small_rhombicuboct.obj b/share/extensions/Poly3DObjects/small_rhombicuboct.obj new file mode 100644 index 0000000..2d064ab --- /dev/null +++ b/share/extensions/Poly3DObjects/small_rhombicuboct.obj @@ -0,0 +1,54 @@ +#Name:Small Rhombicuboctahedron +#Type:face_specified + +v -0.5 -0.5 -1.20711 +v -0.5 -0.5 1.20711 +v -0.5 0.5 -1.20711 +v -0.5 0.5 1.20711 +v -0.5 -1.20711 -0.5 +v -0.5 -1.20711 0.5 +v -0.5 1.20711 -0.5 +v -0.5 1.20711 0.5 +v 0.5 -0.5 -1.20711 +v 0.5 -0.5 1.20711 +v 0.5 0.5 -1.20711 +v 0.5 0.5 1.20711 +v 0.5 -1.20711 -0.5 +v 0.5 -1.20711 0.5 +v 0.5 1.20711 -0.5 +v 0.5 1.20711 0.5 +v -1.20711 -0.5 -0.5 +v -1.20711 -0.5 0.5 +v -1.20711 0.5 -0.5 +v -1.20711 0.5 0.5 +v 1.20711 -0.5 -0.5 +v 1.20711 -0.5 0.5 +v 1.20711 0.5 -0.5 +v 1.20711 0.5 0.5 + +f 3 11 9 1 +f 2 10 12 4 +f 24 22 21 23 +f 19 17 18 20 +f 5 13 14 6 +f 8 16 15 7 +f 13 21 22 14 +f 16 24 23 15 +f 6 18 17 5 +f 7 19 20 8 +f 6 14 10 2 +f 4 12 16 8 +f 22 24 12 10 +f 2 4 20 18 +f 1 9 13 5 +f 7 15 11 3 +f 9 11 23 21 +f 17 19 3 1 +f 22 10 14 +f 16 12 24 +f 6 2 18 +f 20 4 8 +f 13 9 21 +f 23 11 15 +f 17 1 5 +f 7 3 19 diff --git a/share/extensions/Poly3DObjects/small_triam_icos.obj b/share/extensions/Poly3DObjects/small_triam_icos.obj new file mode 100644 index 0000000..1d366ff --- /dev/null +++ b/share/extensions/Poly3DObjects/small_triam_icos.obj @@ -0,0 +1,95 @@ +#Name:Small Triambic Icosahedron +#Type:face_specified +v 0. 0. -0.951057 +v 0. 0. 0.951057 +v 0.262866 -0.809017 0.425325 +v 0.262866 0.809017 0.425325 +v 0.688191 -0.5 -0.425325 +v 0.688191 0.5 -0.425325 +v 0.995959 0. -0.190211 +v -0.688191 -0.5 0.425325 +v -0.688191 0.5 0.425325 +v -0.49798 -0.361803 -0.805748 +v -0.49798 0.361803 -0.805748 +v 0.49798 -0.361803 0.805748 +v 0.49798 0.361803 0.805748 +v 0.190211 -0.58541 -0.805748 +v 0.190211 0.58541 -0.805748 +v 0.850651 0. 0.425325 +v -0.190211 -0.58541 0.805748 +v -0.190211 0.58541 0.805748 +v -0.615537 0. 0.805748 +v -0.307768 -0.947214 0.190211 +v -0.307768 0.947214 0.190211 +v 0.307768 -0.947214 -0.190211 +v 0.307768 0.947214 -0.190211 +v 0.615537 0. -0.805748 +v 0.805748 -0.58541 0.190211 +v 0.805748 0.58541 0.190211 +v -0.850651 0. -0.425325 +v -0.262866 -0.809017 -0.425325 +v -0.262866 0.809017 -0.425325 +v -0.995959 0. 0.190211 +v -0.805748 -0.58541 -0.190211 +v -0.805748 0.58541 -0.190211 + +f 18 2 4 +f 18 4 9 +f 18 9 2 +f 19 2 9 +f 19 9 8 +f 19 8 2 +f 17 2 8 +f 17 8 3 +f 17 3 2 +f 12 2 3 +f 12 3 16 +f 12 16 2 +f 13 2 16 +f 13 16 4 +f 13 4 2 +f 14 5 28 +f 14 28 1 +f 14 1 5 +f 24 6 5 +f 24 5 1 +f 24 1 6 +f 15 29 6 +f 15 6 1 +f 15 1 29 +f 11 27 29 +f 11 29 1 +f 11 1 27 +f 10 28 27 +f 10 27 1 +f 10 1 28 +f 21 4 29 +f 21 29 9 +f 21 9 4 +f 30 9 27 +f 30 27 8 +f 30 8 9 +f 20 8 28 +f 20 28 3 +f 20 3 8 +f 25 3 5 +f 25 5 16 +f 25 16 3 +f 26 16 6 +f 26 6 4 +f 26 4 16 +f 22 5 3 +f 22 3 28 +f 22 28 5 +f 7 6 16 +f 7 16 5 +f 7 5 6 +f 23 29 4 +f 23 4 6 +f 23 6 29 +f 32 27 9 +f 32 9 29 +f 32 29 27 +f 31 28 8 +f 31 8 27 +f 31 27 28 diff --git a/share/extensions/Poly3DObjects/snub_cube.obj b/share/extensions/Poly3DObjects/snub_cube.obj new file mode 100644 index 0000000..de018af --- /dev/null +++ b/share/extensions/Poly3DObjects/snub_cube.obj @@ -0,0 +1,65 @@ +#Name:Snub Cube +#Type:face_specified +v -1.1426135 -0.33775397 -0.62122641 +v -1.1426135 0.33775397 0.62122641 +v -1.1426135 -0.62122641 0.33775397 +v -1.1426135 0.62122641 -0.33775397 +v 1.1426135 -0.33775397 0.62122641 +v 1.1426135 0.33775397 -0.62122641 +v 1.1426135 -0.62122641 -0.33775397 +v 1.1426135 0.62122641 0.33775397 +v -0.33775397 -1.1426135 0.62122641 +v -0.33775397 1.1426135 -0.62122641 +v -0.33775397 -0.62122641 -1.1426135 +v -0.33775397 0.62122641 1.1426135 +v 0.33775397 -1.1426135 -0.62122641 +v 0.33775397 1.1426135 0.62122641 +v 0.33775397 -0.62122641 1.1426135 +v 0.33775397 0.62122641 -1.1426135 +v -0.62122641 -1.1426135 -0.33775397 +v -0.62122641 1.1426135 0.33775397 +v -0.62122641 -0.33775397 1.1426135 +v -0.62122641 0.33775397 -1.1426135 +v 0.62122641 -1.1426135 0.33775397 +v 0.62122641 1.1426135 -0.33775397 +v 0.62122641 -0.33775397 -1.1426135 +v 0.62122641 0.33775397 1.1426135 + +f 3 1 17 +f 3 17 9 +f 3 19 2 +f 3 9 19 +f 1 4 20 +f 1 20 11 +f 1 11 17 +f 2 19 12 +f 2 18 4 +f 2 12 18 +f 4 18 10 +f 4 10 20 +f 17 11 13 +f 19 9 15 +f 18 12 14 +f 20 10 16 +f 9 21 15 +f 11 23 13 +f 12 24 14 +f 10 22 16 +f 13 23 7 +f 13 7 21 +f 15 21 5 +f 15 5 24 +f 16 22 6 +f 16 6 23 +f 14 24 8 +f 14 8 22 +f 21 7 5 +f 23 6 7 +f 24 5 8 +f 22 8 6 +f 1 3 2 4 +f 21 9 17 13 +f 24 12 19 15 +f 10 18 14 22 +f 11 20 16 23 +f 8 5 7 6 diff --git a/share/extensions/Poly3DObjects/snub_dodec.obj b/share/extensions/Poly3DObjects/snub_dodec.obj new file mode 100644 index 0000000..d830978 --- /dev/null +++ b/share/extensions/Poly3DObjects/snub_dodec.obj @@ -0,0 +1,156 @@ +#Name:Snub Dodecahedron +#Type:face_specified + +v -2.0502159 -0.64302961 0.17539263 +v 2.0502159 -0.64302961 -0.17539263 +v -1.6450691 0.64302961 1.2360806 +v 1.6450691 0.64302961 -1.2360806 +v -2.0927544 0.33092102 0.39812710 +v 2.0927544 0.33092102 -0.39812710 +v -1.3329632 1.6469179 -0.39812710 +v 1.3329632 1.6469179 0.39812710 +v -1.8252651 -0.33092102 1.0984232 +v 1.8252651 -0.33092102 -1.0984232 +v -0.62604653 1.7461864 -1.0984232 +v 0.62604653 1.7461864 1.0984232 +v -1.0622158 1.4540242 1.1853886 +v 1.0622158 1.4540242 -1.1853886 +v -1.9321359 0.84755005 -0.44288192 +v 1.9321359 0.84755005 0.44288192 +v -1.1448745 -0.84755005 1.6181953 +v 1.1448745 -0.84755005 -1.6181953 +v -1.5819879 -1.4540242 -0.17539263 +v 1.5819879 -1.4540242 0.17539263 +v -1.0574124 0.37482166 -1.8409298 +v 1.0574124 0.37482166 1.8409298 +v -0.43913786 -0.37482166 -2.0770897 +v 0.43913786 -0.37482166 2.0770897 +v -1.5624104 -1.2495038 0.80327387 +v 1.5624104 -1.2495038 -0.80327387 +v -1.8633072 -0.72833518 -0.80327387 +v 1.8633072 -0.72833518 0.80327387 +v -1.7000678 1.2495038 0.44288192 +v 1.7000678 1.2495038 -0.44288192 +v -0.72811404 -1.6469179 1.1853886 +v 0.72811404 -1.6469179 -1.1853886 +v -0.26565458 -1.7461864 -1.2360806 +v 0.26565458 -1.7461864 1.2360806 +v -0.75979117 -1.9778390 -0.39812710 +v 0.75979117 -1.9778390 0.39812710 +v -1.1992186 -1.4152654 -1.0984232 +v 1.1992186 -1.4152654 1.0984232 +v -1.7903298 0.19289371 -1.1853886 +v 1.7903298 0.19289371 1.1853886 +v -1.3064371 -0.56771537 -1.6181953 +v 1.3064371 -0.56771537 1.6181953 +v -0.85331128 0.72833518 1.8409298 +v 0.85331128 0.72833518 -1.8409298 +v -1.3794145 1.1031568 -1.2360806 +v 1.3794145 1.1031568 1.2360806 +v -0.10503615 0.56771537 -2.0770897 +v 0.10503615 0.56771537 2.0770897 +v -0.46822796 2.0970538 -0.17539263 +v 0.46822796 2.0970538 0.17539263 +v -0.30089684 1.9778390 0.80327387 +v 0.30089684 1.9778390 -0.80327387 +v -0.16156263 1.4152654 1.6181953 +v 0.16156263 1.4152654 -1.6181953 +v -0.54417401 -0.19289371 2.0770897 +v 0.54417401 -0.19289371 -2.0770897 +v -0.23206810 -2.0970538 0.44288192 +v 0.23206810 -2.0970538 -0.44288192 +v -0.20410113 -1.1031568 1.8409298 +v 0.20410113 -1.1031568 -1.8409298 + +f 5 1 9 +f 5 9 3 +f 5 29 15 +f 5 3 29 +f 1 27 19 +f 1 19 25 +f 1 25 9 +f 15 29 7 +f 15 45 39 +f 15 7 45 +f 27 39 41 +f 27 41 37 +f 27 37 19 +f 9 25 17 +f 39 45 21 +f 39 21 41 +f 29 3 13 +f 3 43 13 +f 19 37 35 +f 25 31 17 +f 45 7 11 +f 7 49 11 +f 41 21 23 +f 37 33 35 +f 17 31 59 +f 17 59 55 +f 13 43 53 +f 13 53 51 +f 21 47 23 +f 43 55 48 +f 43 48 53 +f 35 33 58 +f 35 58 57 +f 31 57 34 +f 31 34 59 +f 11 49 52 +f 11 52 54 +f 55 59 24 +f 55 24 48 +f 49 51 50 +f 49 50 52 +f 23 47 56 +f 23 56 60 +f 51 53 12 +f 51 12 50 +f 33 60 32 +f 33 32 58 +f 57 58 36 +f 57 36 34 +f 47 54 44 +f 47 44 56 +f 48 24 22 +f 54 52 14 +f 54 14 44 +f 60 56 18 +f 60 18 32 +f 34 36 38 +f 24 42 22 +f 50 12 8 +f 12 46 8 +f 32 18 26 +f 36 20 38 +f 44 14 4 +f 22 42 40 +f 22 40 46 +f 14 30 4 +f 18 10 26 +f 38 20 28 +f 38 28 42 +f 42 28 40 +f 8 46 16 +f 8 16 30 +f 46 40 16 +f 26 10 2 +f 26 2 20 +f 20 2 28 +f 4 30 6 +f 4 6 10 +f 30 16 6 +f 10 6 2 +f 39 27 1 5 15 +f 3 9 17 55 43 +f 51 49 7 29 13 +f 57 31 25 19 35 +f 47 21 45 11 54 +f 33 37 41 23 60 +f 42 24 59 34 38 +f 46 12 53 48 22 +f 36 58 32 26 20 +f 14 52 50 8 30 +f 44 4 10 18 56 +f 16 40 28 2 6 diff --git a/share/extensions/Poly3DObjects/szilassi.obj b/share/extensions/Poly3DObjects/szilassi.obj new file mode 100644 index 0000000..9dbce05 --- /dev/null +++ b/share/extensions/Poly3DObjects/szilassi.obj @@ -0,0 +1,24 @@ +#Face:Szilassi Polyhedron +#Type:face_specified +v -4.8 0. 4.8 +v -2.8 -1. 0.8 +v -2.8 0. 0.8 +v -1.8 1. 0.8 +v -1.5 -1.5 -1.2 +v -0.8 2. -3.2 +v 0. -5.04 -4.8 +v 0. 5.04 -4.8 +v 0.8 -2. -3.2 +v 1.5 1.5 -1.2 +v 1.8 -1. 0.8 +v 2.8 0. 0.8 +v 2.8 1. 0.8 +v 4.8 0. 4.8 + +f 4 10 6 1 14 13 +f 3 2 1 6 8 7 +f 5 10 4 3 7 9 +f 10 5 11 12 8 6 +f 12 13 14 9 7 8 +f 11 5 9 14 1 2 +f 13 12 11 2 3 4 diff --git a/share/extensions/Poly3DObjects/tet.obj b/share/extensions/Poly3DObjects/tet.obj new file mode 100644 index 0000000..3bd8f0e --- /dev/null +++ b/share/extensions/Poly3DObjects/tet.obj @@ -0,0 +1,12 @@ +#Name:Tetrahedron +#Type:face_specified + +v 0 0 0.61237244 +v -0.28867513 -0.50000000 -0.20412415 +v -0.28867513 0.50000000 -0.20412415 +v 0.57735027 0 -0.20412415 + +f 2 3 4 +f 3 2 1 +f 4 1 2 +f 1 4 3 diff --git a/share/extensions/Poly3DObjects/trunc_cube.obj b/share/extensions/Poly3DObjects/trunc_cube.obj new file mode 100644 index 0000000..1dbcfa6 --- /dev/null +++ b/share/extensions/Poly3DObjects/trunc_cube.obj @@ -0,0 +1,42 @@ +#Name:Truncated Cube +#Type:face_specified + +v -0.5 1.2071068 1.2071068 +v -0.5 1.2071068 -1.2071068 +v -0.5 -1.2071068 1.2071068 +v -0.5 -1.2071068 -1.2071068 +v 0.5 1.2071068 1.2071068 +v 0.5 1.2071068 -1.2071068 +v 0.5 -1.2071068 1.2071068 +v 0.5 -1.2071068 -1.2071068 +v 1.2071068 -0.5 1.2071068 +v 1.2071068 -0.5 -1.2071068 +v 1.2071068 0.5 1.2071068 +v 1.2071068 0.5 -1.2071068 +v 1.2071068 1.2071068 -0.5 +v 1.2071068 1.2071068 0.5 +v 1.2071068 -1.2071068 -0.5 +v 1.2071068 -1.2071068 0.5 +v -1.2071068 -0.5 1.2071068 +v -1.2071068 -0.5 -1.2071068 +v -1.2071068 0.5 1.2071068 +v -1.2071068 0.5 -1.2071068 +v -1.2071068 1.2071068 -0.5 +v -1.2071068 1.2071068 0.5 +v -1.2071068 -1.2071068 -0.5 +v -1.2071068 -1.2071068 0.5 + +f 6 12 10 8 4 18 20 2 +f 1 19 17 3 7 9 11 5 +f 3 24 23 4 8 15 16 7 +f 5 14 13 6 2 21 22 1 +f 9 16 15 10 12 13 14 11 +f 19 22 21 20 18 23 24 17 +f 16 9 7 +f 5 11 14 +f 3 17 24 +f 22 19 1 +f 8 10 15 +f 13 12 6 +f 23 18 4 +f 2 20 21 diff --git a/share/extensions/Poly3DObjects/trunc_dodec.obj b/share/extensions/Poly3DObjects/trunc_dodec.obj new file mode 100644 index 0000000..9a5743a --- /dev/null +++ b/share/extensions/Poly3DObjects/trunc_dodec.obj @@ -0,0 +1,96 @@ +#Name:Truncated Dodecahedron +#Type:face_specified + +v 0 -1.6180340 2.4898983 +v 0 -1.6180340 -2.4898983 +v 0 1.6180340 2.4898983 +v 0 1.6180340 -2.4898983 +v 0.42532540 -2.9270510 0.26286556 +v 0.42532540 2.9270510 0.26286556 +v 0.68819096 -2.1180340 1.9641672 +v 0.68819096 2.1180340 1.9641672 +v -2.7527638 0 -1.1135164 +v -2.0645729 -2.1180340 0.26286556 +v -2.0645729 2.1180340 0.26286556 +v -1.3763819 -2.6180340 -0.26286556 +v -1.3763819 2.6180340 -0.26286556 +v -0.68819096 -2.1180340 -1.9641672 +v -0.68819096 2.1180340 -1.9641672 +v 1.3763819 -2.6180340 0.26286556 +v 1.3763819 2.6180340 0.26286556 +v 2.7527638 0 1.1135164 +v 1.8017073 -1.3090170 -1.9641672 +v 1.8017073 1.3090170 -1.9641672 +v 2.0645729 -2.1180340 -0.26286556 +v 2.0645729 2.1180340 -0.26286556 +v 2.2270327 0 1.9641672 +v 2.2270327 -1.6180340 -1.1135164 +v 2.2270327 1.6180340 -1.1135164 +v -2.6523581 -1.3090170 0.26286556 +v -2.6523581 1.3090170 0.26286556 +v 2.6523581 -1.3090170 -0.26286556 +v 2.6523581 1.3090170 -0.26286556 +v 2.9152237 -0.5 0.26286556 +v 2.9152237 0.5 0.26286556 +v -2.9152237 -0.5 -0.26286556 +v -2.9152237 0.5 -0.26286556 +v 0.95105652 -1.3090170 2.4898983 +v 0.95105652 -1.3090170 -2.4898983 +v 0.95105652 1.3090170 2.4898983 +v 0.95105652 1.3090170 -2.4898983 +v 0.85065081 -2.6180340 1.1135164 +v 0.85065081 2.6180340 1.1135164 +v -0.95105652 -1.3090170 2.4898983 +v -0.95105652 -1.3090170 -2.4898983 +v -0.95105652 1.3090170 2.4898983 +v -0.95105652 1.3090170 -2.4898983 +v -1.5388418 -0.5 2.4898983 +v -1.5388418 -0.5 -2.4898983 +v -1.5388418 0.5 2.4898983 +v -1.5388418 0.5 -2.4898983 +v 1.5388418 -0.5 2.4898983 +v 1.5388418 -0.5 -2.4898983 +v 1.5388418 0.5 2.4898983 +v 1.5388418 0.5 -2.4898983 +v -2.2270327 0 -1.9641672 +v -2.2270327 -1.6180340 1.1135164 +v -2.2270327 1.6180340 1.1135164 +v -0.85065081 -2.6180340 -1.1135164 +v -0.85065081 2.6180340 -1.1135164 +v -1.8017073 -1.3090170 1.9641672 +v -1.8017073 1.3090170 1.9641672 +v -0.42532540 -2.9270510 -0.26286556 +v -0.42532540 2.9270510 -0.26286556 + +f 3 42 46 44 40 1 34 48 50 36 +f 47 43 4 37 51 49 35 2 41 45 +f 2 35 19 24 21 16 5 59 55 14 +f 49 51 20 25 29 31 30 28 24 19 +f 37 4 15 56 60 6 17 22 25 20 +f 43 47 52 9 33 27 11 13 56 15 +f 45 41 14 55 12 10 26 32 9 52 +f 6 60 13 11 54 58 42 3 8 39 +f 27 33 32 26 53 57 44 46 58 54 +f 10 12 59 5 38 7 1 40 57 53 +f 16 21 28 30 18 23 48 34 7 38 +f 31 29 22 17 39 8 36 50 23 18 +f 9 32 33 +f 18 30 31 +f 47 45 52 +f 50 48 23 +f 10 53 26 +f 27 54 11 +f 21 24 28 +f 29 25 22 +f 40 44 57 +f 58 46 42 +f 35 49 19 +f 20 51 37 +f 12 55 59 +f 60 56 13 +f 41 2 14 +f 15 4 43 +f 34 1 7 +f 8 3 36 +f 38 5 16 +f 17 6 39 diff --git a/share/extensions/Poly3DObjects/trunc_icos.obj b/share/extensions/Poly3DObjects/trunc_icos.obj new file mode 100644 index 0000000..4b535ba --- /dev/null +++ b/share/extensions/Poly3DObjects/trunc_icos.obj @@ -0,0 +1,96 @@ +#Name:Truncated Icosahedron +#Type:Face_specified + +v -0.16245985 -2.1180340 1.2759762 +v -0.16245985 2.1180340 1.2759762 +v 0.16245985 -2.1180340 -1.2759762 +v 0.16245985 2.1180340 -1.2759762 +v -0.26286556 -0.80901699 -2.3274384 +v -0.26286556 -2.4270510 -0.42532540 +v -0.26286556 0.80901699 -2.3274384 +v -0.26286556 2.4270510 -0.42532540 +v 0.26286556 -0.80901699 2.3274384 +v 0.26286556 -2.4270510 0.42532540 +v 0.26286556 0.80901699 2.3274384 +v 0.26286556 2.4270510 0.42532540 +v 0.68819096 -0.5 -2.3274384 +v 0.68819096 0.5 -2.3274384 +v 1.2139221 -2.1180340 0.42532540 +v 1.2139221 2.1180340 0.42532540 +v -2.0645729 -0.5 1.2759762 +v -2.0645729 0.5 1.2759762 +v -1.3763819 -1.0 1.8017073 +v -1.3763819 1.0 1.8017073 +v -1.3763819 -1.6180340 -1.2759762 +v -1.3763819 1.6180340 -1.2759762 +v -0.68819096 -0.5 2.3274384 +v -0.68819096 0.5 2.3274384 +v 1.3763819 -1.0 -1.8017073 +v 1.3763819 1.0 -1.8017073 +v 1.3763819 -1.6180340 1.2759762 +v 1.3763819 1.6180340 1.2759762 +v -1.7013016 0 -1.8017073 +v 1.7013016 0 1.8017073 +v -1.2139221 -2.1180340 -0.42532540 +v -1.2139221 2.1180340 -0.42532540 +v -1.9641672 -0.80901699 -1.2759762 +v -1.9641672 0.80901699 -1.2759762 +v 2.0645729 -0.5 -1.2759762 +v 2.0645729 0.5 -1.2759762 +v 2.2270327 -1.0 -0.42532540 +v 2.2270327 1.0 -0.42532540 +v 2.3894926 -0.5 0.42532540 +v 2.3894926 0.5 0.42532540 +v -1.1135164 -1.8090170 1.2759762 +v -1.1135164 1.8090170 1.2759762 +v 1.1135164 -1.8090170 -1.2759762 +v 1.1135164 1.8090170 -1.2759762 +v -2.3894926 -0.5 -0.42532540 +v -2.3894926 0.5 -0.42532540 +v -1.6392475 -1.8090170 0.42532540 +v -1.6392475 1.8090170 0.42532540 +v 1.6392475 -1.8090170 -0.42532540 +v 1.6392475 1.8090170 -0.42532540 +v 1.9641672 -0.80901699 1.2759762 +v 1.9641672 0.80901699 1.2759762 +v 0.85065081 0 2.3274384 +v -2.2270327 -1.0 0.42532540 +v -2.2270327 1.0 0.42532540 +v -0.85065081 0 -2.3274384 +v -0.52573111 -1.6180340 -1.8017073 +v -0.52573111 1.6180340 -1.8017073 +v 0.52573111 -1.6180340 1.8017073 +v 0.52573111 1.6180340 1.8017073 + +f 53 11 24 23 9 +f 51 39 40 52 30 +f 60 28 16 12 2 +f 20 42 48 55 18 +f 19 17 54 47 41 +f 1 10 15 27 59 +f 36 26 44 50 38 +f 4 58 22 32 8 +f 34 29 33 45 46 +f 21 57 3 6 31 +f 37 49 43 25 35 +f 13 5 56 7 14 +f 9 59 27 51 30 53 +f 53 30 52 28 60 11 +f 11 60 2 42 20 24 +f 24 20 18 17 19 23 +f 23 19 41 1 59 9 +f 13 25 43 3 57 5 +f 5 57 21 33 29 56 +f 56 29 34 22 58 7 +f 7 58 4 44 26 14 +f 14 26 36 35 25 13 +f 40 38 50 16 28 52 +f 16 50 44 4 8 12 +f 12 8 32 48 42 2 +f 48 32 22 34 46 55 +f 55 46 45 54 17 18 +f 54 45 33 21 31 47 +f 47 31 6 10 1 41 +f 10 6 3 43 49 15 +f 15 49 37 39 51 27 +f 39 37 35 36 38 40 diff --git a/share/extensions/Poly3DObjects/trunc_oct.obj b/share/extensions/Poly3DObjects/trunc_oct.obj new file mode 100644 index 0000000..0c7c8ad --- /dev/null +++ b/share/extensions/Poly3DObjects/trunc_oct.obj @@ -0,0 +1,42 @@ +#Name:Truncated Octahedron +#Type:face_specified + +v -1.5 -0.5 0 +v -1.5 0.5 0 +v -1. -1. -0.70710678 +v -1. -1. 0.70710678 +v -1. 1. -0.70710678 +v -1. 1. 0.70710678 +v -0.5 -1.5 0 +v -0.5 -0.5 -1.4142136 +v -0.5 -0.5 1.4142136 +v -0.5 0.5 -1.4142136 +v -0.5 0.5 1.4142136 +v -0.5 1.5 0 +v 0.5 -1.5 0 +v 0.5 -0.5 -1.4142136 +v 0.5 -0.5 1.4142136 +v 0.5 0.5 -1.4142136 +v 0.5 0.5 1.4142136 +v 0.5 1.5 0 +v 1. -1. -0.70710678 +v 1. -1. 0.70710678 +v 1. 1. -0.70710678 +v 1. 1. 0.70710678 +v 1.5 -0.5 0 +v 1.5 0.5 0 + +f 17 11 9 15 +f 14 8 10 16 +f 22 24 21 18 +f 12 5 2 6 +f 13 19 23 20 +f 4 1 3 7 +f 19 13 7 3 8 14 +f 15 9 4 7 13 20 +f 16 10 5 12 18 21 +f 22 18 12 6 11 17 +f 20 23 24 22 17 15 +f 14 16 21 24 23 19 +f 9 11 6 2 1 4 +f 3 1 2 5 10 8 \ No newline at end of file diff --git a/share/extensions/Poly3DObjects/trunc_tet.obj b/share/extensions/Poly3DObjects/trunc_tet.obj new file mode 100644 index 0000000..d2c9ceb --- /dev/null +++ b/share/extensions/Poly3DObjects/trunc_tet.obj @@ -0,0 +1,24 @@ +#Name:Truncated Tetrahedron +#Type:face_specified + +v 0 -1. -0.61237244 +v 0 1. -0.61237244 +v -0.57735027 -1. 0.20412415 +v -0.57735027 1. 0.20412415 +v -0.28867513 -0.5 1.0206207 +v -0.28867513 0.5 1.0206207 +v 0.57735027 0 1.0206207 +v 1.1547005 0 0.20412415 +v -0.86602540 -0.5 -0.61237244 +v -0.86602540 0.5 -0.61237244 +v 0.86602540 -0.5 -0.61237244 +v 0.86602540 0.5 -0.61237244 + +f 11 12 8 +f 3 9 1 +f 2 10 4 +f 6 5 7 +f 11 8 7 5 3 1 +f 2 4 6 7 8 12 +f 9 3 5 6 4 10 +f 2 12 11 1 9 10 \ No newline at end of file diff --git a/share/extensions/README.md b/share/extensions/README.md new file mode 100644 index 0000000..531b476 --- /dev/null +++ b/share/extensions/README.md @@ -0,0 +1,67 @@ +# Inkscape Extensions + +This folder contains the stock Inkscape extensions, i.e. the scripts that +implement some commands that you can use from within Inkscape. Most of +these commands are in the Extensions menu. + +## Installation + +These scripts should be installed with an Inkscape package already (if you have +installed Inkscape). For packagers or people testing newer releases, you can +install the files into /usr/share/inkscape/extensions or +~/.config/inkscape/extensions . + +## Testing + +These extensions are designed to have good test coverage for python 3.6 and above. + +You must install the program `pytest` in order to run these tests. You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run. + + pytest + pytest tests/test_my_extension.py + +See TESTING.md for further details. + +## Extension description + +Each *.inx file describes an extension, listing its name, purpose, +prerequisites, location within the menu, etc. These files are read by +Inkscape on launch. Other files are the scripts themselves (Perl, +Python, and Ruby are supported, as well as shell scripts). + +## Development + +Development of both the core inkex modules, tests and each of the extensions +contained within the core inkscape extensions repository should follow these +basic rules of quality assurance: + + * Use python3.6 or later, no python2 code would be used here. + * Use pylint to ensure code is written consistantly + * Have tests so that each line of an extension is covered in the coverage report + * Not cross streams between extensions, so your extension should import from + a module and not from another extension. + * Use translations on text for display to users using get text. + * Should not require external programs to work (with some exceptions) + +Also join the community on chat.inkscape.org channel #inkscape_extensions with any +doubts or problems. + +## Building Docs + +You may wish to compile to docs for use outside of the Inkscape docs, this can +be done with these commands: + + sphinx-apidoc -F -o source inkex + ./setup.py build_sphinx -s source + firefox ./build/sphinx/html/inkex.html + +All documentation should be included INSIDE of each python module. + +The latest documentation for master branch can be found at +https://inkscape.gitlab.io/extensions/documentation/. + +## License Requirements + +Only include extensions here which are GPL-compatible. This includes +Apache-2, MPL 1.1, certain Creative Commons licenses, and more. See +https://www.gnu.org/licenses/license-list.html for guidance. diff --git a/share/extensions/TESTING.md b/share/extensions/TESTING.md new file mode 100644 index 0000000..07158a6 --- /dev/null +++ b/share/extensions/TESTING.md @@ -0,0 +1,104 @@ +# Why Test Extensions + +Previously, Inkscape extensions were not tested for quality or correctness. But since 1.0, the extensions repository is far more strict about requiring tests and requiring tests to pass before changes can be merged in. + +You may find yourself being frustrated by the tests, especially if at first it doesn't make sense why they are failing. But these tests are important and I ask that everyone be as kind as they can to make sure the quality of the repository is maintained. + +# Running Tests + +You must install the program `pytest` in order to run these tests. Both Pytest and Pytest-Coverage are required to run tests. + +Usually the best way to install it is: + +```shell +$ pip3 install pytest pytest-cov +``` + +You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run. + +```shell +$ pytest +$ pytest tests/test_my_extension.py +``` + +You can also run tests until the first time they fail, and ask pytest to run the previously failed tests first. This can cut down how long pytest takes to run before hitting a failure. + +```shell +$ pytest -x --ff +``` + +More info here: https://docs.pytest.org/en/latest/getting-started.html + +# Test Files + +Each extension should have its own test file in the tests directory. This test may be a series of function tests or "comparison" tests. The comparison tests will fail whenever the output of an extension changes, so often they will need to be updated to reflect your changes. + +Usually the test file will be named `tests/test_{name_of_extension}.py` using the same name as the extension file itself. For tests covering inkex and other modules you may find test files have the format `tests/test_{package}_{module}.py` or similar. + +Each test can be run independently as shown in the previous section. + +# Test Data + +As well as python test files, each test will normally depend on additional data. From source svg files, to output comparison tests and other such things. + +This data is always held in `tests/data`, when writing tests, please make sure your data goes into the right directory. If you are updating the comparison test, usually you just need to rename the `export` file generated and remove the `.export` suffix to enable it. + +See tests/data/README.md for further information. + +# Writing or Updating tests + +You need to read the documentation available inside the tester module to learn how to write tests, or what the test code means. From a python3 terminal type: + +```python +from inkex import tester +help(tester) +``` + +# Coverage + +Coverage reports tell us how much of an extension is being exercised when tests are run. + +The latest coverage report for master branch can be found at +https://inkscape.gitlab.io/extensions/coverage/. + +To run a complete coverage report, you can specify the `--cov=.` option like so: + +```shell +$ pytest --cov=. --cov-report term +``` + +For a single extension coverage report, you can limit it further with: + +```shell +$ pytest --cov=my_extension.py --cov-report term +``` + +## Testing Options + +Tests can be run with these options that are provided as environment variables: + + FAIL_ON_DEPRECATION=1 - Will instantly fail any use of deprecated APIs + EXPORT_COMPARE=1 - Generate output files from comparisons. This is useful for manually checking the output as well as updating the comparison data. + NO_MOCK_COMMANDS=1 - Instead of using the mock data, actually call commands. This will also generate the msg files similar to export compare. + INKSCAPE_COMMAND=/other/inkscape - Use a different Inkscape (for example development version) while running commands. Works outside of tests too. + XML_DIFF=1 - Attempt to output an XML diff file, this can be useful for debugging to see differences in context. + DEBUG_KEY=1 - Export mock file keys for debugging. This is a highly specialised option for debugging key generation. + +For example: + +```shell +$ EXPORT_COMPARE=1 pytest +``` + +or + +```shell +export EXPORT_COMPARE=1 +pytest +``` + +# Testing custom extensions + +The same testing framework can be used in your own extension repositories by requiring the inkex module and using the inkex.tester module set. It should be available with Inkscape or can be installed via pypi. + +This is a great way of ensuring you have access to the same tools Inkscape uses to test, and makes it easier for your external extension to make its way to the core repository without resistance. diff --git a/share/extensions/addnodes.inx b/share/extensions/addnodes.inx new file mode 100644 index 0000000..8a3baa1 --- /dev/null +++ b/share/extensions/addnodes.inx @@ -0,0 +1,28 @@ + + + Add Nodes + org.inkscape.filter.add_nodes + + + + + 10.0 + + + + + + + + 2 + + + path + + + + + + diff --git a/share/extensions/addnodes.py b/share/extensions/addnodes.py new file mode 100755 index 0000000..2ccb60f --- /dev/null +++ b/share/extensions/addnodes.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005, 2007 Aaron Spike, aaron@ekips.org +# +# 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. +""" +This extension either adds nodes to a path so that + + No segment is longer than a maximum value OR that each segment is divided + into a given number of equal segments. + +""" +import math +import inkex + +from inkex import bezier, PathElement, CubicSuperPath + + +class AddNodes(inkex.EffectExtension): + """Extension to split a path by adding nodes to it""" + + def add_arguments(self, pars): + pars.add_argument( + "--segments", + type=int, + default=2, + help="Number of segments to divide the path into", + ) + pars.add_argument( + "--max", + type=float, + default=10.0, + help="Number of segments to divide the path into", + ) + pars.add_argument( + "--method", default="bymax", help="The kind of division to perform" + ) + pars.add_argument( + "--unit", default="px", help="Unit for maximum segment length" + ) + + def effect(self): + for node in self.svg.selection.filter(PathElement): + new = [] + for sub in node.path.to_superpath(): + new.append([sub[0][:]]) + i = 1 + while i <= len(sub) - 1: + length = bezier.cspseglength(new[-1][-1], sub[i]) + + if self.options.method == "bynum": + splits = self.options.segments + else: + maxlen = self.svg.viewport_to_unit( + f"{self.options.max}{self.options.unit}" + ) + splits = math.ceil(length / maxlen) + + for sel in range(int(splits), 1, -1): + result = bezier.cspbezsplitatlength( + new[-1][-1], sub[i], 1.0 / sel + ) + better_result = [ + [list(el) for el in elements] for elements in result + ] + new[-1][-1], nxt, sub[i] = better_result + new[-1].append(nxt[:]) + new[-1].append(sub[i]) + i += 1 + node.path = CubicSuperPath(new).to_path(curves_only=False) + + +if __name__ == "__main__": + AddNodes().run() diff --git a/share/extensions/aisvg.inx b/share/extensions/aisvg.inx new file mode 100644 index 0000000..46f4ed0 --- /dev/null +++ b/share/extensions/aisvg.inx @@ -0,0 +1,14 @@ + + + AI SVG Input + org.inkscape.input.aisvg + + .ai.svg + text/xml+svg + Adobe Illustrator SVG (*.ai.svg) + Cleans the cruft out of Adobe Illustrator SVGs before opening + + + aisvg.xslt + + diff --git a/share/extensions/aisvg.xslt b/share/extensions/aisvg.xslt new file mode 100644 index 0000000..15397da --- /dev/null +++ b/share/extensions/aisvg.xslt @@ -0,0 +1,36 @@ + + + + + + + + + + + + layer + + + + + + + + + + + + + + diff --git a/share/extensions/alphabet_soup/2.svg b/share/extensions/alphabet_soup/2.svg new file mode 100644 index 0000000..d198939 --- /dev/null +++ b/share/extensions/alphabet_soup/2.svg @@ -0,0 +1,11 @@ + + + + diff --git a/share/extensions/alphabet_soup/3.svg b/share/extensions/alphabet_soup/3.svg new file mode 100644 index 0000000..3c6d97d --- /dev/null +++ b/share/extensions/alphabet_soup/3.svg @@ -0,0 +1,11 @@ + + + + diff --git a/share/extensions/alphabet_soup/6.svg b/share/extensions/alphabet_soup/6.svg new file mode 100644 index 0000000..d05c508 --- /dev/null +++ b/share/extensions/alphabet_soup/6.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/7.svg b/share/extensions/alphabet_soup/7.svg new file mode 100644 index 0000000..e921bb5 --- /dev/null +++ b/share/extensions/alphabet_soup/7.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Cblob.svg b/share/extensions/alphabet_soup/Cblob.svg new file mode 100644 index 0000000..b5b104e --- /dev/null +++ b/share/extensions/alphabet_soup/Cblob.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Chook.svg b/share/extensions/alphabet_soup/Chook.svg new file mode 100644 index 0000000..2e3cf99 --- /dev/null +++ b/share/extensions/alphabet_soup/Chook.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Ctail.svg b/share/extensions/alphabet_soup/Ctail.svg new file mode 100644 index 0000000..54d55de --- /dev/null +++ b/share/extensions/alphabet_soup/Ctail.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Delta.svg b/share/extensions/alphabet_soup/Delta.svg new file mode 100644 index 0000000..82e60c3 --- /dev/null +++ b/share/extensions/alphabet_soup/Delta.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Eb.svg b/share/extensions/alphabet_soup/Eb.svg new file mode 100644 index 0000000..490671b --- /dev/null +++ b/share/extensions/alphabet_soup/Eb.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Eserif.svg b/share/extensions/alphabet_soup/Eserif.svg new file mode 100644 index 0000000..51e46b9 --- /dev/null +++ b/share/extensions/alphabet_soup/Eserif.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/share/extensions/alphabet_soup/Et.svg b/share/extensions/alphabet_soup/Et.svg new file mode 100644 index 0000000..49a3a5f --- /dev/null +++ b/share/extensions/alphabet_soup/Et.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/G.svg b/share/extensions/alphabet_soup/G.svg new file mode 100644 index 0000000..f7cd3cc --- /dev/null +++ b/share/extensions/alphabet_soup/G.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/IBSerif.svg b/share/extensions/alphabet_soup/IBSerif.svg new file mode 100644 index 0000000..dfb6987 --- /dev/null +++ b/share/extensions/alphabet_soup/IBSerif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/ITSerif.svg b/share/extensions/alphabet_soup/ITSerif.svg new file mode 100644 index 0000000..492aff5 --- /dev/null +++ b/share/extensions/alphabet_soup/ITSerif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Lb.svg b/share/extensions/alphabet_soup/Lb.svg new file mode 100644 index 0000000..3fa9f97 --- /dev/null +++ b/share/extensions/alphabet_soup/Lb.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Lt.svg b/share/extensions/alphabet_soup/Lt.svg new file mode 100644 index 0000000..1f4c18f --- /dev/null +++ b/share/extensions/alphabet_soup/Lt.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Ocross.svg b/share/extensions/alphabet_soup/Ocross.svg new file mode 100644 index 0000000..63b1caa --- /dev/null +++ b/share/extensions/alphabet_soup/Ocross.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Oterm.svg b/share/extensions/alphabet_soup/Oterm.svg new file mode 100644 index 0000000..e167a57 --- /dev/null +++ b/share/extensions/alphabet_soup/Oterm.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/P.svg b/share/extensions/alphabet_soup/P.svg new file mode 100644 index 0000000..0344082 --- /dev/null +++ b/share/extensions/alphabet_soup/P.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Q.svg b/share/extensions/alphabet_soup/Q.svg new file mode 100644 index 0000000..c60ea42 --- /dev/null +++ b/share/extensions/alphabet_soup/Q.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Rblock.svg b/share/extensions/alphabet_soup/Rblock.svg new file mode 100644 index 0000000..a2f4e9d --- /dev/null +++ b/share/extensions/alphabet_soup/Rblock.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Tb.svg b/share/extensions/alphabet_soup/Tb.svg new file mode 100644 index 0000000..2a75ac5 --- /dev/null +++ b/share/extensions/alphabet_soup/Tb.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/share/extensions/alphabet_soup/Tt.svg b/share/extensions/alphabet_soup/Tt.svg new file mode 100644 index 0000000..04d2a18 --- /dev/null +++ b/share/extensions/alphabet_soup/Tt.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/share/extensions/alphabet_soup/U.svg b/share/extensions/alphabet_soup/U.svg new file mode 100644 index 0000000..e8b8244 --- /dev/null +++ b/share/extensions/alphabet_soup/U.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Vser.svg b/share/extensions/alphabet_soup/Vser.svg new file mode 100644 index 0000000..a06b247 --- /dev/null +++ b/share/extensions/alphabet_soup/Vser.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Xh.svg b/share/extensions/alphabet_soup/Xh.svg new file mode 100644 index 0000000..c60f304 --- /dev/null +++ b/share/extensions/alphabet_soup/Xh.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Xne.svg b/share/extensions/alphabet_soup/Xne.svg new file mode 100644 index 0000000..9dc54f1 --- /dev/null +++ b/share/extensions/alphabet_soup/Xne.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Xnw.svg b/share/extensions/alphabet_soup/Xnw.svg new file mode 100644 index 0000000..98cd8bc --- /dev/null +++ b/share/extensions/alphabet_soup/Xnw.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Xvb.svg b/share/extensions/alphabet_soup/Xvb.svg new file mode 100644 index 0000000..16e80b4 --- /dev/null +++ b/share/extensions/alphabet_soup/Xvb.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/Xvt.svg b/share/extensions/alphabet_soup/Xvt.svg new file mode 100644 index 0000000..3a5c5dc --- /dev/null +++ b/share/extensions/alphabet_soup/Xvt.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/a.svg b/share/extensions/alphabet_soup/a.svg new file mode 100644 index 0000000..284de78 --- /dev/null +++ b/share/extensions/alphabet_soup/a.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/abase.svg b/share/extensions/alphabet_soup/abase.svg new file mode 100644 index 0000000..1da2bb1 --- /dev/null +++ b/share/extensions/alphabet_soup/abase.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/acap.svg b/share/extensions/alphabet_soup/acap.svg new file mode 100644 index 0000000..dfc7ede --- /dev/null +++ b/share/extensions/alphabet_soup/acap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/b.svg b/share/extensions/alphabet_soup/b.svg new file mode 100644 index 0000000..fd01a26 --- /dev/null +++ b/share/extensions/alphabet_soup/b.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/bar.svg b/share/extensions/alphabet_soup/bar.svg new file mode 100644 index 0000000..8b477e3 --- /dev/null +++ b/share/extensions/alphabet_soup/bar.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/bar2.svg b/share/extensions/alphabet_soup/bar2.svg new file mode 100644 index 0000000..39ed825 --- /dev/null +++ b/share/extensions/alphabet_soup/bar2.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/barcap.svg b/share/extensions/alphabet_soup/barcap.svg new file mode 100644 index 0000000..5831e83 --- /dev/null +++ b/share/extensions/alphabet_soup/barcap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/c.svg b/share/extensions/alphabet_soup/c.svg new file mode 100644 index 0000000..c6261a0 --- /dev/null +++ b/share/extensions/alphabet_soup/c.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/cross.svg b/share/extensions/alphabet_soup/cross.svg new file mode 100644 index 0000000..89b67fe --- /dev/null +++ b/share/extensions/alphabet_soup/cross.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/cserif.svg b/share/extensions/alphabet_soup/cserif.svg new file mode 100644 index 0000000..14669a0 --- /dev/null +++ b/share/extensions/alphabet_soup/cserif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/e.svg b/share/extensions/alphabet_soup/e.svg new file mode 100644 index 0000000..03106dd --- /dev/null +++ b/share/extensions/alphabet_soup/e.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/epsilon.svg b/share/extensions/alphabet_soup/epsilon.svg new file mode 100644 index 0000000..a2dd33e --- /dev/null +++ b/share/extensions/alphabet_soup/epsilon.svg @@ -0,0 +1,8 @@ + + + diff --git a/share/extensions/alphabet_soup/f.svg b/share/extensions/alphabet_soup/f.svg new file mode 100644 index 0000000..c0f94c3 --- /dev/null +++ b/share/extensions/alphabet_soup/f.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/share/extensions/alphabet_soup/gamma.svg b/share/extensions/alphabet_soup/gamma.svg new file mode 100644 index 0000000..feb6b36 --- /dev/null +++ b/share/extensions/alphabet_soup/gamma.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/h.svg b/share/extensions/alphabet_soup/h.svg new file mode 100644 index 0000000..23be380 --- /dev/null +++ b/share/extensions/alphabet_soup/h.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/h2.svg b/share/extensions/alphabet_soup/h2.svg new file mode 100644 index 0000000..636b4df --- /dev/null +++ b/share/extensions/alphabet_soup/h2.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/hcap.svg b/share/extensions/alphabet_soup/hcap.svg new file mode 100644 index 0000000..a6048b6 --- /dev/null +++ b/share/extensions/alphabet_soup/hcap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/idot.svg b/share/extensions/alphabet_soup/idot.svg new file mode 100644 index 0000000..d3d0dad --- /dev/null +++ b/share/extensions/alphabet_soup/idot.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/j.svg b/share/extensions/alphabet_soup/j.svg new file mode 100644 index 0000000..07c6805 --- /dev/null +++ b/share/extensions/alphabet_soup/j.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/k.svg b/share/extensions/alphabet_soup/k.svg new file mode 100644 index 0000000..314f2b0 --- /dev/null +++ b/share/extensions/alphabet_soup/k.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/l.svg b/share/extensions/alphabet_soup/l.svg new file mode 100644 index 0000000..00beccf --- /dev/null +++ b/share/extensions/alphabet_soup/l.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/lserif.svg b/share/extensions/alphabet_soup/lserif.svg new file mode 100644 index 0000000..7ab2c0d --- /dev/null +++ b/share/extensions/alphabet_soup/lserif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/m.svg b/share/extensions/alphabet_soup/m.svg new file mode 100644 index 0000000..ce3cd05 --- /dev/null +++ b/share/extensions/alphabet_soup/m.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/mcap.svg b/share/extensions/alphabet_soup/mcap.svg new file mode 100644 index 0000000..25c8c8a --- /dev/null +++ b/share/extensions/alphabet_soup/mcap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/n.svg b/share/extensions/alphabet_soup/n.svg new file mode 100644 index 0000000..420042a --- /dev/null +++ b/share/extensions/alphabet_soup/n.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/o.svg b/share/extensions/alphabet_soup/o.svg new file mode 100644 index 0000000..3c08f07 --- /dev/null +++ b/share/extensions/alphabet_soup/o.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/ocap.svg b/share/extensions/alphabet_soup/ocap.svg new file mode 100644 index 0000000..1c50fd2 --- /dev/null +++ b/share/extensions/alphabet_soup/ocap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/question.svg b/share/extensions/alphabet_soup/question.svg new file mode 100644 index 0000000..ddecb15 --- /dev/null +++ b/share/extensions/alphabet_soup/question.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/r.svg b/share/extensions/alphabet_soup/r.svg new file mode 100644 index 0000000..bb2273a --- /dev/null +++ b/share/extensions/alphabet_soup/r.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/rcap.svg b/share/extensions/alphabet_soup/rcap.svg new file mode 100644 index 0000000..e835f50 --- /dev/null +++ b/share/extensions/alphabet_soup/rcap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/s.svg b/share/extensions/alphabet_soup/s.svg new file mode 100644 index 0000000..dc7c6fc --- /dev/null +++ b/share/extensions/alphabet_soup/s.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/serif.svg b/share/extensions/alphabet_soup/serif.svg new file mode 100644 index 0000000..d2bf55e --- /dev/null +++ b/share/extensions/alphabet_soup/serif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/t.svg b/share/extensions/alphabet_soup/t.svg new file mode 100644 index 0000000..7940a68 --- /dev/null +++ b/share/extensions/alphabet_soup/t.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/share/extensions/alphabet_soup/tserif.svg b/share/extensions/alphabet_soup/tserif.svg new file mode 100644 index 0000000..f04cfcf --- /dev/null +++ b/share/extensions/alphabet_soup/tserif.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/v.svg b/share/extensions/alphabet_soup/v.svg new file mode 100644 index 0000000..9175807 --- /dev/null +++ b/share/extensions/alphabet_soup/v.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/vcap.svg b/share/extensions/alphabet_soup/vcap.svg new file mode 100644 index 0000000..792989e --- /dev/null +++ b/share/extensions/alphabet_soup/vcap.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/vserl.svg b/share/extensions/alphabet_soup/vserl.svg new file mode 100644 index 0000000..10e32d3 --- /dev/null +++ b/share/extensions/alphabet_soup/vserl.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/vserr.svg b/share/extensions/alphabet_soup/vserr.svg new file mode 100644 index 0000000..964ae97 --- /dev/null +++ b/share/extensions/alphabet_soup/vserr.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/x.svg b/share/extensions/alphabet_soup/x.svg new file mode 100644 index 0000000..f40b0a9 --- /dev/null +++ b/share/extensions/alphabet_soup/x.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/y.svg b/share/extensions/alphabet_soup/y.svg new file mode 100644 index 0000000..089cec9 --- /dev/null +++ b/share/extensions/alphabet_soup/y.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/yogh.svg b/share/extensions/alphabet_soup/yogh.svg new file mode 100644 index 0000000..6e6f19d --- /dev/null +++ b/share/extensions/alphabet_soup/yogh.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/alphabet_soup/z.svg b/share/extensions/alphabet_soup/z.svg new file mode 100644 index 0000000..7826d59 --- /dev/null +++ b/share/extensions/alphabet_soup/z.svg @@ -0,0 +1,10 @@ + + + + diff --git a/share/extensions/barcode/Base.py b/share/extensions/barcode/Base.py new file mode 100644 index 0000000..024213c --- /dev/null +++ b/share/extensions/barcode/Base.py @@ -0,0 +1,171 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Martin Owens +# +# 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, USA. +# +""" +Base module for rendering barcodes for Inkscape. +""" + +import itertools +import sys + +from inkex import Group, TextElement, Rectangle +from inkex.localization import inkex_gettext as _ + +(TEXT_POS_BOTTOM, TEXT_POS_TOP) = range(2) +(WHITE_BAR, BLACK_BAR, TALL_BAR) = range(3) +TEXT_TEMPLATE = "font-size:%dpx;text-align:center;text-anchor:middle;" + +try: + from typing import Optional +except ImportError: + pass + + +class Barcode(object): + """Provide a base class for all barcode renderers""" + + default_height = 30 + font_size = 9 + name = None # type: Optional[str] + + def error(self, text, msg): + """Cause an error to be reported""" + sys.stderr.write( + _("Error encoding '{}' as {} barcode: {}\n").format(text, self.name, msg) + ) + return "ERROR" + + def encode(self, text): + """ + Replace this with the encoding function, it should return + a string of ones and zeros + """ + raise NotImplementedError("You need to write an encode() function.") + + def __init__(self, param): + param = param or {} + self.document = param.get("document", None) + self.known_ids = [] + self._extra = [] + + self.pos_x = int(param.get("x", 0)) + self.pos_y = int(param.get("y", 0)) + self.text = param.get("text", None) + self.scale = param.get("scale", 1) + self.height = param.get("height", self.default_height) + self.pos_text = param.get("text_pos", TEXT_POS_BOTTOM) + + if self.document: + self.known_ids = list(self.document.xpath("//@id")) + + if not self.text: + raise ValueError(_("No string specified for barcode.")) + + def get_id(self, name="element"): + """Get the next useful id (and claim it)""" + index = 0 + while name in self.known_ids: + index += 1 + name = "barcode{:d}".format(index) + self.known_ids.append(name) + return name + + def add_extra_barcode(self, barcode, **kw): + """Add an extra barcode along side this one, used for ean13 extras""" + from . import get_barcode + + kw["height"] = self.height + kw["document"] = self.document + kw["scale"] = None + self._extra.append(get_barcode(barcode, **kw).generate()) + + def generate(self): + """Generate the actual svg from the coding""" + string = self.encode(self.text) + + if string == "ERROR": + return + + name = self.get_id("barcode") + + # use an svg group element to contain the barcode + barcode = Group() + barcode.set("id", name) + barcode.set("style", "fill: black;") + + barcode.transform.add_translate(self.pos_x, self.pos_y) + if self.scale: + barcode.transform.add_scale(self.scale) + + bar_id = 1 + bar_offset = 0 + tops = set() + + for datum in self.graphical_array(string): + # Datum 0 tells us what style of bar is to come next + style = self.get_style(int(datum[0])) + # Datum 1 tells us what width in units, + # style tells us how wide a unit is + width = int(datum[1]) * int(style["width"]) + + if style["write"]: + tops.add(style["top"]) + rect = Rectangle() + rect.set("x", str(bar_offset)) + rect.set("y", str(style["top"])) + if self.pos_text == TEXT_POS_TOP: + rect.set("y", str(style["top"] + self.font_size)) + rect.set("id", "{}_bar{:d}".format(name, bar_id)) + rect.set("width", str(width)) + rect.set("height", str(style["height"])) + barcode.append(rect) + bar_offset += width + bar_id += 1 + + for extra in self._extra: + if extra is not None: + barcode.append(extra) + + bar_width = bar_offset + # Add text at the bottom of the barcode + text = TextElement() + text.set("x", str(int(bar_width / 2))) + text.set("y", str(min(tops) + self.font_size - 1)) + if self.pos_text == TEXT_POS_BOTTOM: + text.set("y", str(self.height + max(tops) + self.font_size)) + text.set("style", TEXT_TEMPLATE % self.font_size) + text.set("xml:space", "preserve") + text.set("id", "{}_text".format(name)) + text.text = str(self.text) + barcode.append(text) + return barcode + + def graphical_array(self, code): + """Converts black and white markets into a space array""" + return [(x, len(list(y))) for x, y in itertools.groupby(code)] + + def get_style(self, index): + """Returns the styles that should be applied to each bar""" + result = {"width": 1, "top": 0, "write": True} + if index == BLACK_BAR: + result["height"] = int(self.height) + if index == TALL_BAR: + result["height"] = int(self.height) + int(self.font_size / 2) + if index == WHITE_BAR: + result["write"] = False + return result diff --git a/share/extensions/barcode/BaseEan.py b/share/extensions/barcode/BaseEan.py new file mode 100644 index 0000000..d1ab58e --- /dev/null +++ b/share/extensions/barcode/BaseEan.py @@ -0,0 +1,204 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Martin Owens +# +# 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, USA. +# +""" +Some basic common code shared between EAN and UCP generators. +""" + +from .Base import Barcode, TEXT_POS_TOP +from inkex.localization import inkex_gettext as _ + +try: + from typing import Optional, List, Dict +except ImportError: + pass + +MAPPING = [ + # Left side of barcode Family '0' + [ + "0001101", + "0011001", + "0010011", + "0111101", + "0100011", + "0110001", + "0101111", + "0111011", + "0110111", + "0001011", + ], + # Left side of barcode Family '1' and flipped to right side. + [ + "0100111", + "0110011", + "0011011", + "0100001", + "0011101", + "0111001", + "0000101", + "0010001", + "0001001", + "0010111", + ], +] +# This chooses which of the two encodings above to use. +FAMILIES = ( + "000000", + "001011", + "001101", + "001110", + "010011", + "011001", + "011100", + "010101", + "010110", + "011010", +) + + +class EanBarcode(Barcode): + """Simple base class for all EAN type barcodes""" + + lengths = None # type: Optional[List[int]] + length = None # type: Optional[int] + checks = [] # type: List[int] + extras = {} # type: Dict[int, str] + magic = 10 + guard_bar = "202" + center_bar = "02020" + + @staticmethod + def intarray(number): + """Convert a string of digits into an array of ints""" + return [int(i) for i in number] + + @staticmethod + def encode_interleaved(family, number, fams=FAMILIES): + """Encode any side of the barcode, interleaved""" + result = [] + encset = EanBarcode.intarray(fams[family]) + for i, _ in enumerate(number): + thismap = MAPPING[encset[i]] + result.append(thismap[number[i]]) + return result + + @staticmethod + def encode_right(number): + """Encode the right side of the barcode, non-interleaved""" + result = [] + for num in number: + # The right side is always the reverse of the left's family '1' + result.append(MAPPING[1][num][::-1]) + return result + + @staticmethod + def encode_left(number): + """Encode the left side of the barcode, non-interleaved""" + result = [] + for num in number: + result.append(MAPPING[0][num]) + return result + + @staticmethod + def space(*spacing): + """Space out an array of numbers""" + result = "" + for space in spacing: + if isinstance(space, list): + for i in space: + result += str(i) + elif isinstance(space, int): + result += " " * space + return result + + def get_lengths(self): + """Return a list of acceptable lengths""" + if self.length: + return [self.length] + return self.lengths[:] + + def encode(self, text): + """Encode any EAN barcode""" + code = text.replace(" ", "").strip() + guide = code.endswith(">") + code = code.strip(">") + + if not code.isdigit(): + return self.error(code, _("Not a Number, must be digits 0-9 only")) + lengths = self.get_lengths() + self.checks + + # Allow extra barcodes after the first one + if len(code) not in lengths: + for extra in self.extras: + sep = len(code) - extra + if sep in lengths: + # Generate a barcode along side this one. + self.add_extra_barcode( + self.extras[extra], + text=code[sep:], + x=self.pos_x + 400 * self.scale, + text_pos=TEXT_POS_TOP, + ) + code = code[:sep] + + if len(code) not in lengths: + return self.error( + code, + _("Wrong size {:d}, must be {} digits").format( + len(code), ", ".join([str(length) for length in lengths]) + ), + ) + + if self.checks: + if len(code) not in self.checks: + code = self.append_checksum(code) + elif not self.verify_checksum(code): + return self.error(code, _("Checksum failed, omit for new sum")) + return self._encode(EanBarcode.intarray(code), guide=guide) + + def _encode(self, num, guide=False): + """ + Write your EAN encoding function, it's passed in an array of int and + it should return a string on 1 and 0 for black and white parts + """ + raise NotImplementedError("_encode should be provided by parent EAN") + + def enclose(self, left, right=()): + """Standard Enclosure""" + parts = [self.guard_bar] + left + parts.append(self.center_bar) + parts += list(right) + [self.guard_bar] + return "".join(parts) + + def get_checksum(self, num): + """Generate a UPCA/EAN13/EAN8 Checksum""" + # Left to right,checksum based on first digits. + total = sum([int(n) * (3, 1)[x % 2] for x, n in enumerate(num[::-1])]) + # Modulous result to a single digit checksum + checksum = self.magic - (total % self.magic) + if checksum < 0 or checksum >= self.magic: + return "0" + return str(checksum) + + def append_checksum(self, number): + """Apply the checksum to a short number""" + return number + self.get_checksum(number) + + def verify_checksum(self, number): + """Verify any checksum""" + return self.get_checksum(number[:-1]) == number[-1] diff --git a/share/extensions/barcode/Code128.py b/share/extensions/barcode/Code128.py new file mode 100644 index 0000000..e5f8701 --- /dev/null +++ b/share/extensions/barcode/Code128.py @@ -0,0 +1,246 @@ +# coding=utf-8 +# +# Authored by Martin Owens +# Debugged by Ralf Heinecke & Martin Siepmann 2007-09-07 +# Horst Schottky 2010-02-27 +# +# Copyright (C) 2007 Martin Owens +# +# 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, USA. +# +""" +Renderer for Code128/EAN128 codes. Designed for use with Inkscape. +""" + +import re + +from .Base import Barcode + +CODE_MAP = [ + "11011001100", + "11001101100", + "11001100110", + "10010011000", + "10010001100", + "10001001100", + "10011001000", + "10011000100", + "10001100100", + "11001001000", + "11001000100", + "11000100100", + "10110011100", + "10011011100", + "10011001110", + "10111001100", + "10011101100", + "10011100110", + "11001110010", + "11001011100", + "11001001110", + "11011100100", + "11001110100", + "11101101110", + "11101001100", + "11100101100", + "11100100110", + "11101100100", + "11100110100", + "11100110010", + "11011011000", + "11011000110", + "11000110110", + "10100011000", + "10001011000", + "10001000110", + "10110001000", + "10001101000", + "10001100010", + "11010001000", + "11000101000", + "11000100010", + "10110111000", + "10110001110", + "10001101110", + "10111011000", + "10111000110", + "10001110110", + "11101110110", + "11010001110", + "11000101110", + "11011101000", + "11011100010", + "11011101110", + "11101011000", + "11101000110", + "11100010110", + "11101101000", + "11101100010", + "11100011010", + "11101111010", + "11001000010", + "11110001010", + "10100110000", + "10100001100", + "10010110000", + "10010000110", + "10000101100", + "10000100110", + "10110010000", + "10110000100", + "10011010000", + "10011000010", + "10000110100", + "10000110010", + "11000010010", + "11001010000", + "11110111010", + "11000010100", + "10001111010", + "10100111100", + "10010111100", + "10010011110", + "10111100100", + "10011110100", + "10011110010", + "11110100100", + "11110010100", + "11110010010", + "11011011110", + "11011110110", + "11110110110", + "10101111000", + "10100011110", + "10001011110", + "10111101000", + "10111100010", + "11110101000", + "11110100010", + "10111011110", + "10111101110", + "11101011110", + "11110101110", + "11010000100", + "11010010000", + "11010011100", + "11000111010", + "11", +] + + +def map_extra(data, chars): + """Maps the data into the chars""" + result = list(data) + for char in chars: + result.append(chr(char)) + result.append("FNC3") + result.append("FNC2") + result.append("SHIFT") + return result + + +# The map_extra method is used to slim down the amount +# of pre code and instead we generate the lists +CHAR_AB = list(" !\"#$%&'()*+,-./0123456789:;<=>?@" "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_") +CHAR_A = map_extra(CHAR_AB, range(0, 31)) # Offset 64 +CHAR_B = map_extra(CHAR_AB, range(96, 127)) # Offset -32 + + +class Code128(Barcode): + """Main barcode object, generates the encoding bits here""" + + def encode(self, text): + blocks = [] + block = "" + + # Split up into sections of numbers, or characters + # This makes sure that all the characters are encoded + # In the best way possible for Code128 + for datum in re.findall(r"(?:(?:\d\d){2,})|(?:^\d\d)|.", text): + if len(datum) == 1: + block = block + datum + else: + if block: + blocks.append(self.best_block(block)) + block = "" + blocks.append(["C", datum]) + + if block: + blocks.append(Code128.best_block(block)) + block = "" + + return Code128.encode_blocks(blocks) + + @staticmethod + def best_block(block): + """If this has characters above 63, select B over A""" + if any(ord(x) > 63 for x in block): + return ["B", block] + return ["A", block] + + @staticmethod + def encode_blocks(blocks): + """Encode the given blocks into A, B or C codes""" + encode = "" + total = 0 + pos = 0 + + for block in blocks: + b_set = block[0] + datum = block[1] + + # POS : 0, 1 + # A : 101, 103 + # B : 100, 104 + # C : 99, 105 + num = 0 + if b_set == "A": + num = 103 + elif b_set == "B": + num = 104 + elif b_set == "C": + num = 105 + + i = pos + if pos: + num = 204 - num + else: + i = 1 + + total = total + num * i + encode = encode + CODE_MAP[num] + pos += 1 + + if b_set in ("A", "B"): + chars = CHAR_B + if b_set == "A": + chars = CHAR_A + + for char in datum: + total = total + (chars.index(char) * pos) + encode = encode + CODE_MAP[chars.index(char)] + pos += 1 + else: + for char in (datum[i : i + 2] for i in range(0, len(datum), 2)): + total = total + (int(char) * pos) + encode = encode + CODE_MAP[int(char)] + pos += 1 + + checksum = total % 103 + encode = encode + CODE_MAP[checksum] + encode = encode + CODE_MAP[106] + encode = encode + CODE_MAP[107] + + return encode diff --git a/share/extensions/barcode/Code25i.py b/share/extensions/barcode/Code25i.py new file mode 100644 index 0000000..adc0161 --- /dev/null +++ b/share/extensions/barcode/Code25i.py @@ -0,0 +1,71 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Geoffrey Mosini +# +# 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, USA. +# +""" +Generate barcodes for Code25-interleaved 2 of 5, for Inkscape. +""" + +from .Base import Barcode +from inkex.localization import inkex_gettext as _ + +# 1 means thick, 0 means thin +ENCODE = { + "0": "00110", + "1": "10001", + "2": "01001", + "3": "11000", + "4": "00101", + "5": "10100", + "6": "01100", + "7": "00011", + "8": "10010", + "9": "01010", +} + + +class Code25i(Barcode): + """Convert a text into string binary of black and white markers""" + + # Start and stop code are already encoded into white (0) and black(1) bars + def encode(self, text): + if not text.isdigit(): + return self.error(text, _("CODE25 can only encode numbers.")) + number = text + + # Number of figures to encode must be even, + # a 0 is added to the left in case it's odd. + if len(number) % 2 > 0: + number = "0" + number + + # Number is encoded by pairs of 2 figures + size = len(number) // 2 + encoded = "1010" + for i in range(size): + # First in the pair is encoded in black (1), second in white (0) + black = ENCODE[number[i * 2]] + white = ENCODE[number[i * 2 + 1]] + for j in range(5): + if black[j] == "1": + encoded += "11" + else: + encoded += "1" + if white[j] == "1": + encoded += "00" + else: + encoded += "0" + return encoded + "1101" diff --git a/share/extensions/barcode/Code39.py b/share/extensions/barcode/Code39.py new file mode 100644 index 0000000..87f346a --- /dev/null +++ b/share/extensions/barcode/Code39.py @@ -0,0 +1,98 @@ +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for Code39 barcodes. Designed for use with Inkscape. +""" + +from .Base import Barcode + +ENCODE = { + "0": "000110100", + "1": "100100001", + "2": "001100001", + "3": "101100000", + "4": "000110001", + "5": "100110000", + "6": "001110000", + "7": "000100101", + "8": "100100100", + "9": "001100100", + "A": "100001001", + "B": "001001001", + "C": "101001000", + "D": "000011001", + "E": "100011000", + "F": "001011000", + "G": "000001101", + "H": "100001100", + "I": "001001100", + "J": "000011100", + "K": "100000011", + "L": "001000011", + "M": "101000010", + "N": "000010011", + "O": "100010010", + "P": "001010010", + "Q": "000000111", + "R": "100000110", + "S": "001000110", + "T": "000010110", + "U": "110000001", + "V": "011000001", + "W": "111000000", + "X": "010010001", + "Y": "110010000", + "Z": "011010000", + "-": "010000101", + "*": "010010100", + "+": "010001010", + "$": "010101000", + "%": "000101010", + "/": "010100010", + ".": "110000100", + " ": "011000100", +} + + +class Code39(Barcode): + """Convert a text into string binary of black and white markers""" + + def encode(self, text): + self.text = text.upper() + result = "" + # It is possible for us to encode code39 + # into full ascii, but this feature is + # not enabled here + for char in "*" + self.text + "*": + if char not in ENCODE: + char = "-" + result = result + ENCODE[char] + "0" + + # Now we need to encode the code39, best read + # the code to understand what it's up to: + encoded = "" + colour = "1" # 1 = Black, 0 = White + for data in result: + if data == "1": + encoded = encoded + colour + colour + else: + encoded = encoded + colour + colour = "0" if colour == "1" else "1" + + return encoded diff --git a/share/extensions/barcode/Code39Ext.py b/share/extensions/barcode/Code39Ext.py new file mode 100644 index 0000000..d990680 --- /dev/null +++ b/share/extensions/barcode/Code39Ext.py @@ -0,0 +1,97 @@ +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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. +# +""" +Python barcode renderer for Code39 Extended barcodes. Designed for Inkscape. +""" + +from .Code39 import Code39 + +encode = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + +charmap = {} + +i = 0 +for char in encode: + charmap[char] = i + i += 1 + + +def get_map(array): + """Extended encoding maps for full ASCII Code93""" + result = {} + for y, x in enumerate(array): + result[chr(x)] = encode[y] + + return result + + +# MapA is eclectic, but B, C, D are all ASCII ranges +mapA = get_map( + [ + 27, + 28, + 29, + 30, + 31, + 59, + 60, + 61, + 62, + 63, + 91, + 92, + 93, + 94, + 95, + 123, + 124, + 125, + 126, + 127, + 0, + 64, + 96, + 127, + 127, + 127, + ] +) # % +mapB = get_map(range(1, 26)) # $ +mapC = get_map(range(33, 58)) # / +mapD = get_map(range(97, 122)) # + + + +class Code39Ext(Code39): + """Render Code39 Barcodes""" + + def encode(self, text): + # We are only going to extend the Code39 barcodes + result = "" + for character in text: + if character in mapA: + character = "%" + mapA[character] + elif character in mapB: + character = "$" + mapB[character] + elif character in mapC: + character = "/" + mapC[character] + elif character in mapD: + character = "+" + mapD[character] + result = result + character + + return Code39.encode(self, result) diff --git a/share/extensions/barcode/Code93.py b/share/extensions/barcode/Code93.py new file mode 100644 index 0000000..1417b3e --- /dev/null +++ b/share/extensions/barcode/Code93.py @@ -0,0 +1,187 @@ +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for Code93 barcodes. Designed for use with Inkscape. +""" + +from .Base import Barcode + +PALLET = list("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%") +PALLET.append("($)") +PALLET.append("(/)") +PALLET.append("(+)") +PALLET.append("(%)") +PALLET.append("MARKER") + +MAP = dict((PALLET[i], i) for i in range(len(PALLET))) + + +def get_map(array): + """Extended ENCODE maps for full ASCII Code93""" + result = {} + pos = 10 + for char in array: + result[chr(char)] = PALLET[pos] + pos += 1 + return result + + +# MapA is eclectic, but B, C, D are all ASCII ranges +MAP_A = get_map( + [ + 27, + 28, + 29, + 30, + 31, + 59, + 60, + 61, + 62, + 63, + 91, + 92, + 93, + 94, + 95, + 123, + 124, + 125, + 126, + 127, + 0, + 64, + 96, + 127, + 127, + 127, + ] +) # % +MAP_B = get_map(range(1, 26)) # $ +MAP_C = get_map(range(33, 58)) # / +MAP_D = get_map(range(97, 122)) # + + +ENCODE = [ + "100010100", + "101001000", + "101000100", + "101000010", + "100101000", + "100100100", + "100100010", + "101010000", + "100010010", + "100001010", + "110101000", + "110100100", + "110100010", + "110010100", + "110010010", + "110001010", + "101101000", + "101100100", + "101100010", + "100110100", + "100011010", + "101011000", + "101001100", + "101000110", + "100101100", + "100010110", + "110110100", + "110110010", + "110101100", + "110100110", + "110010110", + "110011010", + "101101100", + "101100110", + "100110110", + "100111010", + "100101110", + "111010100", + "111010010", + "111001010", + "101101110", + "101110110", + "110101110", + "100100110", + "111011010", + "111010110", + "100110010", + "101011110", + "", +] + + +class Code93(Barcode): + """Encode Code93 Barcode""" + + def encode(self, text): + # start marker + bits = ENCODE[MAP.get("MARKER", -1)] + + # Extend to ASCII charset ( return Array ) + text = Code93.encode_ascii(text) + + # Calculate the checksums + text.append(Code93.checksum(text, 20)) # C + text.append(Code93.checksum(text, 15)) # K + + # Now convert text into the ENCODE bits (black and white stripes) + for char in text: + bits = bits + ENCODE[MAP.get(char, -1)] + + # end marker and termination bar + return bits + ENCODE[MAP.get("MARKER", -1)] + "1" + + @staticmethod + def checksum(text, mod): + """Generate a code 93 checksum""" + weight = len(text) % mod + check = 0 + for char in text: + check = check + (MAP[char] * weight) + # Reset the weight is required + weight -= 1 + if weight == 0: + weight = mod + + return PALLET[check % 47] + + @staticmethod + def encode_ascii(text): + """Some characters need re-ENCODE into the code93 specification""" + result = [] + for char in text: + if char in MAP: + result.append(char) + elif char in MAP_A: + result.append("(%)") + result.append(MAP_A[char]) + elif char in MAP_B: + result.append("($)") + result.append(MAP_B[char]) + elif char in MAP_C: + result.append("(/)") + result.append(MAP_C[char]) + elif char in MAP_D: + result.append("(+)") + result.append(MAP_D[char]) + return result diff --git a/share/extensions/barcode/Ean13.py b/share/extensions/barcode/Ean13.py new file mode 100644 index 0000000..21a2e44 --- /dev/null +++ b/share/extensions/barcode/Ean13.py @@ -0,0 +1,44 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Martin Owens +# +# Thanks to Lineaire Chez of Inkbar ( www.inkbar.lineaire.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA. +# +""" +Python barcode renderer for EAN13 barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode + + +class Ean13(EanBarcode): + """Provide an Ean13 barcode generator""" + + name = "ean13" + extras = {2: "Ean2", 5: "Ean5"} + checks = [13] + lengths = [12] + + def _encode(self, num, guide=False): + """Encode an ean13 barcode""" + self.text = EanBarcode.space(num[0:1], 4, num[1:7], 5, num[7:], 7) + if guide: + self.text = self.text[:-4] + ">" + return self.enclose( + EanBarcode.encode_interleaved(num[0], num[1:7]), + EanBarcode.encode_right(num[7:]), + ) diff --git a/share/extensions/barcode/Ean2.py b/share/extensions/barcode/Ean2.py new file mode 100644 index 0000000..1025965 --- /dev/null +++ b/share/extensions/barcode/Ean2.py @@ -0,0 +1,40 @@ +# coding=utf-8 +# +# Copyright (C) 2016 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for EAN2 barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode + +FAMS = ["00", "01", "10", "11"] +START = "01011" + + +class Ean2(EanBarcode): + """Provide an Ean5 barcode generator""" + + length = 2 + name = "ean5" + + def _encode(self, num, guide=False): + if len(num) != 2: + num = ([0, 0] + num)[-2:] + self.text = " ".join(EanBarcode.space(num)) + family = ((num[0] * 10) + num[1]) % 4 + return START + "01".join(EanBarcode.encode_interleaved(family, num, FAMS)) diff --git a/share/extensions/barcode/Ean5.py b/share/extensions/barcode/Ean5.py new file mode 100644 index 0000000..3c84290 --- /dev/null +++ b/share/extensions/barcode/Ean5.py @@ -0,0 +1,50 @@ +# coding=utf-8 +# +# Copyright (C) 2009 Aaron C Spike +# 2010 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for EAN5 barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode + +FAMS = [ + "11000", + "10100", + "10010", + "10001", + "01100", + "00110", + "00011", + "01010", + "01001", + "00101", +] +START = "01011" + + +class Ean5(EanBarcode): + """Provide an Ean5 barcode generator""" + + name = "ean5" + length = 5 + + def _encode(self, num, guide=False): + self.text = " ".join(EanBarcode.space(num)) + family = sum([int(n) * int(m) for n, m in zip(num, "39393")]) % 10 + return START + "01".join(EanBarcode.encode_interleaved(family, num, FAMS)) diff --git a/share/extensions/barcode/Ean8.py b/share/extensions/barcode/Ean8.py new file mode 100644 index 0000000..d6875fc --- /dev/null +++ b/share/extensions/barcode/Ean8.py @@ -0,0 +1,38 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for EAN8 barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode + + +class Ean8(EanBarcode): + """Provide an EAN8 barcode generator""" + + name = "ean8" + checks = [8] + lengths = [7] + + def _encode(self, num, guide=False): + """Encode an ean8 barcode""" + self.text = EanBarcode.space(num[:4], 3, num[4:]) + return self.enclose( + EanBarcode.encode_left(num[:4]), EanBarcode.encode_right(num[4:]) + ) diff --git a/share/extensions/barcode/Rm4scc.py b/share/extensions/barcode/Rm4scc.py new file mode 100644 index 0000000..b4d52ba --- /dev/null +++ b/share/extensions/barcode/Rm4scc.py @@ -0,0 +1,139 @@ +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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. +# +""" +Python barcode renderer for RM4CC barcodes. Designed for use with Inkscape. +""" + +from .Base import Barcode + +charmap = { + "(": "25", + ")": "3", + "0": "05053535", + "1": "05152535", + "2": "05153525", + "3": "15052535", + "4": "15053525", + "5": "15152525", + "6": "05251535", + "7": "05350535", + "8": "05351525", + "9": "15250535", + "A": "15251525", + "B": "15350525", + "C": "05253515", + "D": "05352515", + "E": "05353505", + "F": "15252515", + "G": "15253505", + "H": "15352505", + "I": "25051535", + "J": "25150535", + "K": "25151525", + "L": "35050535", + "M": "35051525", + "N": "35150525", + "O": "25053525", + "P": "25152515", + "Q": "25153505", + "R": "35052515", + "S": "35053505", + "T": "35152505", + "U": "25251515", + "V": "25350515", + "W": "25351505", + "X": "35250515", + "Y": "35251505", + "Z": "35350505", +} + +check = ["ZUVWXY", "501234", "B6789A", "HCDEFG", "NIJKLM", "TOPQRS"] +(BAR_TRACK, BAR_DOWN, BAR_UP, BAR_FULL, BAR_NONE, WHITE_SPACE) = range(6) + + +class Rm4scc(Barcode): + """Provice a Rm4scc barcode generator""" + + default_height = 18 + + def encode(self, text): + result = "" + + text = text.upper() + text.replace("(", "") + text.replace(")", "") + + text = "(" + text + Rm4scc.checksum(text) + ")" + + i = 0 + for char in text: + if char in charmap: + result = result + charmap[char] + i += 1 + + return result + + @staticmethod + def checksum(text): + """given a string of data, return the check character""" + total_lower = 0 + total_upper = 0 + for char in text: + if char in charmap: + bars = charmap[char][0:8:2] + lower = 0 + upper = 0 + + if int(bars[0]) & 1: + lower += 4 + if int(bars[1]) & 1: + lower += 2 + if int(bars[2]) & 1: + lower += 1 + if int(bars[0]) & 2: + upper += 4 + if int(bars[1]) & 2: + upper += 2 + if int(bars[2]) & 2: + upper += 1 + total_lower += lower % 6 + total_upper += upper % 6 + + total_lower = total_upper % 6 + total_upper %= 6 + + checkchar = check[total_upper][total_lower] + return checkchar + + def get_style(self, index): + """Royal Mail Barcodes use a completely different style""" + result = {"width": 2, "write": True, "top": 0} + if index == BAR_TRACK: # Track Bar + result["top"] = 6 + result["height"] = 5 + elif index == BAR_DOWN: # Decender Bar + result["top"] = 6 + result["height"] = 11 + elif index == BAR_UP: # Accender Bar + result["height"] = 11 + elif index == BAR_FULL: # Full Bar + result["height"] = 17 + elif index == WHITE_SPACE: # White Space + result["write"] = False + return result diff --git a/share/extensions/barcode/Upca.py b/share/extensions/barcode/Upca.py new file mode 100644 index 0000000..f278fca --- /dev/null +++ b/share/extensions/barcode/Upca.py @@ -0,0 +1,40 @@ +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for UPCA barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode + + +class Upca(EanBarcode): + """Provides a renderer for EAN12 aka UPC-A Barcodes""" + + name = "upca" + font_size = 10 + lengths = [11] + checks = [12] + + def _encode(self, num, guide=False): + """Encode for a UPC-A Barcode""" + self.text = EanBarcode.space(num[0:1], 3, num[1:6], 4, num[6:11], 3, num[11:]) + return self.enclose( + EanBarcode.encode_left(num[0:6]), + EanBarcode.encode_right(num[6:12]), + ) diff --git a/share/extensions/barcode/Upce.py b/share/extensions/barcode/Upce.py new file mode 100644 index 0000000..9404ca2 --- /dev/null +++ b/share/extensions/barcode/Upce.py @@ -0,0 +1,112 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Martin Owens +# +# 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, USA. +# +""" +Python barcode renderer for UPCE barcodes. Designed for use with Inkscape. +""" + +from .BaseEan import EanBarcode +from inkex.localization import inkex_gettext as _ + +# This is almost exactly the same as the standard FAMILIES +# But flipped around and with the first 111000 instead of 000000. +FAMS = [ + "111000", + "110100", + "110010", + "110001", + "101100", + "100110", + "100011", + "101010", + "101001", + "100101", +] + + +class Upce(EanBarcode): + """Generate EAN6/UPC-E barcode generator""" + + name = "upce" + font_size = 10 + lengths = [6, 11] + checks = [7, 12] + center_bar = "020" + + def _encode(self, num, guide=False): + """Generate a UPC-E Barcode""" + self.text = EanBarcode.space(["0"], 2, num[:6], 2, num[-1]) + code = EanBarcode.encode_interleaved(num[-1], num[:6], FAMS) + return self.enclose(code) + + def append_checksum(self, number): + """Generate a UPCE Checksum""" + if len(number) == 6: + number = Upce.convert_e2a(number) + result = self.get_checksum(number) + return Upce.convert_a2e(number) + result + + @staticmethod + def convert_a2e(number): + """Converting UPC-A to UPC-E, may cause errors.""" + # All UPC-E Numbers use number system 0 + if number[0] != "0" or len(number) != 11: + # If not then the code is invalid + raise ValueError(_("Invalid UPC Number")) + + # Most of the conversions deal + # with the specific code parts + maker = number[1:6] + product = number[6:11] + + # There are 4 cases to convert: + if maker[2:] == "000" or maker[2:] == "100" or maker[2:] == "200": + # Maximum number product code digits can be encoded + if product[:2] == "00": + return maker[:2] + product[2:] + maker[2] + elif maker[3:5] == "00": + # Now only 2 product code digits can be used + if product[:3] == "000": + return maker[:3] + product[3:] + "3" + elif maker[4] == "0": + # With even more maker code we have less room for product code + if product[:4] == "0000": + return maker[0:4] + product[4] + "4" + elif product[:4] == "0000" and int(product[4]) > 4: + # The last recorse is to try and squeeze it in the last 5 numbers + # so long as the product is 00005-00009 so as not to conflict with + # the 0-4 used above. + return maker + product[4] + # Invalid UPC-A Numbe + raise ValueError(_("Invalid UPC Number")) + + @staticmethod + def convert_e2a(number): + """Convert UPC-E to UPC-A by padding with zeros""" + # It's more likly to convert this without fault + # But we still must be mindful of the 4 conversions + if len(number) != 6: + return None + + if number[5] in ["0", "1", "2"]: + return "0" + number[:2] + number[5] + "0000" + number[2:5] + if number[5] == "3": + return "0" + number[:3] + "00000" + number[3:5] + if number[5] == "4": + return "0" + number[:4] + "00000" + number[4] + return "0" + number[:5] + "0000" + number[5] diff --git a/share/extensions/barcode/__init__.py b/share/extensions/barcode/__init__.py new file mode 100644 index 0000000..1bfe281 --- /dev/null +++ b/share/extensions/barcode/__init__.py @@ -0,0 +1,77 @@ +# coding=utf-8 +# +# Copyright (C) 2014 Martin Owens +# +# 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. +# +# pylint: disable=no-self-use +""" +Renderer for barcodes, SVG extension for Inkscape. + +For supported barcodes see Barcode module directory. +""" + +from inkex.localization import inkex_gettext as _ + +# This lists all known Barcodes missing from this package +# ===== UPC-Based Extensions ====== # +# Code11 +# ========= Code25-Based ========== # +# Codabar +# Postnet +# ITF25 +# ========= Alpha-numeric ========= # +# Code39Mod +# USPS128 +# =========== 2D Based ============ # +# PDF417 +# PDF417-Macro +# PDF417-Truncated +# PDF417-GLI + + +class NoBarcode: + """Simple class for no barcode""" + + def __init__(self, msg): + self.msg = msg + + def encode(self, text): + """Encode the text into a barcode pattern""" + raise ValueError(_("No barcode encoder: {}").format(self.msg)) + + def generate(self): + """Generate actual svg from the barcode pattern""" + return None + + +def get_barcode(code, **kw): + """Gets a barcode from a list of available barcode formats""" + if not code: + return NoBarcode(_("No barcode format given.")) + + code = str(code).replace("-", "").strip() + module = "barcode." + code + lst = ["barcode"] + try: + return getattr(__import__(module, fromlist=lst), code)(kw) + except ImportError as err: + if code in str(err): + return NoBarcode(_("Invalid type of barcode: {}.{}").format(module, code)) + raise + except AttributeError: + return NoBarcode( + _("Barcode module is missing barcode class: {}.{}").format(module, code) + ) diff --git a/share/extensions/color_blackandwhite.inx b/share/extensions/color_blackandwhite.inx new file mode 100644 index 0000000..71dec01 --- /dev/null +++ b/share/extensions/color_blackandwhite.inx @@ -0,0 +1,15 @@ + + + Black and White + org.inkscape.color.black_and_white + 127 + + all + + + + + + diff --git a/share/extensions/color_blackandwhite.py b/share/extensions/color_blackandwhite.py new file mode 100755 index 0000000..e5e65b2 --- /dev/null +++ b/share/extensions/color_blackandwhite.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +"""To black and white""" + +import inkex + + +class BlackAndWhite(inkex.ColorExtension): + """Convert colours to black and white""" + + def add_arguments(self, pars): + pars.add_argument( + "-t", "--threshold", type=int, default=127, help="Threshold Color Level" + ) + + def modify_color(self, name, color): + # ITU-R Recommendation BT.709 (NTSC and PAL) + # l = 0.2125 * r + 0.7154 * g + 0.0721 * b + lum = 0.299 * color.red + 0.587 * color.green + 0.114 * color.blue + grey = 255 if lum > self.options.threshold else 0 + return inkex.Color((grey, grey, grey)) + + +if __name__ == "__main__": + BlackAndWhite().run() diff --git a/share/extensions/color_brighter.inx b/share/extensions/color_brighter.inx new file mode 100644 index 0000000..6571e7c --- /dev/null +++ b/share/extensions/color_brighter.inx @@ -0,0 +1,14 @@ + + + Brighter + org.inkscape.color.brighter + + all + + + + + + diff --git a/share/extensions/color_brighter.py b/share/extensions/color_brighter.py new file mode 100755 index 0000000..4ab7ecc --- /dev/null +++ b/share/extensions/color_brighter.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +"""Lighten colours of selected objects""" + +import inkex + + +class Brighter(inkex.ColorExtension): + """Make colours brighter""" + + def modify_color(self, name, color): + factor = 0.9 + contra = int(1 / (1 - factor)) + if color.space == "hsl": + color.lightness = min(int(round(color.lightness / factor)), 255) + elif color.red == 0 and color.green == 0 and color.blue == 0: + color.red = contra + color.green = contra + color.blue = contra + else: + color.red = min(int(round(color.red / factor)), 255) + color.green = min(int(round(color.green / factor)), 255) + color.blue = min(int(round(color.blue / factor)), 255) + return color + + +if __name__ == "__main__": + Brighter().run() diff --git a/share/extensions/color_custom.inx b/share/extensions/color_custom.inx new file mode 100644 index 0000000..77328a6 --- /dev/null +++ b/share/extensions/color_custom.inx @@ -0,0 +1,36 @@ + + + Custom + org.inkscape.color.custom + + + r + g + b + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/color_custom.py b/share/extensions/color_custom.py new file mode 100755 index 0000000..87dd5bd --- /dev/null +++ b/share/extensions/color_custom.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +"""Custom color function per channel of selected objects""" + +import ast +import operator as op +import inkex + +OPS = { + ast.Add: op.add, + ast.Sub: op.sub, + ast.Mult: op.mul, + ast.Div: op.truediv, + ast.Pow: op.pow, + ast.BitXor: op.xor, + ast.USub: op.neg, +} + + +def eval_expr(expr, namespace): + """ + >>> eval_expr('2^6') + 4 + >>> eval_expr('2**6') + 64 + >>> eval_expr('1 + 2*3**(4^5) / (6 + -7)') + -5.0 + """ + return _eval(ast.parse(expr, mode="eval").body, namespace) + + +def _eval(node, namespace): + if isinstance(node, ast.Num): # + return node.n + if isinstance(node, ast.Name): # (must be in namespace) + return namespace[node.id] + if isinstance(node, ast.BinOp): # + return OPS[type(node.op)]( + _eval(node.left, namespace), _eval(node.right, namespace) + ) + if isinstance(node, ast.UnaryOp): # e.g., -1 + return OPS[type(node.op)](_eval(node.operand, namespace)) + raise TypeError(node) + + +class Custom(inkex.ColorExtension): + """Custom colour functions per channel""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("-r", "--r", default="r", help="red channel function") + pars.add_argument("-g", "--g", default="g", help="green channel function") + pars.add_argument("-b", "--b", default="b", help="blue channel function") + pars.add_argument( + "-s", "--scale", type=float, default=1.0, help="The input (r,g,b) range" + ) + + def modify_color(self, name, color): + opt = self.options + factor = 255.0 / opt.scale + # add stuff to be accessible from within the custom color function here. + namespace = { + "r": float(color.red) / factor, + "g": float(color.green) / factor, + "b": float(color.blue) / factor, + } + + color.red = int(eval_expr(opt.r.strip(), namespace) * factor) + color.green = int(eval_expr(opt.g.strip(), namespace) * factor) + color.blue = int(eval_expr(opt.b.strip(), namespace) * factor) + return color + + +if __name__ == "__main__": + Custom().run() diff --git a/share/extensions/color_darker.inx b/share/extensions/color_darker.inx new file mode 100644 index 0000000..eb2d8ce --- /dev/null +++ b/share/extensions/color_darker.inx @@ -0,0 +1,14 @@ + + + Darker + org.inkscape.color.darker + + all + + + + + + diff --git a/share/extensions/color_darker.py b/share/extensions/color_darker.py new file mode 100755 index 0000000..71b487b --- /dev/null +++ b/share/extensions/color_darker.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Darken colours of selected objects""" + +import inkex + + +class Darker(inkex.ColorExtension): + """Make the colours darker""" + + def modify_color(self, name, color): + factor = 0.9 + if color.space == "hsl": + color.lightness = int(round(max(color.lightness * factor, 0))) + else: + color.red = int(round(max(color.red * factor, 0))) + color.green = int(round(max(color.green * factor, 0))) + color.blue = int(round(max(color.blue * factor, 0))) + return color + + +if __name__ == "__main__": + Darker().run() diff --git a/share/extensions/color_desaturate.inx b/share/extensions/color_desaturate.inx new file mode 100644 index 0000000..3f52ca1 --- /dev/null +++ b/share/extensions/color_desaturate.inx @@ -0,0 +1,14 @@ + + + Desaturate + org.inkscape.color.desaturate + + all + + + + + + diff --git a/share/extensions/color_desaturate.py b/share/extensions/color_desaturate.py new file mode 100755 index 0000000..1710b1e --- /dev/null +++ b/share/extensions/color_desaturate.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +"""Remove colors""" + +import inkex + + +class Desaturate(inkex.ColorExtension): + """Remove color but maintain intesity""" + + def modify_color(self, name, color): + lum = ( + max(color.red, color.green, color.blue) + + min(color.red, color.green, color.blue) + ) // 2 + return inkex.Color((int(round(lum)), int(round(lum)), int(round(lum)))) + + +if __name__ == "__main__": + Desaturate().run() diff --git a/share/extensions/color_grayscale.inx b/share/extensions/color_grayscale.inx new file mode 100644 index 0000000..0d0a98a --- /dev/null +++ b/share/extensions/color_grayscale.inx @@ -0,0 +1,14 @@ + + + Grayscale + org.inkscape.color.grayscale + + all + + + + + + diff --git a/share/extensions/color_grayscale.py b/share/extensions/color_grayscale.py new file mode 100755 index 0000000..5d134aa --- /dev/null +++ b/share/extensions/color_grayscale.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +"""Convert to grey""" + +import inkex + + +class Grayscale(inkex.ColorExtension): + """Make all colours grayscale""" + + def modify_color(self, name, color): + # ITU-R Recommendation BT.709 (NTSC and PAL) + # l = 0.2125 * r + 0.7154 * g + 0.0721 * b + lum = 0.299 * color.red + 0.587 * color.green + 0.114 * color.blue + return inkex.Color((int(round(lum)), int(round(lum)), int(round(lum)))) + + +if __name__ == "__main__": + Grayscale().run() diff --git a/share/extensions/color_hsl_adjust.inx b/share/extensions/color_hsl_adjust.inx new file mode 100644 index 0000000..b7d7dba --- /dev/null +++ b/share/extensions/color_hsl_adjust.inx @@ -0,0 +1,32 @@ + + + HSL Adjust + org.inkscape.color.hsl_adjust + + + 0 + false + 0 + false + 0 + false + + + + + + + all + + + + + + diff --git a/share/extensions/color_hsl_adjust.py b/share/extensions/color_hsl_adjust.py new file mode 100755 index 0000000..cbe47e6 --- /dev/null +++ b/share/extensions/color_hsl_adjust.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +"""Adjust all the HSL values""" + +import random +import inkex + + +class HslAdjust(inkex.ColorExtension): + """Modify the HSL levels of each color""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("-x", "--hue", type=int, default=0, help="Adjust hue") + pars.add_argument( + "-s", "--saturation", type=int, default=0, help="Adjust saturation" + ) + pars.add_argument( + "-l", "--lightness", type=int, default=0, help="Adjust lightness" + ) + pars.add_argument("--random_h", type=inkex.Boolean, dest="random_hue") + pars.add_argument("--random_s", type=inkex.Boolean, dest="random_saturation") + pars.add_argument("--random_l", type=inkex.Boolean, dest="random_lightness") + + def modify_color(self, name, color): + if self.options.random_hue: + color.hue = int(random.random() * 255.0) + elif self.options.hue: + color.hue += self.options.hue * 256.0 / 360 + + if self.options.random_saturation: + color.saturation = int(random.random() * 255.0) + elif self.options.saturation: + color.saturation += self.options.saturation * 2.55 + + if self.options.random_lightness: + color.lightness = int(random.random() * 255.0) + elif self.options.lightness: + color.lightness += self.options.lightness * 2.55 + + return color + + +if __name__ == "__main__": + HslAdjust().run() diff --git a/share/extensions/color_lesshue.inx b/share/extensions/color_lesshue.inx new file mode 100644 index 0000000..487e972 --- /dev/null +++ b/share/extensions/color_lesshue.inx @@ -0,0 +1,14 @@ + + + Less Hue + org.inkscape.color.less_hue + + all + + + + + + diff --git a/share/extensions/color_lesshue.py b/share/extensions/color_lesshue.py new file mode 100755 index 0000000..114ac3c --- /dev/null +++ b/share/extensions/color_lesshue.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Reduce hue""" + +import inkex + + +class LessHue(inkex.ColorExtension): + """Remove Hue from the color""" + + def modify_color(self, name, color): + color.hue -= int(0.05 * 255) + return color + + +if __name__ == "__main__": + LessHue().run() diff --git a/share/extensions/color_lesslight.inx b/share/extensions/color_lesslight.inx new file mode 100644 index 0000000..5f24539 --- /dev/null +++ b/share/extensions/color_lesslight.inx @@ -0,0 +1,14 @@ + + + Less Light + org.inkscape.color.less_light + + all + + + + + + diff --git a/share/extensions/color_lesslight.py b/share/extensions/color_lesslight.py new file mode 100755 index 0000000..1bbe151 --- /dev/null +++ b/share/extensions/color_lesslight.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Reduce lightness""" + +import inkex + + +class LessLight(inkex.ColorExtension): + """Reduce the light of the color""" + + def modify_color(self, name, color): + color.lightness -= int(0.05 * 255) + return color + + +if __name__ == "__main__": + LessLight().run() diff --git a/share/extensions/color_lesssaturation.inx b/share/extensions/color_lesssaturation.inx new file mode 100644 index 0000000..6e31086 --- /dev/null +++ b/share/extensions/color_lesssaturation.inx @@ -0,0 +1,14 @@ + + + Less Saturation + org.inkscape.color.less_saturation + + all + + + + + + diff --git a/share/extensions/color_lesssaturation.py b/share/extensions/color_lesssaturation.py new file mode 100755 index 0000000..e19b297 --- /dev/null +++ b/share/extensions/color_lesssaturation.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Reduce saturation""" + +import inkex + + +class LessSaturation(inkex.ColorExtension): + """Make colours less saturated""" + + def modify_color(self, name, color): + color.saturation -= int(0.05 * 255) + return color + + +if __name__ == "__main__": + LessSaturation().run() diff --git a/share/extensions/color_list.inx b/share/extensions/color_list.inx new file mode 100644 index 0000000..f5c5d4a --- /dev/null +++ b/share/extensions/color_list.inx @@ -0,0 +1,14 @@ + + + List All + org.inkscape.color.list_colours + + all + + + + + + diff --git a/share/extensions/color_list.py b/share/extensions/color_list.py new file mode 100755 index 0000000..fc4c152 --- /dev/null +++ b/share/extensions/color_list.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +"""List all colors used in an svg document""" + +from collections import defaultdict +from typing import Dict +import inkex + + +class ListColours(inkex.ColorExtension): + """Make the colours darker""" + + _counts: Dict = defaultdict(int) + + def effect(self): + super().effect() + items = sorted(self._counts.items(), key=lambda v: -v[1]) + for color, count in items: + self.msg("{count}: {color}".format(color=color, count=count)) + + def modify_color(self, name, color): + self._counts[color] += 1 + return color + + +if __name__ == "__main__": + ListColours().run() diff --git a/share/extensions/color_morehue.inx b/share/extensions/color_morehue.inx new file mode 100644 index 0000000..d10de1b --- /dev/null +++ b/share/extensions/color_morehue.inx @@ -0,0 +1,14 @@ + + + More Hue + org.inkscape.color.more_hue + + all + + + + + + diff --git a/share/extensions/color_morehue.py b/share/extensions/color_morehue.py new file mode 100755 index 0000000..c421d35 --- /dev/null +++ b/share/extensions/color_morehue.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Add more hue""" + +import inkex + + +class MoreHue(inkex.ColorExtension): + """Add hue to any selected object""" + + def modify_color(self, name, color): + color.hue += int(0.05 * 255.0) + return color + + +if __name__ == "__main__": + MoreHue().run() diff --git a/share/extensions/color_morelight.inx b/share/extensions/color_morelight.inx new file mode 100644 index 0000000..5f5630d --- /dev/null +++ b/share/extensions/color_morelight.inx @@ -0,0 +1,14 @@ + + + More Light + org.inkscape.color.more_light + + all + + + + + + diff --git a/share/extensions/color_morelight.py b/share/extensions/color_morelight.py new file mode 100755 index 0000000..99ef475 --- /dev/null +++ b/share/extensions/color_morelight.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Increase lightness""" + +import inkex + + +class MoreLight(inkex.ColorExtension): + """Lighten selected objects""" + + def modify_color(self, name, color): + color.lightness += int(0.05 * 255.0) + return color + + +if __name__ == "__main__": + MoreLight().run() diff --git a/share/extensions/color_moresaturation.inx b/share/extensions/color_moresaturation.inx new file mode 100644 index 0000000..3305728 --- /dev/null +++ b/share/extensions/color_moresaturation.inx @@ -0,0 +1,14 @@ + + + More Saturation + org.inkscape.color.more_saturation + + all + + + + + + diff --git a/share/extensions/color_moresaturation.py b/share/extensions/color_moresaturation.py new file mode 100755 index 0000000..6c5498b --- /dev/null +++ b/share/extensions/color_moresaturation.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Increase satuation""" + +import inkex + + +class MoreSaturation(inkex.ColorExtension): + """Increase saturation of selected objects""" + + def modify_color(self, name, color): + color.saturation += int(0.05 * 255.0) + return color + + +if __name__ == "__main__": + MoreSaturation().run() diff --git a/share/extensions/color_negative.inx b/share/extensions/color_negative.inx new file mode 100644 index 0000000..9017b4e --- /dev/null +++ b/share/extensions/color_negative.inx @@ -0,0 +1,14 @@ + + + Negative + org.inkscape.color.negative + + all + + + + + + diff --git a/share/extensions/color_negative.py b/share/extensions/color_negative.py new file mode 100755 index 0000000..9407706 --- /dev/null +++ b/share/extensions/color_negative.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +"""Reverse the colors""" + +import inkex + + +class Negative(inkex.ColorExtension): + """Make the colour oposite""" + + def modify_color(self, name, color): + # Support any colour space + for i, channel in enumerate(color): + color[i] = 255 - channel + return color + + +if __name__ == "__main__": + Negative().run() diff --git a/share/extensions/color_randomize.inx b/share/extensions/color_randomize.inx new file mode 100644 index 0000000..8610b96 --- /dev/null +++ b/share/extensions/color_randomize.inx @@ -0,0 +1,25 @@ + + + Randomize + org.inkscape.color.randomize + + + 100 + 100 + 100 + 0 + + + + + + + all + + + + + + diff --git a/share/extensions/color_randomize.py b/share/extensions/color_randomize.py new file mode 100755 index 0000000..e25dc6d --- /dev/null +++ b/share/extensions/color_randomize.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +"""Randomise the selected item's colours using hsl colorspace""" + +from random import randrange, uniform, seed +import inkex +from inkex.localization import inkex_gettext as _ + + +def _rand( + limit, value, roof=255, method=randrange, circular=False, deterministic=False +): + """Generates a random number which is less than limit % away from value, using the method + supplied.""" + if deterministic: + if isinstance(value, float): + seed(int(value * 1000)) + else: + seed(value) + limit = roof * float(limit) / 100 + limit /= 2 + max_ = type(roof)(value + limit) + min_ = type(roof)(value - limit) + if not (circular): + if max_ > roof: + min_ -= max_ - roof + max_ = roof + if min_ < 0: + max_ -= min_ + min_ = 0 + return method(min_, max_) + return method(min_, max_) % roof + + +class Randomize(inkex.ColorExtension): + """Randomize the colours of all objects""" + + deterministic_output = False + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("-y", "--hue_range", type=int, default=0, help="Hue range") + pars.add_argument( + "-t", "--saturation_range", type=int, default=0, help="Saturation range" + ) + pars.add_argument( + "-m", "--lightness_range", type=int, default=0, help="Lightness range" + ) + pars.add_argument( + "-o", "--opacity_range", type=int, default=0, help="Opacity range" + ) + + def _rand(self, limit, value, roof=255, method=randrange, circular=False): + return _rand( + limit, + value, + roof, + method, + circular, + deterministic=self.deterministic_output, + ) + + def modify_color(self, name, color): + hsl = color.to_hsl() + if self.options.hue_range > 0: + hsl.hue = int(self._rand(self.options.hue_range, hsl.hue, circular=True)) + if self.options.saturation_range > 0: + hsl.saturation = int( + self._rand(self.options.saturation_range, hsl.saturation) + ) + if self.options.lightness_range > 0: + hsl.lightness = int(self._rand(self.options.lightness_range, hsl.lightness)) + return hsl.to_rgb() + + def modify_opacity(self, name, opacity): + if name != "opacity": + return opacity + try: + opacity = float(opacity) + except ValueError: + self.msg(_("Ignoring unusual opacity value: {}").format(opacity)) + return opacity + orange = self.options.opacity_range + if orange > 0: + return self._rand(orange, opacity, roof=1.0, method=uniform) + return opacity + + +if __name__ == "__main__": + Randomize().run() diff --git a/share/extensions/color_removeblue.inx b/share/extensions/color_removeblue.inx new file mode 100644 index 0000000..f1ebdda --- /dev/null +++ b/share/extensions/color_removeblue.inx @@ -0,0 +1,14 @@ + + + Remove Blue + org.inkscape.color.remove_blue + + all + + + + + + diff --git a/share/extensions/color_removeblue.py b/share/extensions/color_removeblue.py new file mode 100755 index 0000000..ee64f0e --- /dev/null +++ b/share/extensions/color_removeblue.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Extension to remove the blue colour from selected shapes""" + +import inkex + + +class RemoveBlue(inkex.ColorExtension): + """Remove blue color from selected objects""" + + def modify_color(self, name, color): + return inkex.Color([color.red, color.green, 0]) + + +if __name__ == "__main__": + RemoveBlue().run() diff --git a/share/extensions/color_removegreen.inx b/share/extensions/color_removegreen.inx new file mode 100644 index 0000000..8a2c32e --- /dev/null +++ b/share/extensions/color_removegreen.inx @@ -0,0 +1,14 @@ + + + Remove Green + org.inkscape.color.remove_green + + all + + + + + + diff --git a/share/extensions/color_removegreen.py b/share/extensions/color_removegreen.py new file mode 100755 index 0000000..319a8cd --- /dev/null +++ b/share/extensions/color_removegreen.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Remove green color from selected objects""" + +import inkex + + +class RemoveGreen(inkex.ColorExtension): + """Remove green color from selected objects""" + + def modify_color(self, name, color): + return inkex.Color([color.red, 0, color.blue]) + + +if __name__ == "__main__": + RemoveGreen().run() diff --git a/share/extensions/color_removered.inx b/share/extensions/color_removered.inx new file mode 100644 index 0000000..fab0bd4 --- /dev/null +++ b/share/extensions/color_removered.inx @@ -0,0 +1,14 @@ + + + Remove Red + org.inkscape.color.remove_red + + all + + + + + + diff --git a/share/extensions/color_removered.py b/share/extensions/color_removered.py new file mode 100755 index 0000000..ff1b5af --- /dev/null +++ b/share/extensions/color_removered.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Extension for removing the colour red from selected objects""" + +import inkex + + +class RemoveRed(inkex.ColorExtension): + """Remove red color from selected objects""" + + def modify_color(self, name, color): + return inkex.Color([0, color.green, color.blue]) + + +if __name__ == "__main__": + RemoveRed().run() diff --git a/share/extensions/color_replace.inx b/share/extensions/color_replace.inx new file mode 100644 index 0000000..dab9d0c --- /dev/null +++ b/share/extensions/color_replace.inx @@ -0,0 +1,24 @@ + + + Replace color + org.inkscape.color.replace_color + + + + true + + + + + + + all + + + + + + diff --git a/share/extensions/color_replace.py b/share/extensions/color_replace.py new file mode 100755 index 0000000..a4be3d5 --- /dev/null +++ b/share/extensions/color_replace.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +"""Replace color extension""" + +import inkex + + +class ReplaceColor(inkex.ColorExtension): + """Replace color in SVG with another""" + + pass_rgba = True + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument( + "-f", + "--from_color", + default=inkex.Color("black"), + type=inkex.Color, + help="Replace color", + ) + pars.add_argument( + "-t", + "--to_color", + default=inkex.Color("red"), + type=inkex.Color, + help="By color", + ) + pars.add_argument( + "-i", + "--ignore_opacity", + default=True, + type=inkex.Boolean, + help="Whether color should be replaced regardless of opacity match", + ) + + def modify_color(self, name, color): # color is rgba + if self.options.from_color.to_rgb() == color.to_rgb() and ( + self.options.ignore_opacity + or abs(self.options.from_color.to_rgba().alpha - color.alpha) < 0.01 + ): + return self.options.to_color.to_rgba() + return color + + +if __name__ == "__main__": + ReplaceColor().run() diff --git a/share/extensions/color_rgbbarrel.inx b/share/extensions/color_rgbbarrel.inx new file mode 100644 index 0000000..a035ab7 --- /dev/null +++ b/share/extensions/color_rgbbarrel.inx @@ -0,0 +1,14 @@ + + + RGB Barrel + org.inkscape.color.rgb_barrel + + all + + + + + + diff --git a/share/extensions/color_rgbbarrel.py b/share/extensions/color_rgbbarrel.py new file mode 100755 index 0000000..fb61a58 --- /dev/null +++ b/share/extensions/color_rgbbarrel.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +"""Rotate the colors in the selected elements""" + +import inkex + + +class RgbBarrel(inkex.ColorExtension): + """ + Cycle colors RGB -> BRG + + aka Do a Barrel Roll! + """ + + def modify_color(self, name, color): + return inkex.Color((color.blue, color.red, color.green)) + + +if __name__ == "__main__": + RgbBarrel().run() diff --git a/share/extensions/colors.xml b/share/extensions/colors.xml new file mode 100644 index 0000000..7ed8592 --- /dev/null +++ b/share/extensions/colors.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/convert2dashes.inx b/share/extensions/convert2dashes.inx new file mode 100644 index 0000000..5fd2c44 --- /dev/null +++ b/share/extensions/convert2dashes.inx @@ -0,0 +1,14 @@ + + + Convert to Dashes + org.inkscape.filter.dashit + + path + + + + + + diff --git a/share/extensions/convert2dashes.py b/share/extensions/convert2dashes.py new file mode 100755 index 0000000..4583ed4 --- /dev/null +++ b/share/extensions/convert2dashes.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005,2007 Aaron Spike, aaron@ekips.org +# Copyright (C) 2009 Alvin Penner, penner@vaxxine.com +# +# 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. +# +""" +This extension converts a path into a dashed line using 'stroke-dasharray' +It is a modification of the file addnodes.py +""" +import inkex +from inkex import bezier, CubicSuperPath, Group, PathElement +from inkex.localization import inkex_gettext as _ + + +class Dashit(inkex.EffectExtension): + """Extension to convert paths into dash-array line""" + + def __init__(self): + super(Dashit, self).__init__() + self.not_converted = [] + + def effect(self): + for node in self.svg.selection: + self.convert2dash(node) + if self.not_converted: + inkex.errormsg( + _("Total number of objects not converted: {}\n").format( + len(self.not_converted) + ) + ) + # return list of IDs in case the user needs to find a specific object + inkex.debug(self.not_converted) + + def convert2dash(self, node): + """Convert each selected node's dash array""" + if isinstance(node, Group): + for child in node: + self.convert2dash(child) + elif isinstance(node, PathElement): + self._convert(node) + else: + self.not_converted.append(node.get("id")) + + @staticmethod + def _convert(node): + dashes = [] + offset = 0 + style = node.specified_style() + dashes = style("stroke-dasharray") + offset = style("stroke-dashoffset") + if not dashes: + return + new = [] + for sub in node.path.to_superpath(): + idash = 0 + dash = dashes[0] + length = float(offset) + while dash < length: + length = length - dash + idash = (idash + 1) % len(dashes) + dash = dashes[idash] + new.append([sub[0][:]]) + i = 1 + while i < len(sub): + dash = dash - length + length = bezier.cspseglength(new[-1][-1], sub[i]) + while dash < length: + new[-1][-1], nxt, sub[i] = bezier.cspbezsplitatlength( + new[-1][-1], sub[i], dash / length + ) + if idash % 2: # create a gap + new.append([nxt[:]]) + else: # splice the curve + new[-1].append(nxt[:]) + length = length - dash + idash = (idash + 1) % len(dashes) + dash = dashes[idash] + if idash % 2: + new.append([sub[i]]) + else: + new[-1].append(sub[i]) + i += 1 + style.pop("stroke-dasharray") + node.pop("sodipodi:type") + node.path = CubicSuperPath(new).to_path(rtol=1e-10) + node.style = style + + +if __name__ == "__main__": + Dashit().run() diff --git a/share/extensions/dhw_input.inx b/share/extensions/dhw_input.inx new file mode 100644 index 0000000..5968540 --- /dev/null +++ b/share/extensions/dhw_input.inx @@ -0,0 +1,14 @@ + + + DHW file input + org.inkscape.input.dhw_input + + .dhw + application/x-extension-DHW + ACECAD Digimemo File (*.dhw) + Open files from ACECAD Digimemo + + + diff --git a/share/extensions/dhw_input.py b/share/extensions/dhw_input.py new file mode 100755 index 0000000..80349c7 --- /dev/null +++ b/share/extensions/dhw_input.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 Kevin Lindsey, https://github.com/thelonious/DM2SVG +# 2011 Nikita Kitaev, https://github.com/nikitakit/DM2SVG +# Chris Morgan, https://gist.github.com/1471691 +# 2019 Martin Owens, +# +# 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. +# +""" +Import a DHW file from ACECAD DigiMemo, a hardware based digitiser +""" + +import struct + +import inkex +from inkex import AbortExtension, errormsg, Group, Polyline +from inkex.localization import inkex_gettext as _ + +inkex.NSS["dm"] = "http://github.com/nikitakit/DM2SVG" + + +class DhwInput(inkex.InputExtension): + """Open DHW files and convert to svg on the fly""" + + template = """ + + + + + + +""" + + def load(self, stream): + """Load the steam as if it were an open DHW file""" + header = list(struct.unpack("<32sBHHBxx", stream.read(40))) + doc = header.pop(0).decode() + if doc != "ACECAD_DIGIMEMO_HANDWRITING_____": + raise AbortExtension(_("Could not load file, not a ACECAD DHW file!")) + + height = int(header[2]) + doc = self.get_template(**dict(zip(("v", "w", "h", "p"), header))) + svg = doc.getroot() + + timestamp = 0 + layer = svg.getElementById("layer1") + + while True: + tag = stream.read(1) + if tag == b"": + break + + if ord(tag) <= 128: + errormsg(_("Unsupported tag: {}\n").format(tag)) + continue + + if tag == b"\x90": + # New Layer element + timestamp = 0 + name = "layer{:d}".format(ord(stream.read(1)) + 1) + layer = svg.add(Group(inkscape_groupmode="layer", id=name)) + elif tag == b"\x88": + # Read the timestamp next + timestamp += ord(stream.read(1)) * 20 + else: + # Pen down + coords = [p for p in iter(lambda: read_point(stream, height), None)] + # Pen up + coords.append(read_point(stream, height)) + + poly = layer.add(Polyline()) + poly.path = coords + poly.set("dm:timestamp", timestamp) + + return doc + + +def read_point(stream, ymax): + """If the next byte is a stop byte, return None. Otherwise read 4 bytes + (in total) and return a 2D point. + """ + # read first byte, it might be a stop byte + x1 = struct.unpack("B", stream.read(1))[0] + + if x1 >= 0x80: + return None + + x2, y1, y2 = struct.unpack("BBB", stream.read(3)) + + x = x1 | x2 << 7 + y = y1 | y2 << 7 + + return x, ymax - y + + +if __name__ == "__main__": + DhwInput().run() diff --git a/share/extensions/dimension.inx b/share/extensions/dimension.inx new file mode 100644 index 0000000..ccd4c0d --- /dev/null +++ b/share/extensions/dimension.inx @@ -0,0 +1,20 @@ + + + Dimensions + se.lewerin.filter.dimension + 50 + 50 + + + + + + path + + + + + + diff --git a/share/extensions/dimension.py b/share/extensions/dimension.py new file mode 100755 index 0000000..b452b82 --- /dev/null +++ b/share/extensions/dimension.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 Peter Lewerin, peter.lewerin@tele2.se +# +# 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. +# +""" +An Inkscape effect for adding CAD style dimensions to selected objects +in a drawing. + +It uses the selection's bounding box, so if the bounding box has empty +space in the x- or y-direction (such as with some stars) the results +will look strange. Strokes might also overlap the edge of the +bounding box. + +The dimension arrows aren't measured: use the "Visualize Path/Measure +Path" effect to add measurements. + +This code contains snippets from existing effects in the Inkscape +extensions library, and marker data from markers.svg. +""" + +import inkex +from inkex import Group, Marker, PathElement +from inkex.localization import inkex_gettext as _ + +import pathmodifier + + +class Dimension(pathmodifier.PathModifier): + """Add dimensions as a path modifier""" + + def add_arguments(self, pars): + pars.add_argument( + "--xoffset", + type=float, + default=50.0, + help="x offset of the vertical dimension arrow", + ) + pars.add_argument( + "--yoffset", + type=float, + default=50.0, + help="y offset of the horizontal dimension arrow", + ) + pars.add_argument("--type", default="geometric", help="Bounding box type") + + def add_marker(self, name, rotate): + """Create a marker in the defs of the svg""" + marker = Marker() + marker.set("id", name) + marker.set("orient", "auto") + marker.set("refX", "0.0") + marker.set("refY", "0.0") + marker.set("style", "overflow:visible") + marker.set("inkscape:stockid", name) + self.svg.defs.append(marker) + + arrow = PathElement(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 ") + if rotate: + arrow.set("transform", "scale(0.8) rotate(180) translate(12.5,0)") + else: + arrow.set("transform", "scale(0.8) translate(12.5,0)") + arrow.set( + "style", + "fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none", + ) + marker.append(arrow) + + def horz_line(self, y, xlat, bbox): + """Create a horzontal line""" + line = PathElement() + x1 = bbox.left - xlat[0] * self.options.xoffset + x2 = bbox.right + y1 = y - xlat[1] * self.options.yoffset + line.set("d", "M %f %f H %f" % (x1, y1, x2)) + return line + + def vert_line(self, x, xlat, bbox): + """Create a vertical line""" + line = PathElement() + x = x - xlat[0] * self.options.xoffset + y1 = bbox.top - xlat[1] * self.options.yoffset + y2 = bbox.bottom + line.set("d", "M %f %f V %f" % (x, y1, y2)) + return line + + def effect(self): + scale = self.svg.unittouu("1px") # convert to document units + self.options.xoffset *= scale + self.options.yoffset *= scale + + if not self.svg.selection: + raise inkex.AbortExtension(_("Please select an object")) + if self.options.type == "geometric": + bbox = self.svg.selection.bounding_box() + else: + bbox = self.svg.selection.first().bounding_box() + + layer = self.svg.get_current_layer() + + self.add_marker("Arrow1Lstart", False) + self.add_marker("Arrow1Lend", True) + + group = Group() + layer.append(group) + group.set("fill", "none") + group.set("stroke", "black") + + line = self.horz_line(bbox.top, [0, 1], bbox) + line.set("marker-start", "url(#Arrow1Lstart)") + line.set("marker-end", "url(#Arrow1Lend)") + line.set("stroke-width", str(scale)) + group.append(line) + + line = self.vert_line(bbox.left, [0, 2], bbox) + line.set("stroke-width", str(0.5 * scale)) + group.append(line) + + line = self.vert_line(bbox.right, [0, 2], bbox) + line.set("stroke-width", str(0.5 * scale)) + group.append(line) + + line = self.vert_line(bbox.left, [1, 0], bbox) + line.set("marker-start", "url(#Arrow1Lstart)") + line.set("marker-end", "url(#Arrow1Lend)") + line.set("stroke-width", str(scale)) + group.append(line) + + line = self.horz_line(bbox.top, [2, 0], bbox) + line.set("stroke-width", str(0.5 * scale)) + group.append(line) + + line = self.horz_line(bbox.bottom, [2, 0], bbox) + line.set("stroke-width", str(0.5 * scale)) + group.append(line) + + for node in self.svg.selection.values(): + group.append(node) + + layer.append(group) + return None + + +if __name__ == "__main__": + Dimension().run() diff --git a/share/extensions/doc_ai_convert.inx b/share/extensions/doc_ai_convert.inx new file mode 100644 index 0000000..0f9ccaf --- /dev/null +++ b/share/extensions/doc_ai_convert.inx @@ -0,0 +1,39 @@ + + + Process Illustrator SVG + org.inkscape.doc_ai_convert + + + + + + + + + all + + + + + + diff --git a/share/extensions/doc_ai_convert.py b/share/extensions/doc_ai_convert.py new file mode 100644 index 0000000..db85306 --- /dev/null +++ b/share/extensions/doc_ai_convert.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2021 Windell H. Oskay, www.evilmadscientist.com +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +An Inkscape extension to assist with importing AI SVG files. +""" + +import inkex +from inkex import units + + +class DocAiConvert(inkex.EffectExtension): + """ + Main class of the doc_ai_convert extension + + This extension performs the following two actions: + 1) Recognize intended dimensions of original document. + - If the AI document was set up with a size given in picas, cm, mm, or in, + and then exported to SVG, no conversion is needed. + - If the AI document was set up with any other dimensions, + (point, yard, px, ft/in, ft, or m), then the exported SVG + will be in units of 72 DPI pixels. This causes an issue, + as Inkscape uses CSS pixels (px) which are at 96 DPI. + In this case, we re-interpret the size as 72 DPI points (pt), + which will convert the artwork to appear at the correct size. + 2) Recognize Adobe Illustrator layers. + - Group () elements with non-empty data-name attributes are + groups in an Illustrator SVG document. + - We re-label these as layers such that Inkscape will recognize them. + + """ + + def effect(self): + """ + Main entry point of the doc_ai_convert extension + """ + # 1) Recognize intended dimensions of original document, if given + width_string = self.svg.get("width") + height_string = self.svg.get("height") + + if width_string and height_string: + width_num, width_units = units.parse_unit(width_string) + height_num, height_units = units.parse_unit(height_string) + + # Note that units.parse_unit will return units of 'px' + # for unitless values, and not None. + + if width_num: + if width_units == "px": + self.svg.set("width", units.render_unit(width_num, "pt")) + if height_num: + if height_units == "px": + self.svg.set("height", units.render_unit(height_num, "pt")) + + # 2) Recognize Adobe Illustrator layers. + for node in self.svg.xpath("//svg:g[@data-name]"): + node.set("inkscape:groupmode", "layer") + node.set("inkscape:label", node.pop("data-name")) + + +if __name__ == "__main__": + DocAiConvert().run() diff --git a/share/extensions/docinfo.inx b/share/extensions/docinfo.inx new file mode 100644 index 0000000..095036f --- /dev/null +++ b/share/extensions/docinfo.inx @@ -0,0 +1,14 @@ + + + DOC Info + org.inkscape.doc_info + + all + + + + + + diff --git a/share/extensions/docinfo.py b/share/extensions/docinfo.py new file mode 100755 index 0000000..628c89c --- /dev/null +++ b/share/extensions/docinfo.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2012 Jabiertxo Arraiza, jabier.arraiza@marker.es +# Copyright (C) 2016 su_v, +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +"""Document information""" + +import inkex + +from inkex.localization import ( + inkex_gettext as _, + inkex_fgettext as _f, + inkex_pgettext as pgettext, +) +import inkex.localization + + +class DocInfo(inkex.EffectExtension): + """Show document information""" + + def effect(self): + namedview = self.svg.namedview + self.msg(pgettext("Docinfo Extension", ":::SVG document related info:::")) + self.msg( + _f( + "version: {}", + self.svg.get("inkscape:version", _("New Document (unsaved)")), + ) + ) + self.msg( + pgettext("Docinfo Extension", "width: {}").format(self.svg.viewport_width) + ) + self.msg( + pgettext("Docinfo Extension", "height: {}").format(self.svg.viewport_height) + ) + self.msg( + pgettext("Docinfo Extension", "viewbox: {}").format( + str(self.svg.get_viewbox()) + ) + ) + self.msg( + pgettext("Docinfo Extension", "document-units: {}").format( + namedview.get("inkscape:document-units", "None") + ) + ) + self.msg( + pgettext("Docinfo Extension", "units: ") + namedview.get("units", "None") + ) + self.msg(_f("Document has {} guides", len(namedview.get_guides()))) + for i, grid in enumerate(namedview.findall("inkscape:grid")): + self.msg(_f("Grid number {}: Units: {}", i + 1, grid.get("units", "None"))) + if len(namedview.get_pages()) > 1: + self.msg(_f("Document has {} pages", len(namedview.get_pages()))) + for i, page in enumerate(namedview.get_pages()): + self.msg( + _f( + "Page number {}: x: {} y: {} width: {} height: {}", + i + 1, + page.get("x"), + page.get("y"), + page.get("width"), + page.get("height"), + ) + ) + else: + self.msg(_("This is a single page document.")) + + +if __name__ == "__main__": + DocInfo().run() diff --git a/share/extensions/docs/Makefile b/share/extensions/docs/Makefile new file mode 100644 index 0000000..43276bb --- /dev/null +++ b/share/extensions/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = ../build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/share/extensions/docs/_templates/versions.html b/share/extensions/docs/_templates/versions.html new file mode 100644 index 0000000..476c8d1 --- /dev/null +++ b/share/extensions/docs/_templates/versions.html @@ -0,0 +1,27 @@ +{%- if current_version %} +
+ + Other Versions + v: {{ current_version.name }} + + +
+ {%- if versions.tags %} +
+
Tags
+ {%- for item in versions.tags %} +
{{ item.name }}
+ {%- endfor %} +
+ {%- endif %} + {%- if versions.branches %} +
+
Branches
+ {%- for item in versions.branches %} +
{{ item.name }}
+ {%- endfor %} +
+ {%- endif %} +
+
+{%- endif %} \ No newline at end of file diff --git a/share/extensions/docs/authors/index.rst b/share/extensions/docs/authors/index.rst new file mode 100644 index 0000000..8e7b967 --- /dev/null +++ b/share/extensions/docs/authors/index.rst @@ -0,0 +1,29 @@ +Writing Extensions: In-Depth +============================ + +.. toctree:: + :maxdepth: 2 + + inx-overview + inx-widgets + interpreters + unit-tests + submit + +Highlevel explanation of specific inkex features +---------------------------------------------------- + +.. toctree:: + :maxdepth: 2 + + units + +Update guides +------------- + +.. toctree:: + :maxdepth: 2 + + update1.0 + update1.2 + \ No newline at end of file diff --git a/share/extensions/docs/authors/interpreters.rst b/share/extensions/docs/authors/interpreters.rst new file mode 100644 index 0000000..254abd6 --- /dev/null +++ b/share/extensions/docs/authors/interpreters.rst @@ -0,0 +1,114 @@ +.. _supported_interpreters: + +Supported Interpreters +====================== + +Inkscape Script extensions can use one of the following interpreters: + ++----------+------------------+----------------------+------------------+ +| Language | Name (in INX | Name (in | Default value | +| | file) | preferences.xml) | | ++==========+==================+======================+==================+ +| Perl | "perl" | "perl-interpreter" | "perl" | +| | | | | +| | | | "wperl" (Windows;| +| | | | since Inkscape | +| | | | 1.0) | ++----------+------------------+----------------------+------------------+ +| Python | "python" | "python-interpreter" | "python" | +| | | | | +| | | | "pythonw" | +| | | | (Windows) | ++----------+------------------+----------------------+------------------+ +| Ruby | "ruby" | "ruby-interpreter" | "ruby" | ++----------+------------------+----------------------+------------------+ +| Shell | "shell" | "shell-interpreter" | "sh" | ++----------+------------------+----------------------+------------------+ + +(Code reference: `src/extension/implementation/script.cpp`_) + +.. _src/extension/implementation/script.cpp: https://gitlab.com/inkscape/inkscape/-/blob/master/src/extension/implementation/script.cpp + +.. _inx_files: + +INX files +--------- + +Within the INX file, you need to indicate the interpreter which will be +used to execute the script, using the name given in the table above: + +Example: + +:: + + + ... + + + +.. _selecting_a_specific_interpreter_version_via_preferences_file: + +Selecting a specific interpreter version (via preferences file) +--------------------------------------------------------------- + +In the preferences.xml file, a user can set a specific executable of the +interpreter that Inkscape should use to execute extensions of a specific +type. + +This is especially useful, if the system's default version of the +interpreter is incompatible with the one used by Inkscape's extension +subsystem (e.g. Inkscape extensions that rely on inkex.py will only work +with Python 2 (as of Inkscape 0.92.1), while on some recent Linux +distributions, the default Python version used is Python 3, which +results in errors during execution of extensions). + +To change the executable that will be used to run script extensions to a +different value than the default value in the above table, you need to +do the following: + +#. quit all running Inkscape processes +#. Open your perferences.xml file with a text editor (find the exact + location of the file by going to Edit -> Preferences -> System: User + Preferences) +#. search the group which holds settings for the extension system itself + and options of various extensions: + :: + + + +#. Insert a key for the interpreter, for example 'python-interpreter' + for setting the program that should be used to run python extensions, + and set the string to the absolute path to the python binary which is + compatible with Inkscape's current extension scripts (in the example + below, the path is "/usr/bin/python2.7". It will look different on + Windows systems.): + :: + + + +#. Save the preferences file, and launch Inkscape to test the + extensions. + +.. _see_also: + +See Also +-------- + +- `INX Parameters `__ +- `ScriptingHOWTO `__ + +`Category:Developer Documentation `__ +`Category:Extensions `__ diff --git a/share/extensions/docs/authors/inx-overview.rst b/share/extensions/docs/authors/inx-overview.rst new file mode 100644 index 0000000..83843d4 --- /dev/null +++ b/share/extensions/docs/authors/inx-overview.rst @@ -0,0 +1,238 @@ +INX extension descriptor format +=============================== + + +.. highlight:: xml + +Introduction +------------ + +In order for Inkscape to make use of an external script or program, you +must describe that script to inkscape using an INX file. The INX file is +an XML file with Inkscape-specific content that can be edited in a +plain-text editor. + +The INX file allows the author to: + +- Specify what type of extension it is, for example input, output, or + effect +- Identify :ref:`which interpreter ` should be used to run the extension +- List dependencies; files or other extensions required for operation +- Define parameters that can be set in the extension +- Create :ref:`a GUI with control widgets ` for those parameters +- Add a submenu to the Extensions menu for the extension to reside in +- Label strings for translation +- Chain extensions +- Etc + +Nothing beats a working example, and Inkscape includes a great number of +extensions with INX files that you can read. To find the location of +your Inkscape extensions directory, where included extensions and their +INX files are located, look in the System pane of Inkscape Preferences, +under "Inkscape extensions". + +.. _translation_of_extensions: + +Translation of extensions +------------------------- + +Extension dialog windows, described in INX files, can be prepared for +translation or localisation by adding an ``_`` (underscore) to the XML +tags or attributes. Only add underscores when text needs to be +translated (not numeric values, for example!). + +Example:: + + <_name>Some translatable extension name + +Or:: + + + +When extensions are included in the `Inkscape Extensions Repository`_, +various scripts will scan each INX file for translatable text and +prepare `translation files`_ for others to translate. + +See also: `Ted's blog`_. + +.. _attributes_description: + +Attributes description +---------------------- + ++---------------------------+-------------------------+ +| Attribute name | Allowed values | ++===========================+=========================+ +| ``implements-custom-gui`` | ``"true"`` | | +| | ``"false"`` (default) | +| .. versionadded:: 1.0 | | ++---------------------------+-------------------------+ +| If set to ``true`` **requires** an effect | +| extension to implement custom GUI. | +| | +| .. hint:: | +| *Implementation detail:* The "extension is | +| working" window is not shown for this kind of | +| extensions. This means user interaction with the | +| Inkscape interface is blocked until the | +| extension returns, with no way for the user to | +| abort the running extension! It is therefore | +| **absolutely essential** that your extension | +| provides the necessary visual feedback for the | +| user and has proper error handling, to rule out | +| any dead-locking behavior. | ++---------------------------+-------------------------+ +| ``needs-document`` | ``"true"`` (default) | | +| | ``"false"`` | +| .. versionadded:: 1.0 | | ++---------------------------+-------------------------+ +| If set to ``false`` an effect extension will not be | +| passed a document nor will a document be read back | +| ("no-op" effect). This is currently a hack to make | +| extension manager work and will likely be | +| removed/replaced in future, so use at your | +| **own risk**! | ++---------------------------+-------------------------+ +| ``needs-live-preview`` | ``"true"`` (default) | +| | ``"false"`` | ++---------------------------+-------------------------+ +| If set to ``true`` in an effect extension, it will | +| offer a "Live preview" checkbox in its GUI. When | +| the user checks that box, it will run the extension | +| in a "preview mode", visually showing the effect of | +| the extension, but not making any changes to the | +| SVG document, unless the user clicks the Apply | +| button. While "Live preview" is checked in the GUI, | +| any changes that the user makes to parameters | +| accessible in the GUI will generate an updated | +| preview. | ++---------------------------+-------------------------+ +| ``savecopyonly`` | ``"true"`` | | +| | ``"false"`` (default) | +| .. versionadded:: 1.2 | | ++---------------------------+-------------------------+ +| If set to ``true`` in an **output** extension, it | +| will limit the extension to being available only | +| in the "Save a Copy" menu. | ++---------------------------+-------------------------+ + + +Example +------- + +:: + + + + <_name>{Friendly Extension Name} + {org.domain.sub-domain.extension-name} + program.ext + + + {default value} + + + {Friendly Extension Help} + + + + [all|{element type}] + + + + + + + +More example INX files are available in the Inkscape distribution, which +takes its files from the `Inkscape Extensions Repository`_. + +For a full list of currently supported interpreters, please see +:ref:`supported_interpreters`. + +.. _dtd_xml_schema: + +DTD XML schema +-------------- + +.. warning:: This section contains slightly outdated information. + +The following XML schema may not fully describe the current INX file +structure. The actual XML schema used is described in the :ref:`next +paragraph `. + +:: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +.. _relax_ng_xml_schema: + +RELAX NG XML schema +------------------- + +The XML schema for INX files is available in the `Inkscape extensions +Git repository`_. This is a `RELAX NG schema`_. + +.. _see_also: + +.. _next paragraph: INX_extension_descriptor_format#RELAX_NG_XML_schema +.. _Inkscape extensions Git repository: https://gitlab.com/inkscape/extensions/-/blob/master/inkscape.extension.rng +.. _RELAX NG schema: http://www.relaxng.org/ +.. _INX Parameters: Extensions:_INX_widgets_and_parameters +.. _ScriptingHOWTO: ScriptingHOWTO + +.. _Inkscape Extensions Repository: https://gitlab.com/inkscape/extensions +.. _a GUI with control widgets: Extensions:_INX_widgets_and_parameters +.. _translation files: https://gitlab.com/inkscape/inkscape/-/tree/master/po +.. _Ted's blog: http://gould.cx/ted/blog/Translating_Custom_XML \ No newline at end of file diff --git a/share/extensions/docs/authors/inx-widgets.rst b/share/extensions/docs/authors/inx-widgets.rst new file mode 100644 index 0000000..5c4e1d5 --- /dev/null +++ b/share/extensions/docs/authors/inx-widgets.rst @@ -0,0 +1,536 @@ +.. _inx-widgets: + +INX widgets and parameters +========================== + +This page contains the reference documentation for INX widgets and +parameters. Their primary goal is to make it easy to design GUIs for +`Inkscape Extensions `__ using the built-in `INX +extension descriptor format `__, +although (invisible) parameters can also be used for extensions that +don't need to show a user interface. + +Introduction +------------ + +Extension GUIs consists of an arbitrary number of GUI elements, +so-called `Widgets <#Widgets>`__. These can be simple text labels, boxes +and spacers to control layout or more complex UI elements like images. + +A special class of Widgets are `Parameters <#Parameters>`__. They differ +from other Widgets in that they have a user-settable value, for example +a boolean (implemented as checkbox) or integer (implemented as number +entry). The value of each Parameter is passed to the extension on +execution and can be used to control its behavior. + +All Widgets are described using an easy-to-learn XML schema with +predefined tags and attributes which are described in detail below. + +.. _available_widgets: + +Available Widgets +~~~~~~~~~~~~~~~~~ + +A general Widget takes the form + +.. code:: + + value + +where ``widget_name`` specifies the name of the widget and is one of the +following: + +- ``label``:sup:`since 1.0`\ +- ``hbox``:sup:`since 1.0`\ /``vbox``:sup:`since 1.0`\ +- ``separator``:sup:`since 1.0`\ /``spacer``:sup:`since 1.0`\ +- ``image``:sup:`since 1.0`\ +- ``param`` (for all Parameter types) + +.. _apt: + +Available Parameter types +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A general Parameter takes the form + +.. code:: + + value + +where ``parameter_type`` specifies the type of the parameter and is one +of the following: + +- ``bool``:sup:`since 1.0`\ +- ``int`` +- ``float`` +- ``string`` +- ``path``:sup:`since 1.0`\ +- ``optiongroup`` +- ``notebook`` +- ``color`` + +If a parameter is made invisible (see ``gui-hidden`` attribute in the +`next section <#common-attributes>`__) it will not be shown in the GUI +but it's value is still passed to an extension. This is useful if you +want to hardcode parameter value the user should not be able to change. +If all parameters (and potential widgets) are invisible, Inkscape will +not show a GUI and execute the extension immediately instead, but will +still pass the values of the invisible parameters. + +.. _common_attributes: + +Common attributes +----------------- + +For all widgets +~~~~~~~~~~~~~~~ + ++------------------+------------------+------------------+------------------+ +| Attribute | Allowed | Default | Required? | +| name | value(s) | value | | ++==================+==================+==================+==================+ +| ``gui-hidden`` | ``true``, | | | +| | ``false`` | ``false`` | optional | ++------------------+------------------+------------------+------------------+ +| If set to ``true`` the Widget is hidden from the GUI (primarily used to | +| add hidden parameters that are passed to the extension but are not | +| supposed to be editable by the user.) | +| | +| *Note: If there are* **no** *visible parameters defined in a GUI, the | +| extension is executed immediately without showing a dialog.* | ++------------------+------------------+------------------+------------------+ +| ``indent`` | ``0,1,2,…`` | ``0`` | optional | ++------------------+------------------+------------------+------------------+ +| Sets indentation level of the parameter. Increasing indentation adds | +| padding to the start of the line. | ++------------------+------------------+------------------+------------------+ + + + +Only for Parameters +~~~~~~~~~~~~~~~~~~~ + ++------------------------+------------------------+------------------------+------------------------+ +| Attribute name | Allowed value(s) | Default value | Required? | ++========================+========================+========================+========================+ +| ``name`` | *(text)* | -- | required | ++------------------------+------------------------+------------------------+------------------------+ +| Used as an identifier of the parameter. It has to be unique since the value of this attribute is | +| used to save and transmit parameter values internally! | ++------------------------+------------------------+------------------------+------------------------+ +| ``type`` | see `above <#apt>`__ | -- | required | ++------------------------+------------------------+------------------------+------------------------+ +| Determines the type of the parameter, see the extensive description of | +| `Parameters <#parameters>`__ below. | ++------------------------+------------------------+------------------------+------------------------+ +| ``gui-text`` | *(text)* | -- | required *(visible | +| | | | parameters)*, optional | +| | | | *(hidden parameters* + | +| | | | ``notebooks`` *)* | ++------------------------+------------------------+------------------------+------------------------+ +| Label shown for the parameter in the GUI. | ++------------------------+------------------------+------------------------+------------------------+ +| ``gui-description`` | *(text)* | -- | optional | ++------------------------+------------------------+------------------------+------------------------+ +| Tooltip shown for the parameter when the user hovers the mouse cursor over the active area of the | +| parameter in question. | ++------------------------+------------------------+------------------------+------------------------+ + + + +Widgets +------- + +``hbox`` / ``vbox`` +~~~~~~~~~~~~~~~~~~~ + +Creates a container for other widgets. No visual rendering but provides a possibility to align and +layout other widgets. Child widgets are either added in horizontal (``hbox``) or vertical +(``vbox``) direction. + + .. code:: xml + + … + … + +A box can contain an arbitrary number of other widgets and parameters (including other boxes) to +fine-tune the layout of the GUI. + +*Note*: When you start with an empty extension GUI, you're basically starting with a ``vbox``. +Also ``notebook`` pages behave like vertically oriented boxes. + +.. figure:: widgets/separator.png + :alt: Rendering of hbox/vbox + + ``hbox`` and ``vbox`` + +``image`` +~~~~~~~~~ + +Creates a widget displaying an image. The content of the node specifies +the path of the image file (ideally specify a path relative to the .inx +file itself). + +.. code:: xml + + path/to/image.svg + +By default the image will be rendered at it's actual size. Use +attributes ``width/heigth`` to override the default size (in this case +*both* attributes need to be supplied; units are pixels). + +Images are aligned in the horizontal center of the current box; different alignment +can be realized by wrapping the image in a `hbox <#hbox-vbox>`__ and adding a +`spacer <#spacer>`__ with ``size=expand`` +before (for right alignment) or after (for left alignment) of the image. + +*Implementation note: Loadable image formats are determined by GdkPixbuf +and therefore system-specific. PNG should always work and is the safe +choice. SVG should mostly work and is the preferred choice for obvious +reasons.* + +.. figure:: widgets/image.png + :alt: Rendering of image + + An ``image`` + +``label`` +~~~~~~~~~ + +Creates a widget showing text. The content of the node corresponds to +the text content that will be rendered. + +.. code:: xml + + + +*Note: Labels are intended to provide additional information / help. For +labeling parameters use the ``gui-text`` attribute; for short help texts +that are specific to a single parameter prefer ``gui-description`` which +will render as a tooltip.* + +- When setting the attribute ``appearance="header"`` the text is styled + as a heading and can be used as another possibility to group + parameters. +- | When setting the attribute ``appearance="url"`` the text is rendered + as a clickable link. + | *Note: The text is escaped and used as the link target as-is. + Creating a link text that differs from the URL is prevented for + security reasons.* +- When setting the attribute ``xml:space="preserve"`` any white-space + (spaces, tabs, line-breaks, etc.) in the label will be preserved, + allowing to format the label accordingly. By default all + leading/tailing and intermediary whitespace is collapsed into a + single space character. + +.. figure:: widgets/label.png + :alt: Rendering of different labels + + Different label types (in order): default | ``appearance="header"`` | + ``appearance="url"`` | ``xml:space="preserve"`` + +``separator`` +~~~~~~~~~~~~~ + +Creates a separator for visual separation of other widgets. Renders as a +horizontal/vertical line. + +.. code:: xml + + + +The direction of the separator will automatically adjust depending on +direction of the current container (vertical for "empty" extension GUIs +and ``notebook`` pages; vertical/horizontal for ``vbox`` and ``hbox`` +respectively). + +.. figure:: widgets/separator.png + :alt: Rendering of separators + + Separators can be used in `hbox` and `vbox` environments. + +``spacer`` +~~~~~~~~~~ + +Creates a spacer for visual separation of other widgets. No visual +rendering but provides variable spacing. + +.. code:: xml + + + +The direction of the spacer will automatically adjust depending on +direction of the current container (vertical for "empty" extension GUIs +and ``notebook`` pages; vertical/horizontal for ``vbox`` and ``hbox`` +respectively). + +Use the ``size`` attribute to set the spacing in pixels (default: +``size="10"``). The special value ``expand`` results in a spacer that +grows dynamically and always uses up as much space as possible (useful +for aligning content). + +.. figure:: widgets/spacer.png + :alt: Rendering of spacers + + Different spacer types: (1) default, (2) ``size="30"``, (3) ``size="expand"`` + +Parameters +---------- + +``bool`` +~~~~~~~~ + +.. versionadded:: 1.0 + +Creates a checkbox to set a **boolean value**. Allowed values are +``true`` or ``false`` (default value: ``true``). + +.. code:: xml + + false + +.. figure:: widgets/bool.png + :alt: Checkbox + + Rendering of ``boolean`` values + + +``color`` +~~~~~~~~~ + +Creates a control to select an **RGBA color value**. Values should be +given in hexadecimal notation, e.g. ``0xff0000ff`` for red with full +opacity (default value: ``0x000000ff``) + +.. code:: xml + + 0x000000ff + +Use ``appearance="colorbutton"`` for a simple button that opens a +simplified color picker. Otherwise a full ColorNotebook will be +rendered. + +.. figure:: widgets/color.png + :alt: Rendering of color parameter + + Rendering of a full ColorNotebook for a ``color`` parameter + +.. versionchanged:: 1.0 + + *Implementation note:* colors values are internally treated as 32-bit + unsigned integers (unsigned long). Acceptable default values include + everything the standard library function ``strtoul`` [#]_ understands (since Inkscape 1.0). + Earlier Inkscape version only handled decimal numbers. The value passed + to the extension script will also be a decimal number. + + + +``float`` +~~~~~~~~~ + +Creates a input to enter a **floating point number**. Limit the input +range with the ``min`` and ``max`` attributes; set the number of decimal +places with the ``precision`` attribute. (defaults: ``min="0"``, +``max="10"`` and ``precision="1"``; default value: 0) + +.. code:: xml + + 1.234 + +Use the attribute ``appearance="full"`` to create a slider with which +the value can be adjusted dynamically over the full range. + +.. figure:: widgets/float.png + :alt: Rendering of float parameter + + Rendering of ``float`` parameters: default and with ``appearance="full"`` + +``int`` +~~~~~~~ + +Creates a textbox input to enter an **integer number**. Limit the input +range with the ``min`` and ``max`` attributes. (defaults: ``min="0"`` +and ``max="10"``; default value: 0) + +.. code:: xml + + 1 + +Use the attribute ``appearance="full"`` to create a slider with which +the value can be adjusted dynamically over the full range. + +.. figure:: widgets/integer.png + :alt: Rendering of integer parameter + + Rendering of ``int`` parameters: default and with ``appearance="full"`` + + +``notebook`` +~~~~~~~~~~~~ + +Creates a set of pages (aka tab control). The user can switch between +individual pages. Each page can contain an arbitrary set of other +Widgets and Parameters. Individual pages are created with the element. + +The **returned value** for ``notebook`` parameters is the value of the +``name`` attribute of the selected . By default the first page is +selected. + +Notebooks can be used to show widgets based on an option; that option +would be implemented as notebook. + +.. code:: xml + + + + … + + + … + + + +.. figure:: widgets/notebook.png + :alt: Rendering of notebook parameter + + Rendering of a ``notebook`` + + +``optiongroup`` +~~~~~~~~~~~~~~~ + +Creates a control that allows to select one option **one option** from a +set of multiple choices. The different choices are created with +elements. + +The **returned value** for ``optiongroup`` type parameters is the value +of the ``value`` attribute of the selected . By default the first is +selected. + +.. code:: xml + + + + + + +.. versionadded:: 1.0 + Set the attribute ``appearance="radio"``\ to render radio buttons + (default). Set the attribute ``appearance="combo"``\ to display a + drop-down list instead. + +.. figure:: widgets/optiongroup.png + :alt: Rendering of float parameter + + Rendering of ``optionsgroup`` parameters: ``appearance="radio"`` and + ``appearance="combo"``. On the bottom parameter, ``precision="1"`` + has been set. + + +``path`` +~~~~~~~~ + + +.. versionadded:: 1.0 + +Creates a control to choose a **path**. Paths can either be entered +manually or by using the file chooser that can be opened using the +ellipsis button. + +The ``mode`` attribute allows to set behavior of the file chooser (i.e. +if files or folders can be selected, if they need to exist previously +and if multiple selections are possible). The ``filetypes`` attribute +holds a comma-separated list of file extensions and restricts the +selectable file types in file picker mode. + +.. code:: + + + +Possible values for the ``mode`` attribute: + +- ``file`` - select a single existing file +- ``files`` - select multiple existing files +- ``folder`` - select a single existing folder +- ``folders`` - select multiple existing folders +- ``file_new`` - select a single new file name +- ``file_new`` - select a single new folder name + +Examples + +- Files: + + - Choose a file, with file type restriction (optional): + + .. code:: xml + + my/path/to/file.png + - Choose multiple files (file type restriction possible, too): + + .. code:: xml + + my/path/to/file.png + - Create a new file: + + .. code:: xml + + my/path/to/file.png + +- Folders: + + - Choose a folder: + + .. code:: xml + + my/path/ + - Choose multiple folders: + + .. code:: xml + + my/path/ + - Create a new folder: + + .. code:: xml + + my/path/ + + +.. figure:: widgets/path.png + :alt: Rendering of path parameter + + Rendering of ``path`` parameters + + +*Implementation note:* Existence of paths are not checked before passing +them to the extension, so extension authors need to implement suitable +error handling, especially in case of manual path entry. For multiple +selections the individual paths are joined using the pipe character +("|") and passed to the extension as a single string. + +``string`` +~~~~~~~~~~ + +Creates a input to enter a **string**. Limit the number of characters +the user is allowed to enter with the ``max-length`` attribute. +(defaults: no character limit; default value: empty string) + +.. code:: xml + + Some default text + +.. versionadded:: 1.0 + Set the attribute ``appearance="multiline"``\ to render a multi-line + input. Line-breaks will be encoded as literal ``\n`` in the value passed + to the extension. + +.. figure:: widgets/string.png + :alt: Rendering of string parameters + + Rendering of ``string`` parameters: default and + ``appearance="multiline"`` + + + +.. [#] https://en.cppreference.com/w/cpp/string/byte/strtoul \ No newline at end of file diff --git a/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png b/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png new file mode 100644 index 0000000..2d16fde Binary files /dev/null and b/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png differ diff --git a/share/extensions/docs/authors/samples/unit_camera.svg b/share/extensions/docs/authors/samples/unit_camera.svg new file mode 100644 index 0000000..3a4bad4 --- /dev/null +++ b/share/extensions/docs/authors/samples/unit_camera.svg @@ -0,0 +1,730 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + canvas (infinitely large) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 25 mm + 50 mm + 75 mm + 0 mm + + + + 25 mm + 50 mm + 0 mm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + viewport coordinate system + + diff --git a/share/extensions/docs/authors/samples/units1.svg b/share/extensions/docs/authors/samples/units1.svg new file mode 100644 index 0000000..b221eda --- /dev/null +++ b/share/extensions/docs/authors/samples/units1.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/share/extensions/docs/authors/samples/units2.svg b/share/extensions/docs/authors/samples/units2.svg new file mode 100644 index 0000000..cf2fe17 --- /dev/null +++ b/share/extensions/docs/authors/samples/units2.svg @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/docs/authors/submit.rst b/share/extensions/docs/authors/submit.rst new file mode 100644 index 0000000..c140009 --- /dev/null +++ b/share/extensions/docs/authors/submit.rst @@ -0,0 +1,97 @@ +Submitting and reviewing extensions +=================================== + +This page details how extensions can be submitted to and moderated on +the Inkscape website. + +I want to submit my extension +----------------------------- + +Go through each of these actions and check to make sure your extension +is ready to be made available in Inkscape: + +#. Check for limitations + + * Your extension must not contact the internet (unless exempted for a good reason) + * It must not self-update, or edit files in the config directory. + * It must be readable code, in English. Code in other languages or too obscure may not be accepted. + +#. Check the license of your code + + * Your code must be Free and Open Source. Using one of the available licenses such + as GPL, AGPL, MIT, Apache2 etc. + * Every included dependency must be also Free and Open Source. + +#. Check all of your dependencies + + * Your extension MUST be python based (except for template extensions) + * It MUST work with python 3.6 or later + * Any dependency not shipped with Inkscape MUST be packaged along side your + extension. For example jinja2 would be included in a folder. + +#. Create a zip file of your extension and any external depdencies. + + * Include only one copy in the root of the zip file. + * No specific versions for windows or linux, macOS. + +#. Check which versions of Inkscape it works with (each one, make a note for tagging + later) + + * set the variable "INKSCAPE_PROFILE_DIR=/tmp/folder" + * run the inkscape version + * open the extensions manager + * install the zip file you hope to submit (second tab, folder button at the bottom) + * Your extension MUST work with at least one version of Inkscape. + +#. Sign your zip file + + * Use GnuPG to sign your zip file, use the same signature as the public key you + uploaded to inkscape.org + * OR use md5hash to create a less secure md5 signature of the zip file. Make sure + you have some text in your inkscape.org gnupg key profile setting so you see the + signature field when uploading. + +#. Upload the zip file to the extensions category in the website. + + * Include the generated signature + * Title and description in English with as much detail as possible + * Add Inkscape versions as you tested above. + * Include a link to the Git repository. + * Include an icon and screenshot file. + +#. Send a message to the Inkscape extensions team on `RocketChat`_ asking for a review. + +.. _RocketChat: https://chat.inkscape.org/channel/inkscape_extensions + +I want to review a submission +----------------------------- + +Extensions Reviewer Checklist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ☠Take next popular extension [#]_ or request to review +- ☠Check for existing verification signature +- ☠Contact author to inform about review +- ☠Unpack zip to extensions folder +- ☠Check zip contents for inx and py file +- ☠Check for license header and/or file +- ☠Run pytest and record test coverage +- ☠Run pylint to get code quality score +- ☠Visually confirm no mallicious or internet code +- ☠If no tests, add simple test upstream [#]_ +- ☠Install zip using extensions manager +- If everything is correct … +- ☠Add version tags and any other tags +- ☠Edit description, title, logos to improve presentation +- ☠contact a website administrator to complete + +If everything is correct (must be admin): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ☠Add testing and quality scores to decription +- ☠Generate signature key and upload +- ☠Generate md5 if package is not self-signed + +.. [#] https://inkscape.org/gallery/=extension/ + +.. [#] Add simple inkex.tester comparision test \ No newline at end of file diff --git a/share/extensions/docs/authors/unit-tests.rst b/share/extensions/docs/authors/unit-tests.rst new file mode 100644 index 0000000..3384d59 --- /dev/null +++ b/share/extensions/docs/authors/unit-tests.rst @@ -0,0 +1,67 @@ +.. _unittests: + +Writing unit tests +================== + +All Inkscape extensions should come with tests. This package provides you with +the tools needed to create tests and thus ensure that your extension continues +to work with future versions of Inkscape, the "inkex" python modules, and other +python and non-python tools you may use. + +Make sure your extension is a python extension and is using the +:py:mod:`inkex.extensions` base classes. These provide the greatest amount of +functionality for testing. + +You should start by creating a folder in your repository called ``tests`` with +an empty file inside called ``__init__.py`` to turn it into a module folder. + +For each of your extensions, you should create a file called +``test_{extension_name}.py`` where the name reflects the name of your extension. + +There are two types of tests: + +1. Full-process Comparison tests - These are tests which invoke your + extension with various arguments and attempt to compare the + output to a known good reference. These are useful for testing + that your extension would work if it was used in Inkscape. + + Good example of writing comparison tests can be found in the + Inkscape core repository, each test which inherits from + the ComparisonMixin class is running comparison tests. + +2. Unit tests - These are individual test functions which call out to + specific functions within your extension. These are typical + python unit tests and many good python documents exist + to describe how to write them well. For examples here you + can find the tests that test the inkex modules themselves + to be the most instructive. + +When running a test, it will cause a certain fraction of the code within the +extension to execute. This fraction called it's **coverage** and a higher +coverage score indicates that your test is better at exercising the various +options, features, and branches within your code. + +.. versionadded:: 1.2 + ``EXPORT_COMPARE`` environment variable + +Generating comparison output can be done using the EXPORT_COMPARE environment +variable when calling pytest and comes in 3 modes, the first of which is the +CHECK comparisons mode:: + + EXPORT_COMPARE=1 pytest tests/test_my_specific_test.py + +This will create files in ``tests/data/refs/*.{ext}`` and these files +should be manually checked to make sure they are correct. Once you are happy +with the output you can re-run the test with the WRITE comparisons mode:: + + EXPORT_COMPARE=2 pytest tests/test_my_specific_test.py + +Which will create an output file of the right name and then run the test suite +against it. But only if the file doesn't already exist. The final mode is the +OVERWRITE comparisons mode:: + + EXPORT_COMPARE=3 pytest tests/test_my_specific_test.py + +This is like mode 2, but will over-write any existing files too. This allows +you to update the test compare files. + diff --git a/share/extensions/docs/authors/units.rst b/share/extensions/docs/authors/units.rst new file mode 100644 index 0000000..055fbfd --- /dev/null +++ b/share/extensions/docs/authors/units.rst @@ -0,0 +1,316 @@ +.. _units: + +Units +================= + +If you are reading this page, you are probably confused about how units work in Inkscape, inkex and +SVG in general. This is understandable, since there's quite a bit of conflicting information online. + +Units in SVG +------------ + +SVG means "scalable vector graphics". This introduces an inherent difficulty with how to map units +to the real world. Should units be pixels? Millimeters? Something else? The answer to this depends +on the output format you're targeting. + +The authors of the SVG specification solved this problem by introducing an abstract "dimensionless" +unit called **user units**. The SVG1.1 specification [1]_ is quite clear about their definition: + + *One px unit is defined to be equal to one user unit. + Thus, a length of "5px" is the same as a length of "5".* + +So whenever you read "user unit", think "pixel". And when you encounter a coordinate without unit, +it's specified in user units, i.e. pixels. You might have heard or read something like "I can choose +the unit of a document, so that one user unit equals one millimeter". This statement is misleading, +although not entirely wrong. It will be explained below. + +An `` tag has two different properties that influence its size and the mapping of coordinates. +These are called *viewport coordinate system* and *user coordinate system*. + +And as the name indicates, **user units always refer to the user coordinate system**. So for +the next section which explains the **viewport coordinate system**, forget user units. + +Viewport coordinate system +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The viewport coordinate system is [2]_ + + *[...] a top-level SVG viewport that establishes a mapping between the coordinate system used by the + containing environment (for example, CSS pixels in web browsers) and user units.* + +The viewport coordinate system is established by the ``width`` and ``height`` attributes of the SVG tag. +To reformulate the quote above: The viewport tells the SVG viewer how big the visible part of the +canvas should be *rendered*. It may be ``200px x 100px`` on your screen (``width="200px" height="100px"``) +or ``210mm x 297mm`` (``width="210mm" height="297mm"``), i.e. one A4 page. + + *If the width or height presentation attributes on the outermost svg element are in user units + (i.e., no unit identifier has been provided), then the value is assumed to be equivalent to the + same number of "px" units.* [3]_ + +Expressed in simple terms: if no unit has been specified in the ``width`` or ``height`` attributes, +assume the user means pixels. Otherwise, the unit is converted by the SVG viewer. Inkscape uses a +DPI of 96 px/in, and corresponding conversions for mm, yd etc. are used. + +Consider the following SVG file: + +.. code-block:: XML + + + + + +which renders as follows: + +.. image:: samples/units1.svg + +If your browser zoom is set to 100%, this image should have a size of 100 times 200 pixels, +and is filled with a grey rectangle. You can verify this by taking a screenshot. + +Likewise, in ``mm`` based documents, you might see code such as +``width="210mm" height="297mm"`` which tells an standard-compliant program that if printed or +exported to PDF, the document should span an entire A4 page. + +User coordinate system +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may have noticed that we didn't explicitly specify in the above svg that we want to draw +everything within the area with the coordinates ``0 ≤ x ≤ 200`` and ``0 ≤ y ≤ 100``. This was +done for us automatically since we specified ``width`` and ``height``. The ``viewBox`` attribute +allows to change this. + +Again from the specification [4]_: + + *The effect of the viewBox attribute is that the user agent automatically supplies the + appropriate transformation matrix to map the specified rectangle in user coordinate system + to the bounds of a designated region (often, the SVG viewport).* + +Let's break this down. Imagine the ``viewBox`` attribute as a camera that moves over the infinite +canvas. It can zoom in or out and move around - but whatever image the camera outputs, it is +rendered in the rectangle defined by ``width`` and ``height``, i.e. the viewport. Initially, the +camera is located such that the region ``viewBox="0 0 width height"`` is pictured. We may +however modify the viewBox as we wish. + +In a ``mm`` based documents, where we specified ``width="210mm" height="297mm"``, the viewbox is +initially ``viewBox="0 0 793.7 1122.5"`` due to the conversion from mm to px. This means that the +bottom right corner is at ``(210, 297) mm * 1/25.4 in/mm * 96 px/in ≈ (793.7, 1122.5) px``. + +As already mentioned: no units means user unit means pixels. So a rectangle with +``x="793.7" y="1122.5"`` (no units specified) is at the bottom right corner of the page. It would be +nicer if unitless values would be implicitly in millimeters, so we could specify such a rectangle +with ``x="210" y="297"``. This can be done with the ``viewBox`` attribute and will be explained with +an example SVG. + +Let's say we want to design a business card that should eventually be *printed on 84mm x 56mm*, so +we specifiy ``width="84mm" height="56mm"```. We also want the user units to behave like real-world +millimeters, so we have to zoom the viewbox camera: ``viewBox="0 0 84 56"``. As mentioned above, +no units means px, so these attributes together tell the SVG viewer "move the camera in such a way +that (84, 56) in user units, i.e. px, is the bottom right corner, and scale the image such that when +printed or rendered it has a size of 84mm by 56mm". + +You can imagine this situation like this [5]_: + +.. image:: samples/unit_camera.svg + +To illustrate this, we draw a crosshair at ``(14, 21)`` (note: no units in the path specification!), +i.e. a fourth horizontally and vertically for reference. Then we draw three circles: one at +``(21, 14)``, one at ``(21px, 14px)`` and one at ``(21mm, 14mm)``. + +.. code-block:: XML + + + + + + + + + + +.. image:: samples/units2.svg + +The rendered image at 100% browser resolution should be approximatly ``85mm`` by ``56mm``, but this +highly depends on your screen resolution. + +Note that the first two circles specified without unit +(i.e. user units) and specified in px are at the correct position and identical except for radius +and stroke color. + +The third circle's coordinates, radius and stroke-width are specified in mm. It should be located +somewhere near the bottom right corner (where exactly depends on the DPI conversion of your browser, +but most browsers use ``96dpi = 96 px/in`` today, which yields a conversion factor of approx. +``3.77px/mm``). The stroke is thicker by the same factor and the radius has been reduced to be +comparable to the first circle. + +This is somewhat unintuitive. Didn't we create a mm based document? Now we can explain the +statement from the introduction +"I can choose the unit of a document, so that one user unit equals one millimeter". +We didn't change the core statement "no unit = user unit = pixels" by specifying width and +height in mm. But the special choice of the viewbox attribute - the same width and height, but +without the unit) makes the following statement true: "**One user unit looks like one millimeter on +the output device** (e.g. screen or paper)". + +Now you understand why appending "mm" to the circle's position moved it. The transformation px->mm +has been applied twice! Once in the coordinate specification itself, and once by the "camera". + + +Units in Inkex +----------------- + +As an extension autor, you may have four different questions regarding units. + +What is the position of this object [in the user coordinate system]? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is a question that typically needs to be answered if you want to position an object relative +to other objects, whose coordinates may be specified in a different unit. + +The most convenient way to deal with this is to get rid of the units, and that means converting +everything to user units. + +Each :class:`BaseElement ` has a method +:meth:`to_dimensionless `. This method parses a +``length`` value and returns it, converted to px (user units). + +:meth:`~inkex.elements._base.BaseElement.to_dimensionless` fulfils the following task: +**Convert this string from the XML into a number, while processing the unit. +When using this function on any SVG attribute and replacing the +original value with the result, the output doesn't change visually.** + +In these and the following examples, the above "business card" SVG will be used. + +>>> svg = inkex.load_svg("docs/samples/units2.svg").getroot() +>>> svg.to_dimensionless(svg.getElementById("c1").get("cx")) +21.0 +>>> svg.to_dimensionless(svg.getElementById("c2").get("cx")) +21.0 +>>> svg.to_dimensionless(svg.getElementById("c3").get("cx")) +79.370078 + +For some classes, e.g. :class:`Rectangle `, convenience +properties are available which do the conversion for you, e.g. +:attr:`Rectangle.left `. Similarly there are some +properties for circles: + +>>> svg.getElementById("c3").center +Vector2d(79.3701, 52.9134) +>>> svg.getElementById("c2").radius +4.0 + +What is the dimension of an object in a specified unit in the user coordinate system? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can also convert from user units to any unit. This is done using +:meth:`BaseElement.to_dimensional `. + +>>> svg.to_dimensional(svg.getElementById("c2").radius, "px") +4.0 +>>> svg.to_dimensional(svg.getElementById("c2").radius, "mm") +1.0583333333333333 + +What is the dimension of an object on the viewport in arbitrary units? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is useful if you want to draw a property of a shape (for example its area) as text on the +canvas, in a unit specified by the user. The default unit to convert to is px. + +The method for this is called :meth:`BaseElement.unit_to_viewport `. + +>>> svg.unit_to_viewport(svg.getElementById("c2").radius) +15.118110236220472 +>>> svg.unit_to_viewport(svg.getElementById("c2").radius, "mm") +4.0 +>>> svg.unit_to_viewport("4", "mm") +4.0 + +In other words, ``unit_to_viewport(value, unit="px")`` answers the following +question: **What does the the width/height widget of the selection +tool (set to** ``unit`` **) show when selecting an element with width** +``value`` **as defined in the SVG?** Consider again +```` +, i.e. a "mm-based" document with scale=2. When selecting this rectangle, the rectangle tool +shows ``viewport_to_unit("100", unit="mm") = 200``, if the rectangle tool is set to mm. + +Obviously the element needs to know the viewport of its SVG document for this. This method therefore +does not work if the element is unrooted. + + +How big does an object have to be to have the specified size on the viewport? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is useful if you want to draw a shape at a given location on the viewport, regardless of +what the user coordinate system is. This is done using +:meth:`BaseElement.viewport_to_unit `. + +>>> svg.viewport_to_unit("4mm", "px") +4.0 +>>> svg.viewport_to_unit("4mm", "mm") +1.0583333333333333 + +An example for this would be text elements. In order for text to show up in Inkscape's text +tool as ``9pt``, you have to user + +>>> element.style["font-size"] = self.svg.viewport_to_unit("9pt") + +Again, this method will raise an error if the element is unrooted. + +In other words, ``viewport_to_unit(value, target_unit="px")`` answers the following question: +**What is the SVG representation of entering** ``value`` **in the width/height widget of the +selection tool (set to the unit of value)?** Consider +````, +i.e. a "mm-based" SVG with scale=2. When typing ``200`` in the +rectangle tool, set to mm, the XML editor shows ``100`` = +``100px``. That's what ``viewport_to_unit("200mm") = 100`` does. + +Note that this is different than +``viewport_to_unit("200", "mm")``, which would be for a rectangle +with a width (in the width/height widget of the rectangle tool) of +200 (px), while writing the width in ``mm`` *in the SVG*: +````. + +Document dimensions +^^^^^^^^^^^^^^^^^^^^^^^^ + +* :attr:`SvgDocumentElement.viewport_width ` + and + :attr:`SvgDocumentElement.viewport_height ` + are the width and height of the viewport coordinate system, i.e. the "output screen" of the + viewBox camera, in pixels. In above example: ``(317.480314, 211.653543)`` + +.. code-block: + 84mm * 96px/in / (25.4mm/in) = 317.480314 + [output size] [resolution 96dpi] [output size in pixels] + +* :attr:`SvgDocumentElement.viewbox_width ` + and + :attr:`SvgDocumentElement.viewbox_height ` + are the width and height of the user coordinate system, i.e. for a viewport without offset, the + largest ``x`` and ``y`` values that are visible to the viewport camera. + In above example: ``(84, 56)`` + +Conversion between arbitrary units +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The functions listed above are methods of :class:`BaseElement ` +because they use properties of the root SVG. For an unrooted SVG fragment, +:meth:`BaseElement.to_dimensionless `. +:meth:`BaseElement.to_dimensional ` work as well. + +If you want to convert between arbitrary units, you can do so using the +:meth:`convert_unit ` method: + +>>> inkex.units.convert_unit("4mm", "px") +15.118110236220472 + + +Note that inkex doesn't support relative units (percentage, `em` and `ex`) yet. You will have to +implement these yourself if you want your extension to support them. + +.. [1] https://www.w3.org/TR/SVG11/coords.html#Units +.. [2] https://www.w3.org/TR/SVG2/coords.html#Introduction +.. [3] https://www.w3.org/TR/SVG2/coords.html#ViewportSpace +.. [4] https://www.w3.org/TR/SVG2/coords.html#ViewBoxAttribute +.. [5] Note that this drawing has ``width="100%" height="" viewBox="0 0 88.540985 36.87265"``. + This instructs the viewer that the SVG should span the entire width of the containing + element (in this case, an HTML div) and the height should be chosen such that the image + is scaled proportionally. Inkex doesn't support these relative units and these don't really + make sense in standalone SVGs anyway. \ No newline at end of file diff --git a/share/extensions/docs/authors/update1.0.rst b/share/extensions/docs/authors/update1.0.rst new file mode 100644 index 0000000..294af52 --- /dev/null +++ b/share/extensions/docs/authors/update1.0.rst @@ -0,0 +1,301 @@ +Updating your extension for Inkscape 1.0 +======================================== + +.. warning:: This information is partially outdated. + +This is a preliminary and incomplete list of actions to take for +updating Python extensions for Inkscape 1.0: + +.. _adjusting_folder_structure: + +Adjusting folder structure +-------------------------- + +For easier extension 'installation' by users and for having a better +overview about the installed extensions, you can now put extensions into +their own subfolders of the ``extensions`` directory. This is optional. + +When specifying the command in the .inx file, you can use the new +parameter 'location'. + +- If you set ``location="extensions"`` (de-facto default in 0.92.x), it + will assume the path is relative to either user or system extensions + folder. +- If it's ``location="inx"`` (new and recommended in 1.0), it will + assume the path is relative to the .inx file location. + +An extension that uses the following snippet: + +.. code:: xml + + + +can be put into any subfolder in ``extensions`` or into the +``extensions`` folder itself, as long as the file ``hello.py`` is in +that same folder, at the same hierarchy level. + +The old parameter ``reldir`` is deprecated. It is recommended to use +Unix style path separators (i.e. ``/``), if your script file is located +in a nested subdirectory (should be a very rare case). + +.. _updating_.inx_files: + +Updating \*.inx files +--------------------- + +.. _remove_dependency_listings: + +Remove dependency listings +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Remove the dependency listings for the following modules: + +- bezmisc.py +- coloreffect.py +- cspsubdiv.py +- cubicsuperpath.py +- ffgeom.py +- inkex.py (removal not strictly required) +- pathmodifier.py +- simplepath.py +- simplestyle.py +- simpletransform.py +- more? + +This change is backwards compatible (as long as the user has a fully +functioning Inkscape installation). Not removing these will result in +the extension not being selectable (disabled and greyed out) in Inkscape +1.0 or higher. + +.. _changes_to_parameter_definitions: + +Changes to parameter definitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are also some updates to the parameter definitions in .inx files. +While these are intended to be backwards compatible to 0.92, you may +wish to review the changes below: + +- **Underscores** in inx parameter tags and attributes for translation + **can be dropped** entirely. Use ``translatable="no"`` to make an + item (e.g. a unit name) untranslatable. +- ``boolean`` can be renamed to ``bool`` +- ```` is deprecated, instead use optiongroups. + Remember to rename ``item`` to ``option`` when replacing. +- In optiongroups ``appearance="minimal"`` is deprecated. + + - In optiongroups you can now define dropdown selections + (comboboxes) and radio buttons. + - i.e. ````, or + ````. + +- Choosing files / folders with ```` + (these return the path as a string to the Python script) +- Color choosers: make them more compact with + ``appearance="colorbutton"`` for parameters of type ``color`` +- Multiline text entry fields are available with + ``appearance="multiline"`` for parameters of type ``string`` +- The following new widgets (static, do not need to be read in by the + .py file's option parser anymore): + + - ``label``: (````), replaces parameters of type + ``description`` (which never really were parameters in the actual + sense), optionally with ``appearance="header"``. + - ``hbox``/``vbox``: for layouting purposes (allow to pack child + widgets into horizontally/vertically oriented boxes) + - ```` / ````: which add a variable space or separating line between child + widgets. + - ``my_image.svg``: which allows to display an image in the + extension UI + +See :ref:`inx-widgets` for more details. + +Example file with many of the new features: + +.. code:: xml + + + + Layout Demo + org.inkscape.test.layout_demo + pathmodifier.py + + + + + + + + true + 12345 + 1.2345 + 0x12345678 + + + + + a string value + + + + a\nmultiline\nstring\nvalue + + + + + my/path/to/file.png + + my/path/to/file.png + + my/path/to/file.png + + + + + + + + my/path/ + my/path/to/file.png + my/path/ + + + + + ink_icon.svg + + + + + + + + + + + + all + + + + + + + +.. _updating_.py_files: + +Updating \*.py files +-------------------- + +.. _collecting_the_options_of_the_extension: + +Collecting the options of the extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#. Instead of ``inkex.Effect.OptionParser.add_option``, your extension + should now use ``inkex.Effect.arg_parser.add_argument``. +#. The 'type' option now works with variables instead of strings. Use + ``int`` instead of ``"int"`` (same for float,...). +#. The 'inkbool' type is now ``inkex.Boolean``. +#. ``action="store"`` can be removed. + +These changes are not backwards compatible. The old options will still +work, but are deprecated and should no longer be used when you develop +your extension for Inkscape 1.0 or higher. + +.. _replace_specific_functions: + +Replace specific functions +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the .inx file is valid and not greyed out (meaning: a dependency is +missing), you can start building the .py file up again. + +In the Inkscape extensions refactoring process for Inkscape 1.0, many +inkex functions have been removed, or renamed, or moved, or options have +changed. Wherever possible, Inkscape will try to replace the old +function by the new one, and will give you a deprecation warning, with +instructions what to replace them by. + +E.g. ``inkex.Effect.selected`` is replaced by +``inkex.Effect.svg.selected`` - however, most replacements do not follow +this naming scheme translation. + +These changes are not backwards compatible. + +.. _python_3_python_2_compatibility: + +Python 3 / Python 2 compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: Starting from Inkscape 1.1, only Python 3 is supported. + +Test your extension with both Python 2 and Python 3, if you want it to +work for as many users as possible. With the updated extensions, +Inkscape does no longer require Python 2, so some users will probably be +using Python 3, and may no longer have Python 2 installed on their +system. See `Extension_Interpreters `__ for how +to set the Python version for your extension in the preferences file +(for testing). + +.. _getting_your_extension_added_to_inkscapes_stock_extensions: + +Getting your extension added to Inkscape's stock extensions +----------------------------------------------------------- + +Inkscape now has a `separate repository for its Python +extensions `__, which is +included into Inkscape proper by using a Git submodule. + +.. _writing_tests: + +Writing tests +~~~~~~~~~~~~~ + +Previously Inkscape didn't require any unit testing for code. You should +now write test code if you expect your module to be included into the +Inkscape extensions repository and included in the shipped Inkscape +release. In this case, a test suite file should be made in the tests +directory for your extension. It should test each aspect of your +extension and exercise all assumptions. + +If you are writing a standalone extension that users will install +themselves, there is no strict requirement for tests. But having them +will greatly improve your code and your ability to upgrade the code +later. You can have tests in your own folders and use the extension's +setup.py as a harness to run them (a setup.py file is also useful for +installing your python code as a non-inkscape related python module, +which might be useful too). See Python documentation for creating +packages. + +.. _documenting_your_extension: + +Documenting your extension +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Docstrings +---------- + +Include docstrings in your extension, so documentation can be built from +them automatically. + +.. _submitting_your_extension_for_inclusion: + +Submitting your extension for inclusion +--------------------------------------- + +Visit https://gitlab.com/inkscape/extensions, fork the repository, and +create a merge request on GitLab. + +.. _external_links: + +External links +-------------- + +A script to perform some of the conversion steps automatically has been +contributed: https://gitlab.com/inkscape/extensions/-/issues/380 + diff --git a/share/extensions/docs/authors/update1.2.rst b/share/extensions/docs/authors/update1.2.rst new file mode 100644 index 0000000..d50323a --- /dev/null +++ b/share/extensions/docs/authors/update1.2.rst @@ -0,0 +1,229 @@ +Updating your extension for Inkscape 1.2 +========================================= + +This page is intended for extension authors who want to use the new +capabilities of inkex in Inkscape 1.2. As of the Release of 1.2alpha +(Feb 5, 2022), no more breaking changes will be introduced until the +final release of 1.2. + +There are no breaking changes in this release, but a few methods have +been deprecated. + +.. _deprecating_changes: + +Deprecating changes +------------------- + +- The Transforms multiplication operator has been changed from ``*`` + (``*=``) to ``@`` (``@=``), in accordance with + `PEP-465 `__ (`MR + extensions#389 `__, + `Issue + extensions#327 `__) +- ``svg.width`` and ``svg.height`` have been deprecated, and replaced + with ``svg.viewbox_width``, ``svg.viewport_width``, + ``svg.viewbox_height`` and ``svg.viewport_height``, see `New Units + API `__. +- ``selection.paint_order`` has been renamed to + ``selection.rendering_order`` to be conformant with the specification + (`MR + extensions#344 `__, + `Issue + extensions#310 `__) +- ``FallbackStyle`` has been deprecated in favor of ``Style``, see `New + Style API `__. + +.. _new_style_api: + +New Style API +------------- +.. figure:: samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png + + Top: W3C SVG1.1 Test suite, + test `styling-css-04-f.svg `__. + This test includes various CSS selectors, and includes group inheritance + and pseudo-selectors. It is rendered correctly in Inkscape 1.2. Bottom + left: Output of the "Lighter" extension in Inkscape 1.1.2, only two + squares are processed correctly, two squares have a wrong color and the + other 14 raise unhandled exceptions. Bottom right: Correct output in + Inkscape 1.2. This shows that inkex correctly handles different types of + CSS selectors. + +Added in `MR +extensions#294 `__, +`MR +extensions#296 `__, +`MR +extensions#298 `__, +`MR +extensions#300 `__, +`MR +extensions#352 `__, +`MR +extensions#403 `__ + +Inkex now exposes styles to extensions authors as intended by the SVG +specification. This means: + +- ``BaseElement`` now has functions ``cascaded_style``, + ``specified_style`` and ``presentation_style``. +- In most use cases, extensions querying a style will use + ``specified_style``. This computes the `effective + style `__ + of the element, including CSS classes / pseudo-selectors, inherited + styles, presentation attributes etc. +- While ``style.get()`` and ``style[key]`` has been unchaged, a new + getter has been added in form of ``style(key)`` (similar to a + function call), which attempts to parse the attribute in a reasonable + datatype. If the attribute is unset, the (parsed) default value will + be returned. For example: + + - ``style("fill")`` returns a ``Color`` / ``Gradient`` / ``Pattern`` + / ``None``, + - ``style("opacity")`` returns a value between 0 and 1, regardless + if opacity is defined as percentage or as float, is out of bounds + or undefined, + - ``style("stroke-dasharray")`` returns a list of floats of + dash/gap/dash/gap in user units. + +- Not for all attributes there is a parser defined - in that case, a + string will be returned. Additional parsers may be added in the + future, so if you handle the string value, typecheck it first! + +.. _using_the_new_style_api_in_your_extension: + +Using the new Style API in your extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following calls can probably be simplified: + ++----------------------------------------------------+----------------------------------------------------+ +| Old code (pre-1.2) | New code (1.2+) | ++====================================================+====================================================+ +| .. code:: python3 | .. code:: python3 | +| | | +| if "fill-opacity" in self.style: | alpha = self.style("fill-opacity") | +| alpha = self.style["fill-opacity"] | | +| else: | | +| alpha = 1 | | ++----------------------------------------------------+----------------------------------------------------+ +| .. code:: python3 | .. code:: python3 | +| | | +| if not node.style.get(attr, '')\ | marker_node = node.style(attr) | +| .startswith('url(#'): | | +| continue | | +| | | +| marker_id = node.style[attr][5:-1] | | +| marker_node = self.svg.getElement( | | +| f'/svg:svg//svg:marker[@id="{marker_id}"]') | | ++----------------------------------------------------+----------------------------------------------------+ +| .. code:: python3 | .. code:: python3 | +| | | +| obj.style['fill'] = pattern.get_id(2) | obj.style['fill'] = pattern | ++----------------------------------------------------+----------------------------------------------------+ + +Checkout `MR +extensions#298 `__ +for additional examples of simplifications. + +.. _new_units_api: + +New Units API +------------- + +Added in `MR +extensions#329 `__, +`MR +extensions#343 `__, +`MR +extensions#415 `__ + +The existing functions ``unittouu`` and ``uutounit`` are widely used, +but for different purposes. Different extension authors try to answer +different questions using these function, and, inevitably, some answers +were incorrect (see linked issues in `MR +extensions#329 `__). + +In Inkscape 1.2, new methods have been added to make working with +dimensional values easier. These are ``to_dimensionless``, +``to_dimensional``, ``viewport_to_unit`` and ``unit_to_viewport``. The +existing functions ``unittouu`` and ``uutounit`` are not deprecated, but +discouraged; in most cases, the new functions are more reliable. + +- ``to_dimensionless(value)`` fulfills the following task: **Convert + this string from the XML into a number, while processing the unit. + When using this function on any SVG attribute and replace the + original value with the result, the output doesn't change visually.** +- ``viewport_to_unit(value, target_unit="px")`` answers the following + questions: + + - **What is the length (e.g. the length of a rectangle, without a + unit) of an object that has size** ``value`` **on the viewport?** This + is relevant because in Inkscape toolbars / tools, all dimensions + are shown in "viewport units". + - In other words: **What is the SVG representation of entering + ``value`` in the width/height widget of the selection tool (set to + the unit of value)?** Consider ```` + , i.e. a "mm-based" SVG with scale=2. When typing ``200`` in the + rectangle tool, set to mm, the XML editor shows ``100`` = + ``100px``. That's what ``viewport_to_unit("200mm") = 100`` does. + + - Note that this is different than + ``viewport_to_unit("200", "mm")``, which would be for a rectangle + with a width (in the width/height widget of the rectangle tool) of + 200 (px), while writing the width in ``mm`` *in the SVG*: \ + ````. + +- ``to_dimensional`` simply converts a float to its equivalent with + attached unit. It's the opposite of ``to_dimensionless``. +- ``unit_to_viewport(value, unit="px")`` answers the following + question: **What does the the width/height widget of the selection + tool (set to** ``unit`` **) show when selecting an element with width + ``value`` as defined in the SVG?** Consider again ```` + , i.e. a "mm-based" document with scale=2. To create this rectangle, + one has to type ``viewport_to_unit("100", unit="mm") = 200`` into the + rectangle tool, if the rectangle tool is set to mm. + +With the same spirit, the functions for width/height of the document +have been updated. ``svg.width`` and ``svg.height`` have been +deprecated, and replaced with ``svg.viewbox_width``, +``svg.viewport_width``, ``svg.viewbox_height`` and +``svg.viewport_height``. + +There is also ``svg.scale``, which returns the ratio of the viewport and +viewbox width, and ``svg.inkscape_scale`` which is the scale reported in +the Document properties dialog. + +See :ref:`units` for additional information. + +.. _other_additions_to_inkex: + +Other additions to inkex +------------------------ + +- The path conversion for arcs and stars have been added, so when + extensions create these objects, they are rendered in a browser as + well and can be processed further by the same extension. (`MR + extensions#387 `__, + `Issue + extensions#240 `__) +- ``ColorExtension``\ s can now process in RGBA space. Previously, + opacity and color were processed independently. By setting the class + variable ``pass_rgba = True``, the ``modify_color`` method gets + passed a color with alpha channel computed from matching property + pairs, e.g. ``fill`` and ``fill-opacity``. (This value takes CSS + styling and style inheritance into account. (`MR + extensions#392 `__ + , `Issue + extensions#419 `__). +- API functions for the new `multipage + feature `__ have been added: `MR + extensions#499 `__. + +.. _other_deprecations_to_inkex_1_2 + +Other deprecations to inkex +---------------------------- + +- Pre Inkscape 1.0 way of declaring the dependency on inkex in the ``*.inx`` file has been removed entirely. (It was deprecated in Inkscape 1.0. For details, see :ref:`remove_dependency_listings`) + diff --git a/share/extensions/docs/authors/widgets/bool.png b/share/extensions/docs/authors/widgets/bool.png new file mode 100644 index 0000000..dbf5588 Binary files /dev/null and b/share/extensions/docs/authors/widgets/bool.png differ diff --git a/share/extensions/docs/authors/widgets/color.png b/share/extensions/docs/authors/widgets/color.png new file mode 100644 index 0000000..1d6e894 Binary files /dev/null and b/share/extensions/docs/authors/widgets/color.png differ diff --git a/share/extensions/docs/authors/widgets/float.png b/share/extensions/docs/authors/widgets/float.png new file mode 100644 index 0000000..63ac125 Binary files /dev/null and b/share/extensions/docs/authors/widgets/float.png differ diff --git a/share/extensions/docs/authors/widgets/image.png b/share/extensions/docs/authors/widgets/image.png new file mode 100644 index 0000000..057b1d0 Binary files /dev/null and b/share/extensions/docs/authors/widgets/image.png differ diff --git a/share/extensions/docs/authors/widgets/integer.png b/share/extensions/docs/authors/widgets/integer.png new file mode 100644 index 0000000..da376db Binary files /dev/null and b/share/extensions/docs/authors/widgets/integer.png differ diff --git a/share/extensions/docs/authors/widgets/label.png b/share/extensions/docs/authors/widgets/label.png new file mode 100644 index 0000000..fb1e470 Binary files /dev/null and b/share/extensions/docs/authors/widgets/label.png differ diff --git a/share/extensions/docs/authors/widgets/notebook.png b/share/extensions/docs/authors/widgets/notebook.png new file mode 100644 index 0000000..f21dcec Binary files /dev/null and b/share/extensions/docs/authors/widgets/notebook.png differ diff --git a/share/extensions/docs/authors/widgets/optiongroup.png b/share/extensions/docs/authors/widgets/optiongroup.png new file mode 100644 index 0000000..a8d9d7d Binary files /dev/null and b/share/extensions/docs/authors/widgets/optiongroup.png differ diff --git a/share/extensions/docs/authors/widgets/path.png b/share/extensions/docs/authors/widgets/path.png new file mode 100644 index 0000000..3050182 Binary files /dev/null and b/share/extensions/docs/authors/widgets/path.png differ diff --git a/share/extensions/docs/authors/widgets/separator.png b/share/extensions/docs/authors/widgets/separator.png new file mode 100644 index 0000000..e4e7e2e Binary files /dev/null and b/share/extensions/docs/authors/widgets/separator.png differ diff --git a/share/extensions/docs/authors/widgets/spacer.png b/share/extensions/docs/authors/widgets/spacer.png new file mode 100644 index 0000000..32ab128 Binary files /dev/null and b/share/extensions/docs/authors/widgets/spacer.png differ diff --git a/share/extensions/docs/authors/widgets/string.png b/share/extensions/docs/authors/widgets/string.png new file mode 100644 index 0000000..b95ffff Binary files /dev/null and b/share/extensions/docs/authors/widgets/string.png differ diff --git a/share/extensions/docs/conf.py b/share/extensions/docs/conf.py new file mode 100644 index 0000000..62e2884 --- /dev/null +++ b/share/extensions/docs/conf.py @@ -0,0 +1,93 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys + +sys.path.insert(0, os.path.abspath("../")) + +import datetime + +# -- Project information ----------------------------------------------------- + +project = "inkex documentation" +copyright = f"{datetime.datetime.now().year} The Inkscape Project" +author = "The Inkscape Project" + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", + "sphinx.ext.todo", + "sphinx.ext.napoleon", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "pydata_sphinx_theme" + +html_theme_options = { + "show_toc_level": 2, + "use_edit_page_button": True, + "gitlab_url": "https://gitlab.com/inkscape/extensions", +} + +html_context = { + "gitlab_user": "inkscape", + "gitlab_repo": "extensions", + "gitlab_version": "master", + "doc_path": "docs", +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ["_static"] + +# -- Extension configuration ------------------------------------------------- + +always_document_param_types = True + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +autodoc_member_order = "bysource" + +autodoc_preserve_defaults = True + +html_favicon = "favicon.svg" diff --git a/share/extensions/docs/dev/getting-started.rst b/share/extensions/docs/dev/getting-started.rst new file mode 100644 index 0000000..63d8a46 --- /dev/null +++ b/share/extensions/docs/dev/getting-started.rst @@ -0,0 +1,148 @@ +Getting started with developing inkex +===================================== + +.. highlight:: bash + +.. warning:: + + This document is tailored for contributors to the inkex package and core extensions. + + Extension authors should look here: :ref:`authors-tutorial` + +Repository setup +---------------- + +It is possible to synchronize a fork with the extensions repository - whenever a branch in the +mirrored repository is updated, your fork will be updated too (usually with a delay of up to one +hour). See `Settings -> Repository -> Mirroring Repositories` and add a "Pull" mirror. + +.. warning:: + + If you use this method, **do not** add commits to branches that should be synced + (such as `master`). + Depending on the exact settings of the mirroring option, you will either lose your changes, + lose the synchronisation or run into a messed up branch history. + +Always check out submodules as well:: + + git submodule update && git submodule init + +Python setup +------------ + +On every operating system, you need a working Python environment. Currently, inkex is tested +against Python 3.7-3.10. + +inkex manages its dependencies using `poetry `_. It can be installed using:: + + pip install poetry + +Install the dependencies and the pre-commit hook:: + + poetry install + pre-commit install + +Testing changes in Inkscape +--------------------------- + +Most of the time, calling the python file of the extension directly and through unit tests is +sufficient. In some cases, the interaction between Inkscape and the extension should be tested, +though. + +Assuming you have managed to make Inkscape look in the correct folder for the extensions (see hints +for different operating systems below), the python +file of an extension is reloaded every time the extension is run. For changes to the inx file or +the command line parameters of the extension (as defined in the +:func:`~inkex.base.InkscapeExtension.add_arguments` method) you need to restart Inkscape. + +Developing extensions on Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +.. highlight:: batch + +To test extensions with a given Inkscape version, download the 7z archive of that version, +unarchive it and delete the ``inkscape\share\extensions`` folder. Next, create a symlink in that +folder from an administrative command prompt:: + + cd [directory of the unzipped Inkscape folder] + mklink /D share\extensions C:\path\to\your\fork + +If you start ``bin\inkscape`` now, the extensions are loaded from your fork. + +Developing extensions on Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. highlight:: bash + +A very similar path to Windows can be used when working off an appimage build. + +Extract the appimage into a new folder called ``squashfs-root``:: + + /path/to/appimage --appimage-extract + squashfs-root/AppRun --system-data-directory + +This prints the location of the extensions folder. Create a symlink to your repo there and run:: + + squashfs-root/AppRun + +Trying / Changing a merge request locally +----------------------------------------- + +Add this to ``git config -e`` (only once):: + + [remote "upstream"] + url = git@gitlab.com:inkscape/extensions.git + fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* + [alias] + mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' - + +Check out the merge request !123:: + + git mr upstream 123 + +Push changes to the source branch ``source-branch-name`` of fork in the namespace (typically the +author's username) ``xyz``:: + + git push git@gitlab.com:xyz/extensions.git mr-origin-123:source-branch-name + + +Adding/Updating dependencies +---------------------------- + +.. highlight:: bash + +The *direct* dependencies of inkex are declared in the ``pyproject.toml`` file. + +There is also a lockfile named ``poetry.lock`` which has *all* the dependencies +(direct, dependencies of direct, dependencies of dependencies of direct and so on till the leaf dependencies) +pinned to specific versions (versions which were compatible the last time lockfile was updated). + +To update all the dependencies in the lockfile to latest compatible versions, enter:: + + poetry lock + +To add/update a particular dependency, add it to ``pyproject.toml`` manually. The dependency should be declared in the +``[tool.poetry.dependencies]`` TOML table, while a dependency required only during development of inkex should be declared in +``[tool.poetry.dev-dependencies]``. + +Then update the lockfile using:: + + poetry lock + +Alternatively, you can add a dependency and update the lockfile in a single command:: + + poetry add "lxml@^4.5.0" --lock + +Both the ``pyproject.toml`` and ``poetry.lock`` are to be committed to the repository. + +.. note:: + + You don't need to install the dependencies to add/update them. So, the commands above don't install anything. + However, if you are using poetry to manage the environment, and want to also install the dependencies, + remove the ``--lock`` options from the commands and use ``poetry update`` instead of ``poetry lock``. + +.. note:: + + Dependencies should be updated according to the `policy `_ defined in Inkscape wiki . + diff --git a/share/extensions/docs/dev/index.rst b/share/extensions/docs/dev/index.rst new file mode 100644 index 0000000..a38cf03 --- /dev/null +++ b/share/extensions/docs/dev/index.rst @@ -0,0 +1,8 @@ +inkex (and core Extensions) development +======================================= + +.. toctree:: + :maxdepth: 2 + + getting-started + Writing unit tests <../authors/unit-tests> \ No newline at end of file diff --git a/share/extensions/docs/favicon.svg b/share/extensions/docs/favicon.svg new file mode 100644 index 0000000..cf0292a --- /dev/null +++ b/share/extensions/docs/favicon.svg @@ -0,0 +1,159 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/docs/index.rst b/share/extensions/docs/index.rst new file mode 100644 index 0000000..abfc319 --- /dev/null +++ b/share/extensions/docs/index.rst @@ -0,0 +1,35 @@ +Welcome to inkex's documentation! +================================= + +.. toctree:: + :maxdepth: 1 + :hidden: + + Tutorial + authors/index + Inkex Development + API Reference + +**Useful links**: +`Source Repository `_ | +`Issue Tracker `_ | +`Chat `_ + +Inkex is: + +- a general-purpose SVG reading/writing/modification package +- an object-oriented interface for access to + many common SVG attributes, such as paths and styles +- the Python package that enables Inkscape extensions + +Furthermore, :mod:`inkex.gui` provides a way to ship GTK interfaces with extensions, and +:mod:`inkex.tester` is a package to facilitate unit testing of extensions. + +Welcome to its documentation! + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/share/extensions/docs/make.bat b/share/extensions/docs/make.bat new file mode 100644 index 0000000..21b58de --- /dev/null +++ b/share/extensions/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/share/extensions/docs/source/index.rst b/share/extensions/docs/source/index.rst new file mode 100644 index 0000000..b8aad2c --- /dev/null +++ b/share/extensions/docs/source/index.rst @@ -0,0 +1,21 @@ +.. inkex documentation master file, created by + sphinx-quickstart on Tue May 18 23:45:21 2021. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +API Reference +============= + +.. toctree:: + :maxdepth: 4 + :caption: Contents: + + inkex + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/share/extensions/docs/tutorial/index.rst b/share/extensions/docs/tutorial/index.rst new file mode 100644 index 0000000..0e9551a --- /dev/null +++ b/share/extensions/docs/tutorial/index.rst @@ -0,0 +1,49 @@ +.. _authors-tutorial: + +Tutorial +======== + +Introduction +------------ + +Extensions are small programs that extend Inkscape’s functionality. They +can provide features for specific tasks, experimentation, or art styles. +They can also add support for special hardware or different export +formats. While many extensions are included with Inkscape, you can also +install extensions written by third parties or write your own. + +This guide aims to provide you with enough information to write your own +extension using the python programming language and a text editor. You +should have the latest version of Inkscape installed. While Inkscape +extensions generally work across platforms, this guide will use Linux as +its default operating system. Linux is not required for writing +extensions, but you may need to modify the location of files on your +computer as you follow along. You may also need to use other “helper†+programs, for example a different text editor, depending on your +operating system. + +When a user selects an extension from the menu within Inkscape, Inkscape +opens a pop-up dialog that presents information to the user and/or +allows the user to enter any parameters that are necessary to use the +extension. An extension can also be configured to run immediately +without an intermediate dialog, for example if it does not have any +adjustable parameters. When the user clicks **Apply** in the dialog, the +parameters are passed to the extension program along with the svg file +and a list of selected objects. The extension program itself then runs, +and the data that it returns will be used to update Inkscape’s svg +canvas or to save data to disk. + +We’ve made this process easier for you by creating a set of template +extensions which you can download as the starting point for this +tutorial. If you are a beginner we recommend that you start with the +Effect Extension Template. Input, Output and other types of extensions +will be covered in the more advanced topics later. + +.. toctree:: + :maxdepth: 1 + + my-first-effect-extension + simple-path-extension + my-first-text-extension + my-first-import-extension + diff --git a/share/extensions/docs/tutorial/my-first-effect-extension.rst b/share/extensions/docs/tutorial/my-first-effect-extension.rst new file mode 100644 index 0000000..7666288 --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-effect-extension.rst @@ -0,0 +1,130 @@ +.. _first-effect-extension: + +My first effect extension +========================= + +Resources +--------- + +- :download:`Template Files ` +- :download:`Example solution ` + +Introduction +------------ +Effect extensions take the svg from Inkscape, modify it in some way and +pass the modified version back to Inkscape to be rendered onto the +canvas. This can be very powerful, allowing everything from randomising +colours to manipulating path elements in external programs. + +We are going to write an effect extension that will simply change the fill +any selected object to red. + +Step One +--------- + +Extract the ``Effect Extension Template`` files into a folder on your +computer. You should have two files, one inx file and one python file. +Move or link these files into your extensions directory as you would +when installing extensions manually. This is the directory listed at +``Edit > Preferences > System: User extensions``. + +Edit the inx file in a text editor and change the name of the extension +to ``Make Red Extension`` and the id to +``org.inkscape.tutorial.make_red_extension`` by changing these lines near +the top: + +.. code:: xml + + + + Make Red Extension + org.inkscape.tutorial.make_red_extension + [...] + +Toward the end of the .inx file, change the submenu to ``Color`` +specify that this extension will be listed in the ``Color`` submenu +under the ``Extensions`` menu: + +.. code:: xml + + [...] + + + + + + + [...] + +Step Two +--------- + +Next, open ``my_effect_extension.py`` in your text editor. You can see +this is an inkex extension because it contains a python class that +inherits from ``inkex.EffectExtension``. Change the class name to +``MakeRedExtension``: + +.. code:: python + + [...] + class MakeRedExtension(inkex.EffectExtension): + [...] + +Reflect this change down in the ``__main__`` section of the code by +changing the class name to ``MakeRedExtension`` there: + +.. code:: python + + [...] + if __name__ == '__main__': + MakeRedExtension().run() + +When a standard inkex-based python effect extension is run, it will call +a method called :func:`~inkex.base.InkscapeExtension.effect` on your extension's class. So, most of the +code you need to write will go there. Edit +``my_effect_extension.py``\ 's ``effect()`` method to look like the +following, **being sure that the indentation is correct so that** +``effect()`` **is recognized as a method of the MakeRedExtension class**: + +.. code:: python + + for elem in self.svg.selection: + elem.style['fill'] = 'red' + elem.style['fill-opacity'] = 1 + elem.style['opacity'] = 1 + + + +Code Explanation +~~~~~~~~~~~~~~~~ + +We want to change the color of all selected objects to red. For this we need to loop +through each of the selected paths. The first line of :func:`inkex.base.InkscapeExtension.effect` +does this. The :attr:`~inkex.elements._svg.SvgDocumentElement.selection` attribute of ``self.svg`` +contains the currently selected objects. + +.. hint:: + ``self.svg`` contains the SVG document in its current state - passed by Inkscape - and + is already parsed for us, so we don't have to manipulate the XML manually. Instead, inkex offers + an object-oriented interface to all the SVG element types. + +Each element has a ``style`` attribute: it's one of the +:attr:`~inkex.elements._base.BaseElement.WRAPPED_ATTRS` of each element, so ``elem.style`` is a +:class:`~inkex.styles.Style` object (you can think of it as a dictionary). And in this dictionary, +we set the value for ``'fill'`` to ``'red'``. We also set the ``'fill-opacity'`` to ``1``, in case +the object was transparent previously. + + +Final Step +------------ + +That’s it! There’s no need to set, save or do anything else as we’ve +modified the style in place. + +Save your python script, and re-launch Inkscape. If inkscape was already +open, close it first. You should find your new extension available in +the ``Effect`` menu. + +Draw some shapes in Inkscape. Select some of the shapes and use the extension. +The fill of all objects should change to red. + diff --git a/share/extensions/docs/tutorial/my-first-import-extension.rst b/share/extensions/docs/tutorial/my-first-import-extension.rst new file mode 100644 index 0000000..6c296bd --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-import-extension.rst @@ -0,0 +1,305 @@ +My first import extension +========================= + +Resources +--------- + +:download:`vanillin.smi ` + +Introduction +------------ + +This article will teach you the basics of writing an Import Extension for +Inkscape using the ``inkex`` Extensions API. + +Import Extensions are used to add support for a file format that +Inkscape does not support out of the box. It is rather complex to implement an entire file format, +but often there are already tools available to convert the file to a format that Inkscape can read, +such as SVG or PDF. In this case, the extension depends on external programs that convert that +specific file format to a svg that Inkscape can then read. + +The way these extensions are used is not through the ``Extensions`` menu +but instead these provide options in\ ``File``>\ ``Open`` or +``File``>\ ``Import`` dialog. + +The general flow of a Import Extension is as follows: + +1) You select the specific file format from the File Format drop down + menu of the ``File``>\ ``Open`` or ``File``>\ ``Import``\ dialog. +2) You select one or more files of that specific file format. You click + on ``Open`` button. +3) Inkscape will then either open the svg file in a new window or will + import it depending on which dialog of ``File`` menu was used. + +.. hint:: + + You can entirely skip 1) and 2) and just double click on + the file. If your extension is set up correctly, you won’t notice the + difference between opening a regular file and your file. + +In this article we will create an extension named +``Organic Bond Visualizer``. It will produce the bond structure of an +organic compound given a +`SMILES `__ +file. The extension uses an external program called ``indigo-depict`` +which has its GitHub repository +`here `__. (It is a part of the +``indigo-utils`` package in Debian/Ubuntu repositories. For other +platforms you might need to build it from source.) + +.. note:: A note on **PATH** + + Since the extension depends on external programs, it is important that + these external programs can be found by our extensions. For that to + happen, either these programs **should** be on your *system PATH* or an + absolute path for the program should be used in the code. + + Depending on the operating system, the steps required for adding + programs to the PATH might vary. + + You can get away with setting the PATH variable entirely by using an + absolute path for the program but it is almost always a bad idea to + hard-code paths in the code. + +.. hint:: + + This article assumes you create all extension related files in the + User Extensions directory which is listed at + ``Edit``>\ ``Preferences``>\ ``System`` - ``User Extensions:`` in + Inkscape. + +Step 0 : The Boilerplate +------------------------ + +Like any other Inkscape extension, this extension will also have two +files. So, create a ``organic_bond_vis.inx`` file and a +``organic_bond_vis.py`` file. + +- ``organic_bond_vis.inx`` - It will have the necessary information for + Inkscape to be able to recognize your extension as a valid Inkscape + extension. It will also have the info required to present the + extension as an option in ``File``>\ ``Open`` or + ``File``>\ ``Import`` dialog. +- ``organic_bond_vis.py`` - It will have the actual Python code your + extension will execute. + +.. hint:: + + There is another file that is worth mentioning here - the **test** + file which in our case will be ``test_organic_bond_vis.py``. It is + not required to be present for an extension per se, but as a best + practice, the extension code should always be accompanied by test + code. + +Step 1 : Populate the ``*.inx`` file +------------------------------------ + +.. code:: xml + + + + Organic Bond Visualizer + org.inkscape.input.bondvisualizer + indigo-depict + + + + +The lines below help Inkscape uniquely identify our extension. You +should modify these two lines for your own extension: + +.. code:: xml + + [...] + Organic Bond Visualizer + org.inkscape.input.bondvisualizer + [...] + +Now we declare the dependency of our extension: + +.. code:: xml + + indigo-depict + +The `` + Inkscape Output + + + + + + + """ + return dedent(html) % (self.width, self.height, self.obj, "".join(self.code)) + + def equal_style(self, style, key): + """Checks if the last style used is the same or there's no style yet""" + if key in self.style_cache: + return True + if key not in style: + return True + return style[key] == self.style_cache[key] + + def begin_path(self): + self.write("ctx.beginPath();") + + def create_linear_gradient(self, href, x1, y1, x2, y2): + data = (href, x1, y1, x2, y2) + self.write( + "var %s = \ + ctx.createLinearGradient(%f,%f,%f,%f);" + % data + ) + + def create_radial_gradient(self, href, cx1, cy1, rx, cx2, cy2, ry): + data = (href, cx1, cy1, rx, cx2, cy2, ry) + self.write( + "var %s = ctx.createRadialGradient\ + (%f,%f,%f,%f,%f,%f);" + % data + ) + + def add_color_stop(self, href, pos, color): + self.write("%s.addColorStop(%f, %s);" % (href, pos, color)) + + @staticmethod + def get_color(rgb, alpha): + return "'{}'".format(str(Color(rgb).to_rgba(alpha))) + + def set_gradient(self, href): + """ + for stop in gstops: + style = simplestyle.parseStyle(stop.get("style")) + stop_color = style["stop-color"] + opacity = style["stop-opacity"] + color = self.get_color(stop_color, opacity) + pos = float(stop.get("offset")) + self.add_color_stop(href, pos, color) + """ + return None # href + + def set_opacity(self, value): + self.write("ctx.globalAlpha = %.1f;" % float(value)) + + def set_fill(self, value): + alpha = self.style("fill-opacity") + if not value.startswith("url("): + fill = self.get_color(value, alpha) + self.write("ctx.fillStyle = %s;" % fill) + + def set_stroke(self, value): + alpha = self.style("stroke-opacity") + self.write("ctx.strokeStyle = %s;" % self.get_color(value, alpha)) + + def set_stroke_width(self, value): + self.write("ctx.lineWidth = %f;" % self.parent.svg.unittouu(value)) + + def set_stroke_linecap(self, value): + self.write("ctx.lineCap = '%s';" % value) + + def set_stroke_linejoin(self, value): + self.write("ctx.lineJoin = '%s';" % value) + + def set_stroke_miterlimit(self, value): + self.write("ctx.miterLimit = %s;" % value) + + def set_font(self, value): + self.write('ctx.font = "%s";' % value) + + def move_to(self, x, y): + self.write("ctx.moveTo(%f, %f);" % (x, y)) + + def line_to(self, x, y): + self.write("ctx.lineTo(%f, %f);" % (x, y)) + + def close_path(self): + self.write("ctx.closePath();") + + def quadratic_curve_to(self, cpx, cpy, x, y): + data = (cpx, cpy, x, y) + self.write("ctx.quadraticCurveTo(%f, %f, %f, %f);" % data) + + def bezier_curve_to(self, x1, y1, x2, y2, x, y): + data = (x1, y1, x2, y2, x, y) + self.write("ctx.bezierCurveTo(%f, %f, %f, %f, %f, %f);" % data) + + def rect(self, x, y, width, height, rx=0, ry=0): + if rx or ry: + # rounded rectangle, starts top-left anticlockwise + self.move_to(x, y + ry) + self.line_to(x, y + height - ry) + self.quadratic_curve_to(x, y + height, x + rx, y + height) + self.line_to(x + width - rx, y + height) + self.quadratic_curve_to(x + width, y + height, x + width, y + height - ry) + self.line_to(x + width, y + ry) + self.quadratic_curve_to(x + width, y, x + width - rx, y) + self.line_to(x + rx, y) + self.quadratic_curve_to(x, y, x, y + ry) + else: + self.write("ctx.rect(%f, %f, %f, %f);" % (x, y, width, height)) + + def arc(self, x, y, r, a1, a2, flag): + data = (x, y, r, a1, a2, flag) + self.write("ctx.arc(%f, %f, %f, %f, %.8f, %d);" % data) + + def fill_text(self, text, x, y): + self.write('ctx.fillText("%s", %f, %f);' % (text, x, y)) + + def translate(self, cx, cy): + self.write("ctx.translate(%f, %f);" % (cx, cy)) + + def rotate(self, angle): + self.write("ctx.rotate(%f);" % angle) + + def scale(self, rx, ry): + self.write("ctx.scale(%f, %f);" % (rx, ry)) + + def transform(self, m11, m12, m21, m22, dx, dy): + data = (m11, m12, m21, m22, dx, dy) + self.write("ctx.transform(%f, %f, %f, %f, %f, %f);" % data) + + def save(self): + self.write("ctx.save();") + + def restore(self): + self.write("ctx.restore();") + + def finish_path(self): + if self.style("fill") is not None: + self.write("ctx.fill();") + if self.style("stroke") is not None: + self.write("ctx.stroke();") diff --git a/share/extensions/ink2canvas_lib/svg.py b/share/extensions/ink2canvas_lib/svg.py new file mode 100644 index 0000000..3d3fafb --- /dev/null +++ b/share/extensions/ink2canvas_lib/svg.py @@ -0,0 +1,326 @@ +# coding=utf-8 +# +# Copyright (C) 2011 Karlisson Bezerra +# +# 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. +# +""" +Element parsing and context for ink2canvas extensions +""" + +from __future__ import unicode_literals +import math + +import inkex +from inkex.localization import inkex_gettext as _ + + +# pylint: disable=missing-function-docstring, missing-class-docstring +# pylint: disable=too-few-public-methods + + +class Element: + """Base Element""" + + def __init__(self, node): + self.node = node + + def attr(self, val): + """Get attribute""" + try: + attr = float(self.node.get(val)) + except (ValueError, TypeError, AttributeError): + attr = self.node.get(val) + return attr + + +class GradientDef(Element): + def __init__(self, node, stops): + super().__init__(node) + self.stops = stops + + +class LinearGradientDef(GradientDef): + def get_data(self): + # pylint: disable=unused-variable + x1 = self.attr("x1") + y1 = self.attr("y1") + x2 = self.attr("x2") + y2 = self.attr("y2") + # self.create_linear_gradient(href, x1, y1, x2, y2) + + def draw(self): + pass + + +class RadialGradientDef(GradientDef): + def get_data(self): + # pylint: disable=unused-variable + cx = self.attr("cx") + cy = self.attr("cy") + r = self.attr("r") + # self.create_radial_gradient(href, cx, cy, r, cx, cy, r) + + def draw(self): + pass + + +class AbstractShape(Element): + def __init__(self, command, node, ctx): + super().__init__(node) + self.command = command + self.ctx = ctx + self.gradient = None + + def get_data(self): # pylint: disable=no-self-use + return None + + def get_style(self): + return self.node.specified_style() + + def set_style(self, style): + """Translates style properties names into method calls""" + self.ctx.style = style + for key in style: + method = "set_" + "_".join(key.split("-")) + if hasattr(self.ctx, method) and style[key] != "none": + getattr(self.ctx, method)(style[key]) + # saves style to compare in next iteration + if ( + hasattr(self.ctx, "style_cache") + and "opacity" not in style + and self.ctx.style_cache("opacity") != style("opacity") + ): + self.ctx.set_opacity( + style("opacity") + ) # opacity is kept in memory, need to reset + self.ctx.style_cache = style + + def has_transform(self): + return bool(self.attr("transform")) + + def get_transform(self): + return self.node.transform.to_hexad() + + def has_gradient(self): + style = self.get_style() + fill = style("fill") + return fill is not None and isinstance(fill, inkex.Gradient) + + def get_gradient_href(self): + style = self.get_style() + return style("fill").get_id() + + def has_clip(self): + return bool(self.attr("clip-path")) + + def start(self, gradient): + self.gradient = gradient + self.ctx.write("\n// #%s" % self.attr("id")) + if self.has_transform() or self.has_clip(): + self.ctx.save() + + def draw(self): + data = self.get_data() # pylint: disable=assignment-from-none + style = self.get_style() + self.ctx.begin_path() + if self.has_transform(): + trans_matrix = self.get_transform() + self.ctx.transform(*trans_matrix) # unpacks argument list + if self.has_gradient(): + self.gradient.draw() + self.set_style(style) + # unpacks "data" in parameters to given method + getattr(self.ctx, self.command)(*data) + self.ctx.finish_path() + + def end(self): + if self.has_transform() or self.has_clip(): + self.ctx.restore() + + +class G(AbstractShape): # pylint: disable=invalid-name + def draw(self): + # get layer label, if exists + if self.has_transform(): + trans_matrix = self.get_transform() + self.ctx.transform(*trans_matrix) + + +class Rect(AbstractShape): + def get_data(self): + x = self.attr("x") + y = self.attr("y") + width = self.attr("width") + height = self.attr("height") + rx = self.attr("rx") or 0 + ry = self.attr("ry") or 0 + return x, y, width, height, rx, ry + + +class Circle(AbstractShape): + def __init__(self, command, node, ctx): + AbstractShape.__init__(self, command, node, ctx) + self.command = "arc" + + def get_data(self): + + cx = self.attr("cx") + cy = self.attr("cy") + r = self.attr("r") + return cx, cy, r, 0, math.pi * 2, True + + +class Ellipse(AbstractShape): + def get_data(self): + cx = self.attr("cx") + cy = self.attr("cy") + rx = self.attr("rx") + ry = self.attr("ry") + return cx, cy, rx, ry + + def draw(self): + cx, cy, rx, ry = self.get_data() + style = self.get_style() + self.ctx.begin_path() + if self.has_transform(): + trans_matrix = self.get_transform() + self.ctx.transform(*trans_matrix) # unpacks argument list + self.set_style(style) + + kappa = 4 * ((math.sqrt(2) - 1) / 3) + self.ctx.move_to(cx, cy - ry) + self.ctx.bezier_curve_to( + cx + (kappa * rx), cy - ry, cx + rx, cy - (kappa * ry), cx + rx, cy + ) + self.ctx.bezier_curve_to( + cx + rx, cy + (kappa * ry), cx + (kappa * rx), cy + ry, cx, cy + ry + ) + self.ctx.bezier_curve_to( + cx - (kappa * rx), cy + ry, cx - rx, cy + (kappa * ry), cx - rx, cy + ) + self.ctx.bezier_curve_to( + cx - rx, cy - (kappa * ry), cx - (kappa * rx), cy - ry, cx, cy - ry + ) + self.ctx.finish_path() + + +class Path(AbstractShape): + def __init__(self, command, node, ctx): + AbstractShape.__init__(self, command, node, ctx) + self.current_position = 0, 0 + + def path_move_to(self, data): + self.ctx.move_to(data[0], data[1]) + self.current_position = data[0], data[1] + + def path_line_to(self, data): + self.ctx.line_to(data[0], data[1]) + self.current_position = data[0], data[1] + + def path_curve_to(self, data): + x1, y1, x2, y2 = data[0], data[1], data[2], data[3] + x, y = data[4], data[5] + self.ctx.bezier_curve_to(x1, y1, x2, y2, x, y) + self.current_position = x, y + + def path_close(self, data): # pylint: disable=unused-argument + self.ctx.close_path() + + def draw(self): + """Gets the node type and calls the given method""" + style = self.get_style() + self.ctx.begin_path() + if self.has_transform(): + trans_matrix = self.get_transform() + self.ctx.transform(*trans_matrix) # unpacks argument list + self.set_style(style) + + # Draws path commands + path_command = { + "M": self.path_move_to, + "L": self.path_line_to, + "C": self.path_curve_to, + "Z": self.path_close, + } + # Make sure we only have Lines and curves (no arcs etc) + for comm, data in self.node.path.to_superpath().to_path().to_arrays(): + if comm in path_command: + path_command[comm](data) + + self.ctx.finish_path() + + +class Line(Path): + def get_data(self): + x1 = self.attr("x1") + y1 = self.attr("y1") + x2 = self.attr("x2") + y2 = self.attr("y2") + return ("M", (x1, y1)), ("L", (x2, y2)) + + +class Polygon(Path): + def get_data(self): + points = self.attr("points").strip().split(" ") + points = map(lambda x: x.split(","), points) + comm = [] + for point in points: # creating path command similar + point = list(map(float, point)) + comm.append(["L", point]) + comm[0][0] = "M" # first command must be a 'M' => moveTo + return comm + + +class Polyline(Polygon): + pass + + +class Text(AbstractShape): + def text_helper(self, tspan): + if tspan is not None: + return tspan.text + for ts_cur in tspan: + return ts_cur.text + self.text_helper(ts_cur) + ts_cur.tail + + def set_text_style(self, style): + keys = ("font-style", "font-weight", "font-size", "font-family") + text = [] + for key in keys: + if key in style: + text.append(style[key]) + self.ctx.set_font(" ".join(text)) + + def get_data(self): + x = self.attr("x") + y = self.attr("y") + return x, y + + def draw(self): + for tspan in self.node: + if isinstance(tspan, inkex.TextPath): + raise ValueError(_("TextPath elements are not supported")) + style = self.get_style() + if self.has_transform(): + trans_matrix = self.get_transform() + self.ctx.transform(*trans_matrix) # unpacks argument list + self.set_style(style) + self.set_text_style(style) + + for tspan in self.node: + text = self.text_helper(tspan) + cur_x = float(tspan.get("x").split()[0]) + cur_y = float(tspan.get("y").split()[0]) + self.ctx.fill_text(text, cur_x, cur_y) diff --git a/share/extensions/inkex/__init__.py b/share/extensions/inkex/__init__.py new file mode 100644 index 0000000..4e0748c --- /dev/null +++ b/share/extensions/inkex/__init__.py @@ -0,0 +1,32 @@ +# coding=utf-8 +""" +This describes the core API for the inkex core modules. + +This provides the basis from which you can develop your inkscape extension. +""" + +# pylint: disable=wildcard-import +import sys + +from .extensions import * +from .utils import AbortExtension, DependencyError, Boolean, errormsg +from .styles import * +from .paths import Path, CubicSuperPath # Path commands are not exported +from .colors import * +from .transforms import * +from .elements import * + +# legacy proxies +from .deprecated import Effect +from .deprecated import localize +from .deprecated import debug + +# legacy functions +from .deprecated import are_near_relative +from .deprecated import unittouu + +MIN_VERSION = (3, 6) +if sys.version_info < MIN_VERSION: + sys.exit("Inkscape extensions require Python 3.6 or greater.") + +__version__ = "1.2.0" # Version number for inkex; may differ from Inkscape version. diff --git a/share/extensions/inkex/base.py b/share/extensions/inkex/base.py new file mode 100644 index 0000000..63f9218 --- /dev/null +++ b/share/extensions/inkex/base.py @@ -0,0 +1,537 @@ +# coding=utf-8 +# +# Copyright (c) 2018 - Martin Owens +# +# 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. +# +""" +The ultimate base functionality for every Inkscape extension. +""" + +import os +import re +import sys +import copy + +from typing import ( + Dict, + List, + Tuple, + Type, + Optional, + Callable, + Any, + Union, + IO, + TYPE_CHECKING, + cast, +) + +from argparse import ArgumentParser, Namespace +from lxml import etree + +from .interfaces.IElement import IBaseElement, ISVGDocumentElement +from .utils import filename_arg, AbortExtension, ABORT_STATUS, errormsg, do_nothing +from .elements._parser import load_svg +from .elements._utils import NSS +from .localization import localize + +stdout = sys.stdout.buffer # type: ignore + + +class InkscapeExtension: + """ + The base class extension, provides argument parsing and basic + variable handling features. + """ + + multi_inx = False # Set to true if this class is used by multiple inx files. + extra_nss = {} # type: Dict[str, str] + + def __init__(self): + # type: () -> None + NSS.update(self.extra_nss) + self.file_io = None # type: Optional[IO] + self.options = Namespace() + self.document = None # type: Union[None, bytes, str, etree.element] + self.arg_parser = ArgumentParser(description=self.__doc__) + + self.arg_parser.add_argument( + "input_file", + nargs="?", + metavar="INPUT_FILE", + type=filename_arg, + help="Filename of the input file (default is stdin)", + default=None, + ) + + self.arg_parser.add_argument( + "--output", + type=str, + default=None, + help="Optional output filename for saving the result (default is stdout).", + ) + + self.add_arguments(self.arg_parser) + + localize() + + def add_arguments(self, pars): + # type: (ArgumentParser) -> None + """Add any extra arguments to your extension handle, use: + + def add_arguments(self, pars): + pars.add_argument("--num-cool-things", type=int, default=3) + pars.add_argument("--pos-in-doc", type=str, default="doobry") + """ + # No extra arguments by default so super is not required + + def parse_arguments(self, args): + # type: (List[str]) -> None + """Parse the given arguments and set 'self.options'""" + self.options = self.arg_parser.parse_args(args) + + def arg_method(self, prefix="method"): + # type: (str) -> Callable[[str], Callable[[Any], Any]] + """Used by add_argument to match a tab selection with an object method + + pars.add_argument("--tab", type=self.arg_method(), default="foo") + ... + self.options.tab(arguments) + ... + .. code-block:: python + .. def method_foo(self, arguments): + .. # do something + """ + + def _inner(value): + name = f"""{prefix}_{value.strip('"').lower()}""".replace("-", "_") + try: + return getattr(self, name) + except AttributeError as error: + if name.startswith("_"): + return do_nothing + raise AbortExtension(f"Can not find method {name}") from error + + return _inner + + @staticmethod + def arg_number_ranges(): + + """Parses a number descriptor. e.g: + ``1,2,4-5,7,9-`` is parsed to ``1, 2, 4, 5, 7, 9, 10, ..., lastvalue`` + + .. versionadded:: 1.2 + + Usage: + + .. code-block:: python + + # in add_arguments() + pars.add_argument("--pages", type=self.arg_number_ranges(), default=1-) + # later on, pages is then a list of ints + pages = self.options.pages(lastvalue) + + """ + + def _inner(value): + def method(pages, lastvalue, startvalue=1): + # replace ranges, such as -3, 10- with startvalue,2,3,10..lastvalue + pages = re.sub( + r"(\d+|)\s?-\s?(\d+|)", + lambda m: ",".join( + map( + str, + range( + int(m.group(1) or startvalue), + int(m.group(2) or lastvalue) + 1, + ), + ) + ) + if not (m.group(1) or m.group(2)) == "" + else "", + pages, + ) + + pages = map(int, re.findall(r"(\d+)", pages)) + pages = tuple({i for i in pages if i <= lastvalue}) + return pages + + return lambda lastvalue, startvalue=1: method( + value, lastvalue, startvalue=startvalue + ) + + return _inner + + @staticmethod + def arg_class(options: List[Type]) -> Callable[[str], Any]: + """Used by add_argument to match an option with a class + + Types to choose from are given by the options list + + .. versionadded:: 1.2 + + Usage: + + .. code-block:: python + + pars.add_argument("--class", type=self.arg_class([ClassA, ClassB]), + default="ClassA") + """ + + def _inner(value: str): + name = value.strip('"') + for i in options: + if name == i.__name__: + return i + raise AbortExtension(f"Can not find class {name}") + + return _inner + + def debug(self, msg): + # type: (str) -> None + """Write a debug message""" + errormsg(f"DEBUG<{type(self).__name__}> {msg}\n") + + @staticmethod + def msg(msg): + # type: (str) -> None + """Write a non-error message""" + errormsg(msg) + + def run(self, args=None, output=stdout): + # type: (Optional[List[str]], Union[str, IO]) -> None + """Main entrypoint for any Inkscape Extension""" + try: + if args is None: + args = sys.argv[1:] + + self.parse_arguments(args) + if self.options.input_file is None: + self.options.input_file = sys.stdin + elif "DOCUMENT_PATH" not in os.environ: + os.environ["DOCUMENT_PATH"] = self.options.input_file + + if self.options.output is None: + self.options.output = output + + self.load_raw() + self.save_raw(self.effect()) + except AbortExtension as err: + errormsg(str(err)) + sys.exit(ABORT_STATUS) + finally: + self.clean_up() + + def load_raw(self): + # type: () -> None + """Load the input stream or filename, save everything to self""" + if isinstance(self.options.input_file, str): + # pylint: disable=consider-using-with + self.file_io = open(self.options.input_file, "rb") + document = self.load(self.file_io) + else: + document = self.load(self.options.input_file) + self.document = document + + def save_raw(self, ret): + # type: (Any) -> None + """Save to the output stream, use everything from self""" + if self.has_changed(ret): + if isinstance(self.options.output, str): + with open(self.options.output, "wb") as stream: + self.save(stream) + else: + if sys.platform == "win32" and not "PYTEST_CURRENT_TEST" in os.environ: + # When calling an extension from within Inkscape on Windows, + # Python thinks that the output stream is seekable + # (https://gitlab.com/inkscape/inkscape/-/issues/3273) + self.options.output.seekable = lambda self: False + + def seek_replacement(offset: int, whence: int = 0): + raise AttributeError( + "We can't seek in the stream passed by Inkscape on Windows" + ) + + def tell_replacement(): + raise AttributeError( + "We can't tell in the stream passed by Inkscape on Windows" + ) + + # Some libraries (e.g. ZipFile) don't query seekable, but check for an error + # on seek + self.options.output.seek = seek_replacement + self.options.output.tell = tell_replacement + self.save(self.options.output) + + def load(self, stream): + # type: (IO) -> str + """Takes the input stream and creates a document for parsing""" + raise NotImplementedError(f"No input handle for {self.name}") + + def save(self, stream): + # type: (IO) -> None + """Save the given document to the output file""" + raise NotImplementedError(f"No output handle for {self.name}") + + def effect(self): + # type: () -> Any + """Apply some effects on the document or local context""" + raise NotImplementedError(f"No effect handle for {self.name}") + + def has_changed(self, ret): # pylint: disable=no-self-use + # type: (Any) -> bool + """Return true if the output should be saved""" + return ret is not False + + def clean_up(self): + # type: () -> None + """Clean up any open handles and other items""" + if self.file_io is not None: + self.file_io.close() + + @classmethod + def svg_path(cls, default=None): + # type: (Optional[str]) -> Optional[str] + """ + Return the folder the svg is contained in. + Returns None if there is no file. + + .. versionchanged:: 1.1 + A default path can be given which is returned in case no path to the + SVG file can be determined. + """ + path = cls.document_path() + if path: + return os.path.dirname(path) + if default: + return default + return path # Return None or '' for context + + @classmethod + def ext_path(cls): + # type: () -> str + """Return the folder the extension script is in""" + return os.path.dirname(sys.modules[cls.__module__].__file__ or "") + + @classmethod + def get_resource(cls, name, abort_on_fail=True): + # type: (str, bool) -> str + """Return the full filename of the resource in the extension's dir + + .. versionadded:: 1.1""" + filename = cls.absolute_href(name, cwd=cls.ext_path()) + if abort_on_fail and not os.path.isfile(filename): + raise AbortExtension(f"Could not find resource file: {filename}") + return filename + + @classmethod + def document_path(cls): + # type: () -> Optional[str] + """Returns the saved location of the document + + * Normal return is a string containing the saved location + * Empty string means the document was never saved + * 'None' means this version of Inkscape doesn't support DOCUMENT_PATH + + DO NOT READ OR WRITE TO THE DOCUMENT FILENAME! + + * Inkscape may have not written the latest changes, leaving you reading old + data. + * Inkscape will not respect anything you write to the file, causing data loss. + + .. versionadded:: 1.1 + """ + return os.environ.get("DOCUMENT_PATH", None) + + @classmethod + def absolute_href(cls, filename, default="~/", cwd=None): + # type: (str, str, Optional[str]) -> str + """ + Process the filename such that it's turned into an absolute filename + with the working directory being the directory of the loaded svg. + + User's home folder is also resolved. So '~/a.png` will be `/home/bob/a.png` + + Default is a fallback working directory to use if the svg's filename is not + available. + + .. versionchanged:: 1.1 + If you set default to None, then the user will be given errors if + there's no working directory available from Inkscape. + """ + filename = os.path.expanduser(filename) + if not os.path.isabs(filename): + filename = os.path.expanduser(filename) + if not os.path.isabs(filename): + if cwd is None: + cwd = cls.svg_path(default) + if cwd is None: + raise AbortExtension( + "Can not use relative path, Inkscape isn't telling us the " + "current working directory." + ) + if cwd == "": + raise AbortExtension( + "The SVG must be saved before you can use relative paths." + ) + filename = os.path.join(cwd, filename) + return os.path.realpath(os.path.expanduser(filename)) + + @property + def name(self): + # type: () -> str + """Return a fixed name for this extension""" + return type(self).__name__ + + +if TYPE_CHECKING: + _Base = InkscapeExtension +else: + _Base = object + + +class TempDirMixin(_Base): # pylint: disable=abstract-method + """ + Provide a temporary directory for extensions to stash files. + """ + + dir_suffix = "" + dir_prefix = "inktmp" + + def __init__(self, *args, **kwargs): + self.tempdir = None + super().__init__(*args, **kwargs) + + def load_raw(self): + # type: () -> None + """Create the temporary directory""" + # pylint: disable=import-outside-toplevel + from tempfile import TemporaryDirectory + + # Need to hold a reference to the Directory object or else it might get GC'd + self._tempdir = TemporaryDirectory( # pylint: disable=consider-using-with + prefix=self.dir_prefix, suffix=self.dir_suffix + ) + self.tempdir = os.path.realpath(self._tempdir.name) + super().load_raw() + + def clean_up(self): + # type: () -> None + """Delete the temporary directory""" + self.tempdir = None + self._tempdir.cleanup() + super().clean_up() + + +class SvgInputMixin(_Base): # pylint: disable=too-few-public-methods, abstract-method + """ + Expects the file input to be an svg document and will parse it. + """ + + # Select all objects if none are selected + select_all: Tuple[Type[IBaseElement], ...] = () + + def __init__(self): + super().__init__() + + self.arg_parser.add_argument( + "--id", + action="append", + type=str, + dest="ids", + default=[], + help="id attribute of object to manipulate", + ) + + self.arg_parser.add_argument( + "--selected-nodes", + action="append", + type=str, + dest="selected_nodes", + default=[], + help="id:subpath:position of selected nodes, if any", + ) + + def load(self, stream): + # type: (IO) -> etree + """Load the stream as an svg xml etree and make a backup""" + document = load_svg(stream) + self.original_document = copy.deepcopy(document) + self.svg: ISVGDocumentElement = document.getroot() + self.svg.selection.set(*self.options.ids) + if not self.svg.selection and self.select_all: + self.svg.selection = self.svg.descendants().filter(*self.select_all) + return document + + +class SvgOutputMixin(_Base): # pylint: disable=too-few-public-methods, abstract-method + """ + Expects the output document to be an svg document and will write an etree xml. + + A template can be specified to kick off the svg document building process. + """ + + template = """ + """ + + @classmethod + def get_template(cls, **kwargs): + """ + Opens a template svg document for building, the kwargs + MUST include all the replacement values in the template, the + default template has 'width' and 'height' of the document. + """ + kwargs.setdefault("unit", "") + return load_svg(str(cls.template.format(**kwargs))) + + def save(self, stream): + # type: (IO) -> None + """Save the svg document to the given stream""" + if isinstance(self.document, (bytes, str)): + document = self.document + elif "Element" in type(self.document).__name__: + # isinstance can't be used here because etree is broken + doc = cast(etree, self.document) + document = doc.getroot().tostring() + else: + raise ValueError( + f"Unknown type of document: {type(self.document).__name__} can not" + + "save." + ) + + try: + stream.write(document) + except TypeError: + # we hope that this happens only when document needs to be encoded + stream.write(document.encode("utf-8")) # type: ignore + + +class SvgThroughMixin(SvgInputMixin, SvgOutputMixin): # pylint: disable=abstract-method + """ + Combine the input and output svg document handling (usually for effects). + """ + + def has_changed(self, ret): # pylint: disable=unused-argument + # type: (Any) -> bool + """Return true if the svg document has changed""" + original = etree.tostring(self.original_document) + result = etree.tostring(self.document) + return original != result diff --git a/share/extensions/inkex/bezier.py b/share/extensions/inkex/bezier.py new file mode 100644 index 0000000..976fdab --- /dev/null +++ b/share/extensions/inkex/bezier.py @@ -0,0 +1,488 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Nick Drobchenko, nick@cnc-club.ru +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +# pylint: disable=invalid-name,too-many-locals +# +""" +Bezier calculations +""" + +import cmath +import math + +import numpy + +from .transforms import DirectedLineSegment +from .localization import inkex_gettext as _ + +# bez = ((bx0,by0),(bx1,by1),(bx2,by2),(bx3,by3)) + + +def pointdistance(point_a, point_b): + """The straight line distance between two points""" + return math.sqrt( + ((point_b[0] - point_a[0]) ** 2) + ((point_b[1] - point_a[1]) ** 2) + ) + + +def between_point(point_a, point_b, time=0.5): + """Returns the point between point a and point b""" + return point_a[0] + time * (point_b[0] - point_a[0]), point_a[1] + time * ( + point_b[1] - point_a[1] + ) + + +def percent_point(point_a, point_b, percent=50.0): + """Returns between_point but takes percent instead of 0.0-1.0""" + return between_point(point_a, point_b, percent / 100.0) + + +def root_wrapper(root_a, root_b, root_c, root_d): + """Get the Cubic function, moic formular of roots, simple root""" + if root_a: + # Monics formula, see + # http://en.wikipedia.org/wiki/Cubic_function#Monic_formula_of_roots + mono_a, mono_b, mono_c = (root_b / root_a, root_c / root_a, root_d / root_a) + m = 2.0 * mono_a**3 - 9.0 * mono_a * mono_b + 27.0 * mono_c + k = mono_a**2 - 3.0 * mono_b + n = m**2 - 4.0 * k**3 + w1 = -0.5 + 0.5 * cmath.sqrt(-3.0) + w2 = -0.5 - 0.5 * cmath.sqrt(-3.0) + if n < 0: + m1 = pow(complex((m + cmath.sqrt(n)) / 2), 1.0 / 3) + n1 = pow(complex((m - cmath.sqrt(n)) / 2), 1.0 / 3) + else: + if m + math.sqrt(n) < 0: + m1 = -pow(-(m + math.sqrt(n)) / 2, 1.0 / 3) + else: + m1 = pow((m + math.sqrt(n)) / 2, 1.0 / 3) + if m - math.sqrt(n) < 0: + n1 = -pow(-(m - math.sqrt(n)) / 2, 1.0 / 3) + else: + n1 = pow((m - math.sqrt(n)) / 2, 1.0 / 3) + return ( + -1.0 / 3 * (mono_a + m1 + n1), + -1.0 / 3 * (mono_a + w1 * m1 + w2 * n1), + -1.0 / 3 * (mono_a + w2 * m1 + w1 * n1), + ) + if root_b: + det = root_c**2.0 - 4.0 * root_b * root_d + if det: + return ( + (-root_c + cmath.sqrt(det)) / (2.0 * root_b), + (-root_c - cmath.sqrt(det)) / (2.0 * root_b), + ) + return (-root_c / (2.0 * root_b),) + if root_c: + return (1.0 * (-root_d / root_c),) + return () + + +def bezlenapprx(sp1, sp2): + """Return the aproximate length between two beziers""" + return ( + pointdistance(sp1[1], sp1[2]) + + pointdistance(sp1[2], sp2[0]) + + pointdistance(sp2[0], sp2[1]) + ) + + +def cspbezsplit(sp1, sp2, time=0.5): + """Split a cubic bezier at the time period""" + m1 = tpoint(sp1[1], sp1[2], time) + m2 = tpoint(sp1[2], sp2[0], time) + m3 = tpoint(sp2[0], sp2[1], time) + m4 = tpoint(m1, m2, time) + m5 = tpoint(m2, m3, time) + m = tpoint(m4, m5, time) + return [[sp1[0][:], sp1[1][:], m1], [m4, m, m5], [m3, sp2[1][:], sp2[2][:]]] + + +def cspbezsplitatlength(sp1, sp2, length=0.5, tolerance=0.001): + """Split a cubic bezier at length""" + bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]) + time = beziertatlength(bez, length, tolerance) + return cspbezsplit(sp1, sp2, time) + + +def cspseglength(sp1, sp2, tolerance=0.001): + """Get cubic bezier segment length""" + bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]) + return bezierlength(bez, tolerance) + + +def csplength(csp): + """Get cubic bezier length""" + total = 0 + lengths = [] + for sp in csp: + lengths.append([]) + for i in range(1, len(sp)): + l = cspseglength(sp[i - 1], sp[i]) + lengths[-1].append(l) + total += l + return lengths, total + + +def bezierparameterize(bez): + """Return the bezier parameter size + Converts the bezier parametrisation from the default form + P(t) = (1-t)³ P_1 + 3(1-t)²t P_2 + 3(1-t)t² P_3 + t³ x_4 + to the a form which can be differentiated more easily + P(t) = a t³ + b t² + c t + P0 + + Args: + bez (List[Tuple[float, float]]): the Bezier curve. The elements of the list the + coordinates of the points (in this order): Start point, Start control point, + End control point, End point. + + Returns: + Tuple[float, float, float, float, float, float, float, float]: + the values ax, ay, bx, by, cx, cy, x0, y0 + """ + ((bx0, by0), (bx1, by1), (bx2, by2), (bx3, by3)) = bez + # parametric bezier + x0 = bx0 + y0 = by0 + cx = 3 * (bx1 - x0) + bx = 3 * (bx2 - bx1) - cx + ax = bx3 - x0 - cx - bx + cy = 3 * (by1 - y0) + by = 3 * (by2 - by1) - cy + ay = by3 - y0 - cy - by + + return ax, ay, bx, by, cx, cy, x0, y0 + + +def linebezierintersect(arg_a, bez): + """Where a line and bezier intersect""" + ((lx1, ly1), (lx2, ly2)) = arg_a + # parametric line + dd = lx1 + cc = lx2 - lx1 + bb = ly1 + aa = ly2 - ly1 + + if aa: + coef1 = cc / aa + coef2 = 1 + else: + coef1 = 1 + coef2 = aa / cc + + ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize(bez) + # cubic intersection coefficients + a = coef1 * ay - coef2 * ax + b = coef1 * by - coef2 * bx + c = coef1 * cy - coef2 * cx + d = coef1 * (y0 - bb) - coef2 * (x0 - dd) + + roots = root_wrapper(a, b, c, d) + retval = [] + for i in roots: + if isinstance(i, complex) and i.imag == 0: + i = i.real + if not isinstance(i, complex) and 0 <= i <= 1: + retval.append(bezierpointatt(bez, i)) + return retval + + +def bezierpointatt(bez, t): + """Get coords at the given time point along a bezier curve""" + ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize(bez) + x = ax * (t**3) + bx * (t**2) + cx * t + x0 + y = ay * (t**3) + by * (t**2) + cy * t + y0 + return x, y + + +def bezierslopeatt(bez, t): + """Get slope at the given time point along a bezier curve + The slope is computed as (dx, dy) where dx = df_x(t)/dt and dy = df_y(t)/dt. + Note that for lines P1=P2 and P3=P4, so the slope at the end points is dx=dy=0 + (slope not defined). + + Args: + bez (List[Tuple[float, float]]): the Bezier curve. The elements of the list the + coordinates of the points (in this order): Start point, Start control point, + End control point, End point. + t (float): time in the interval [0, 1] + + Returns: + Tuple[float, float]: x and y increment + """ + ax, ay, bx, by, cx, cy, _, _ = bezierparameterize(bez) + dx = 3 * ax * (t**2) + 2 * bx * t + cx + dy = 3 * ay * (t**2) + 2 * by * t + cy + return dx, dy + + +def beziertatslope(bez, d): + """Reverse; get time from slope along a bezier curve""" + ax, ay, bx, by, cx, cy, _, _ = bezierparameterize(bez) + (dy, dx) = d + # quadratic coefficients of slope formula + if dx: + slope = 1.0 * (dy / dx) + a = 3 * ay - 3 * ax * slope + b = 2 * by - 2 * bx * slope + c = cy - cx * slope + elif dy: + slope = 1.0 * (dx / dy) + a = 3 * ax - 3 * ay * slope + b = 2 * bx - 2 * by * slope + c = cx - cy * slope + else: + return [] + + roots = root_wrapper(0, a, b, c) + retval = [] + for i in roots: + if isinstance(i, complex) and i.imag == 0: + i = i.real + if not isinstance(i, complex) and 0 <= i <= 1: + retval.append(i) + return retval + + +def tpoint(p1, p2, t): + """Linearly interpolate between p1 and p2. + + t = 0.0 returns p1, t = 1.0 returns p2. + + :return: Interpolated point + :rtype: tuple + + :param p1: First point as sequence of two floats + :param p2: Second point as sequence of two floats + :param t: Number between 0.0 and 1.0 + :type t: float + """ + x1, y1 = p1 + x2, y2 = p2 + return x1 + t * (x2 - x1), y1 + t * (y2 - y1) + + +def beziersplitatt(bez, t): + """Split bezier at given time""" + ((bx0, by0), (bx1, by1), (bx2, by2), (bx3, by3)) = bez + m1 = tpoint((bx0, by0), (bx1, by1), t) + m2 = tpoint((bx1, by1), (bx2, by2), t) + m3 = tpoint((bx2, by2), (bx3, by3), t) + m4 = tpoint(m1, m2, t) + m5 = tpoint(m2, m3, t) + m = tpoint(m4, m5, t) + + return ((bx0, by0), m1, m4, m), (m, m5, m3, (bx3, by3)) + + +def addifclose(bez, l, error=0.001): + """Gravesen, Add if the line is closed, in-place addition to array l""" + box = 0 + for i in range(1, 4): + box += pointdistance(bez[i - 1], bez[i]) + chord = pointdistance(bez[0], bez[3]) + if (box - chord) > error: + first, second = beziersplitatt(bez, 0.5) + addifclose(first, l, error) + addifclose(second, l, error) + else: + l[0] += (box / 2.0) + (chord / 2.0) + + +# balfax, balfbx, balfcx, balfay, balfby, balfcy = 0, 0, 0, 0, 0, 0 + + +def balf(t, args): + """Bezier Arc Length Function""" + ax, bx, cx, ay, by, cy = args + retval = (ax * (t**2) + bx * t + cx) ** 2 + (ay * (t**2) + by * t + cy) ** 2 + return math.sqrt(retval) + + +def simpson(start, end, maxiter, tolerance, bezier_args): + """Calculate the length of a bezier curve using Simpson's algorithm: + http://steve.hollasch.net/cgindex/curves/cbezarclen.html + + Args: + start (int): Start time (between 0 and 1) + end (int): End time (between start time and 1) + maxiter (int): Maximum number of iterations. If not a power of 2, the algorithm + will behave like the value is set to the next power of 2. + tolerance (float): maximum error ratio + bezier_args (list): arguments as computed by bezierparametrize() + + Returns: + float: the appoximate length of the bezier curve + """ + + n = 2 + multiplier = (end - start) / 6.0 + endsum = balf(start, bezier_args) + balf(end, bezier_args) + interval = (end - start) / 2.0 + asum = 0.0 + bsum = balf(start + interval, bezier_args) + est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum)) + est0 = 2.0 * est1 + # print(multiplier, endsum, interval, asum, bsum, est1, est0) + while n < maxiter and abs(est1 - est0) > tolerance: + n *= 2 + multiplier /= 2.0 + interval /= 2.0 + asum += bsum + bsum = 0.0 + est0 = est1 + for i in range(1, n, 2): + bsum += balf(start + (i * interval), bezier_args) + est1 = multiplier * (endsum + (2.0 * asum) + (4.0 * bsum)) + # print(multiplier, endsum, interval, asum, bsum, est1, est0) + return est1 + + +def bezierlength(bez, tolerance=0.001, time=1.0): + """Get length of bezier curve""" + ax, ay, bx, by, cx, cy, _, _ = bezierparameterize(bez) + return simpson(0.0, time, 4096, tolerance, [3 * ax, 2 * bx, cx, 3 * ay, 2 * by, cy]) + + +def beziertatlength(bez, l=0.5, tolerance=0.001): + """Get bezier curve time at the length specified""" + curlen = bezierlength(bez, tolerance, 1.0) + time = 1.0 + tdiv = time + targetlen = l * curlen + diff = curlen - targetlen + while abs(diff) > tolerance: + tdiv /= 2.0 + if diff < 0: + time += tdiv + else: + time -= tdiv + curlen = bezierlength(bez, tolerance, time) + diff = curlen - targetlen + return time + + +def maxdist(bez): + """Get maximum distance within bezier curve""" + seg = DirectedLineSegment(bez[0], bez[3]) + return max(seg.distance_to_point(*bez[1]), seg.distance_to_point(*bez[2])) + + +def cspsubdiv(csp, flat): + """Sub-divide cubic sub-paths""" + for sp in csp: + subdiv(sp, flat) + + +def subdiv(sp, flat, i=1): + """sub divide bezier curve""" + while i < len(sp): + p0 = sp[i - 1][1] + p1 = sp[i - 1][2] + p2 = sp[i][0] + p3 = sp[i][1] + + bez = (p0, p1, p2, p3) + mdist = maxdist(bez) + if mdist <= flat: + i += 1 + else: + one, two = beziersplitatt(bez, 0.5) + sp[i - 1][2] = one[1] + sp[i][0] = two[2] + p = [one[2], one[3], two[1]] + sp[i:1] = [p] + + +def csparea(csp): + """Get area in cubic sub-path""" + MAT_AREA = numpy.array( + [[0, 2, 1, -3], [-2, 0, 1, 1], [-1, -1, 0, 2], [3, -1, -2, 0]] + ) + area = 0.0 + for sp in csp: + if len(sp) < 2: + continue + for x, coord in enumerate(sp): # calculate polygon area + area += 0.5 * sp[x - 1][1][0] * (coord[1][1] - sp[x - 2][1][1]) + for i in range(1, len(sp)): # add contribution from cubic Bezier + vec_x = numpy.array( + [sp[i - 1][1][0], sp[i - 1][2][0], sp[i][0][0], sp[i][1][0]] + ) + vec_y = numpy.array( + [sp[i - 1][1][1], sp[i - 1][2][1], sp[i][0][1], sp[i][1][1]] + ) + vex = numpy.matmul(vec_x, MAT_AREA) + area += 0.15 * numpy.matmul(vex, vec_y.T) + return -area + + +def cspcofm(csp): + """Get cubic sub-path coefficient""" + MAT_COFM_0 = numpy.array( + [[0, 35, 10, -45], [-35, 0, 12, 23], [-10, -12, 0, 22], [45, -23, -22, 0]] + ) + + MAT_COFM_1 = numpy.array( + [[0, 15, 3, -18], [-15, 0, 9, 6], [-3, -9, 0, 12], [18, -6, -12, 0]] + ) + + MAT_COFM_2 = numpy.array( + [[0, 12, 6, -18], [-12, 0, 9, 3], [-6, -9, 0, 15], [18, -3, -15, 0]] + ) + + MAT_COFM_3 = numpy.array( + [[0, 22, 23, -45], [-22, 0, 12, 10], [-23, -12, 0, 35], [45, -10, -35, 0]] + ) + area = csparea(csp) + xc = 0.0 + yc = 0.0 + if abs(area) < 1.0e-8: + raise ValueError(_("Area is zero, cannot calculate Center of Mass")) + for sp in csp: + for x, coord in enumerate(sp): # calculate polygon moment + xc += ( + sp[x - 1][1][1] + * (sp[x - 2][1][0] - coord[1][0]) + * (sp[x - 2][1][0] + sp[x - 1][1][0] + coord[1][0]) + / 6 + ) + yc += ( + sp[x - 1][1][0] + * (coord[1][1] - sp[x - 2][1][1]) + * (sp[x - 2][1][1] + sp[x - 1][1][1] + coord[1][1]) + / 6 + ) + for i in range(1, len(sp)): # add contribution from cubic Bezier + vec_x = numpy.array( + [sp[i - 1][1][0], sp[i - 1][2][0], sp[i][0][0], sp[i][1][0]] + ) + vec_y = numpy.array( + [sp[i - 1][1][1], sp[i - 1][2][1], sp[i][0][1], sp[i][1][1]] + ) + + def _mul(MAT, vec_x=vec_x, vec_y=vec_y): + return numpy.matmul(numpy.matmul(vec_x, MAT), vec_y.T) + + vec_t = numpy.array( + [_mul(MAT_COFM_0), _mul(MAT_COFM_1), _mul(MAT_COFM_2), _mul(MAT_COFM_3)] + ) + xc += numpy.matmul(vec_x, vec_t.T) / 280 + yc += numpy.matmul(vec_y, vec_t.T) / 280 + return -xc / area, -yc / area diff --git a/share/extensions/inkex/colors.py b/share/extensions/inkex/colors.py new file mode 100644 index 0000000..9a583ff --- /dev/null +++ b/share/extensions/inkex/colors.py @@ -0,0 +1,535 @@ +# coding=utf-8 +# +# Copyright (C) 2006 Jos Hirth, kaioa.com +# Copyright (C) 2007 Aaron C. Spike +# Copyright (C) 2009 Monash University +# +# 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. +# +""" +Basic color controls +""" + + +# All the names that get added to the inkex API itself. +__all__ = ("Color", "ColorError", "ColorIdError") + +SVG_COLOR = { + "aliceblue": "#f0f8ff", + "antiquewhite": "#faebd7", + "aqua": "#00ffff", + "aquamarine": "#7fffd4", + "azure": "#f0ffff", + "beige": "#f5f5dc", + "bisque": "#ffe4c4", + "black": "#000000", + "blanchedalmond": "#ffebcd", + "blue": "#0000ff", + "blueviolet": "#8a2be2", + "brown": "#a52a2a", + "burlywood": "#deb887", + "cadetblue": "#5f9ea0", + "chartreuse": "#7fff00", + "chocolate": "#d2691e", + "coral": "#ff7f50", + "cornflowerblue": "#6495ed", + "cornsilk": "#fff8dc", + "crimson": "#dc143c", + "cyan": "#00ffff", + "darkblue": "#00008b", + "darkcyan": "#008b8b", + "darkgoldenrod": "#b8860b", + "darkgray": "#a9a9a9", + "darkgreen": "#006400", + "darkgrey": "#a9a9a9", + "darkkhaki": "#bdb76b", + "darkmagenta": "#8b008b", + "darkolivegreen": "#556b2f", + "darkorange": "#ff8c00", + "darkorchid": "#9932cc", + "darkred": "#8b0000", + "darksalmon": "#e9967a", + "darkseagreen": "#8fbc8f", + "darkslateblue": "#483d8b", + "darkslategray": "#2f4f4f", + "darkslategrey": "#2f4f4f", + "darkturquoise": "#00ced1", + "darkviolet": "#9400d3", + "deeppink": "#ff1493", + "deepskyblue": "#00bfff", + "dimgray": "#696969", + "dimgrey": "#696969", + "dodgerblue": "#1e90ff", + "firebrick": "#b22222", + "floralwhite": "#fffaf0", + "forestgreen": "#228b22", + "fuchsia": "#ff00ff", + "gainsboro": "#dcdcdc", + "ghostwhite": "#f8f8ff", + "gold": "#ffd700", + "goldenrod": "#daa520", + "gray": "#808080", + "grey": "#808080", + "green": "#008000", + "greenyellow": "#adff2f", + "honeydew": "#f0fff0", + "hotpink": "#ff69b4", + "indianred": "#cd5c5c", + "indigo": "#4b0082", + "ivory": "#fffff0", + "khaki": "#f0e68c", + "lavender": "#e6e6fa", + "lavenderblush": "#fff0f5", + "lawngreen": "#7cfc00", + "lemonchiffon": "#fffacd", + "lightblue": "#add8e6", + "lightcoral": "#f08080", + "lightcyan": "#e0ffff", + "lightgoldenrodyellow": "#fafad2", + "lightgray": "#d3d3d3", + "lightgreen": "#90ee90", + "lightgrey": "#d3d3d3", + "lightpink": "#ffb6c1", + "lightsalmon": "#ffa07a", + "lightseagreen": "#20b2aa", + "lightskyblue": "#87cefa", + "lightslategray": "#778899", + "lightslategrey": "#778899", + "lightsteelblue": "#b0c4de", + "lightyellow": "#ffffe0", + "lime": "#00ff00", + "limegreen": "#32cd32", + "linen": "#faf0e6", + "magenta": "#ff00ff", + "maroon": "#800000", + "mediumaquamarine": "#66cdaa", + "mediumblue": "#0000cd", + "mediumorchid": "#ba55d3", + "mediumpurple": "#9370db", + "mediumseagreen": "#3cb371", + "mediumslateblue": "#7b68ee", + "mediumspringgreen": "#00fa9a", + "mediumturquoise": "#48d1cc", + "mediumvioletred": "#c71585", + "midnightblue": "#191970", + "mintcream": "#f5fffa", + "mistyrose": "#ffe4e1", + "moccasin": "#ffe4b5", + "navajowhite": "#ffdead", + "navy": "#000080", + "oldlace": "#fdf5e6", + "olive": "#808000", + "olivedrab": "#6b8e23", + "orange": "#ffa500", + "orangered": "#ff4500", + "orchid": "#da70d6", + "palegoldenrod": "#eee8aa", + "palegreen": "#98fb98", + "paleturquoise": "#afeeee", + "palevioletred": "#db7093", + "papayawhip": "#ffefd5", + "peachpuff": "#ffdab9", + "peru": "#cd853f", + "pink": "#ffc0cb", + "plum": "#dda0dd", + "powderblue": "#b0e0e6", + "purple": "#800080", + "rebeccapurple": "#663399", + "red": "#ff0000", + "rosybrown": "#bc8f8f", + "royalblue": "#4169e1", + "saddlebrown": "#8b4513", + "salmon": "#fa8072", + "sandybrown": "#f4a460", + "seagreen": "#2e8b57", + "seashell": "#fff5ee", + "sienna": "#a0522d", + "silver": "#c0c0c0", + "skyblue": "#87ceeb", + "slateblue": "#6a5acd", + "slategray": "#708090", + "slategrey": "#708090", + "snow": "#fffafa", + "springgreen": "#00ff7f", + "steelblue": "#4682b4", + "tan": "#d2b48c", + "teal": "#008080", + "thistle": "#d8bfd8", + "tomato": "#ff6347", + "turquoise": "#40e0d0", + "violet": "#ee82ee", + "wheat": "#f5deb3", + "white": "#ffffff", + "whitesmoke": "#f5f5f5", + "yellow": "#ffff00", + "yellowgreen": "#9acd32", + "none": None, +} +COLOR_SVG = {value: name for name, value in SVG_COLOR.items()} + + +def is_color(color): + """Determine if it is a color that we can use. If not, leave it unchanged.""" + try: + return bool(Color(color)) + except ColorError: + return False + + +def constrain(minim, value, maxim, channel): + """Returns the value so long as it is between min and max values""" + if channel == "h": # Hue + return value % maxim # Wrap around hue value + return min([maxim, max([minim, value])]) + + +class ColorError(KeyError): + """Specific color parsing error""" + + +class ColorIdError(ColorError): + """Special color error for gradient and color stop ids""" + + +class Color(list): + """An RGB array for the color + + Can be constructed from valid CSS color attributes, as well as + tuple/list + color space. Percentage values are supported. + + .. versionchanged:: 1.2 + Clarification with respect to values denoting unity: For RGB color channels, + "1.0", 1.0 and "100%" are treated as 255, while "1" and 1 are treated as 1. + + """ + + red = property( + lambda self: self.to_rgb()[0], lambda self, value: self._set(0, value) + ) + green = property( + lambda self: self.to_rgb()[1], lambda self, value: self._set(1, value) + ) + blue = property( + lambda self: self.to_rgb()[2], lambda self, value: self._set(2, value) + ) + alpha = property( + lambda self: self.to_rgba()[3], + lambda self, value: self._set(3, value, ("rgba",)), + ) + hue = property( + lambda self: self.to_hsl()[0], lambda self, value: self._set(0, value, ("hsl",)) + ) + saturation = property( + lambda self: self.to_hsl()[1], lambda self, value: self._set(1, value, ("hsl",)) + ) + lightness = property( + lambda self: self.to_hsl()[2], lambda self, value: self._set(2, value, ("hsl",)) + ) + + def __init__(self, color=None, space="rgb"): + super().__init__() + if isinstance(color, Color): + space, color = color.space, list(color) + + if isinstance(color, str): + # String from xml or css attributes + space, color = self.parse_str(color.strip()) + + if isinstance(color, int): + # Number from arg parser colour value + space, color = self.parse_int(color) + + # Empty list means 'none', or no color + if color is None: + color = [] + + if not isinstance(color, (list, tuple)): + raise ColorError("Not a known a color value") + + self.space = space + try: + for val in color: + self.append(val) + except ValueError as error: + raise ColorError("Bad color list") from error + + def __hash__(self): + """Allow colors to be hashable""" + return tuple(self.to_rgba()).__hash__() + + def _set(self, index, value, spaces=("rgb", "rgba")): + """Set the color value in place, limits setter to specific color space""" + # Named colors are just rgb, so dump name memory + if self.space == "named": + self.space = "rgb" + if not self.space in spaces: + if index == 3 and self.space == "rgb": + # Special, add alpha, don't convert back to rgb + self.space = "rgba" + self.append(constrain(0.0, float(value), 1.0, "a")) + return + # Set in other colour space and convert back and forth + target = self.to(spaces[0]) + target[index] = constrain(0, int(value), 255, spaces[0][index]) + self[:] = target.to(self.space) + return + self[index] = constrain(0, int(value), 255, spaces[0][index]) + + def append(self, val): + """Append a value to the local list""" + if len(self) == len(self.space): + raise ValueError("Can't add any more values to color.") + + if isinstance(val, str): + val = val.strip() + if val.endswith("%"): + val = float(val.strip("%")) / 100 + elif "." in val: + val = float(val) + else: + val = int(val) + + end_type = int + if len(self) == 3: # Alpha value + val = min([1.0, val]) + end_type = float + elif isinstance(val, float) and val <= 1.0: + val *= 255 + + if isinstance(val, (int, float)): + super().append(max(end_type(val), 0)) + + @staticmethod + def parse_str(color): + """Creates a rgb int array""" + # Handle pre-defined svg color values + if color and color.lower() in SVG_COLOR: + return "named", Color.parse_str(SVG_COLOR[color.lower()])[1] + + if color is None: + return "rgb", None + + if color.startswith("url("): + raise ColorIdError("Color references other element id, e.g. a gradient") + + # Next handle short colors (css: #abc -> #aabbcc) + if color.startswith("#"): + # Remove any icc or ilab directives + # FUTURE: We could use icc or ilab information + col = color.split(" ")[0] + if len(col) == 4: + # pylint: disable=consider-using-f-string + col = "#{1}{1}{2}{2}{3}{3}".format(*col) + + # Convert hex to integers + try: + return "rgb", (int(col[1:3], 16), int(col[3:5], 16), int(col[5:], 16)) + except ValueError as error: + raise ColorError(f"Bad RGB hex color value {col}") from error + + # Handle other css color values + elif "(" in color and ")" in color: + space, values = color.lower().strip().strip(")").split("(") + return space, values.split(",") + + try: + return Color.parse_int(int(color)) + except ValueError: + pass + + raise ColorError(f"Unknown color format: {color}") + + @staticmethod + def parse_int(color): + """Creates an rgb or rgba from a long int""" + space = "rgb" + color = [ + ((color >> 24) & 255), # red + ((color >> 16) & 255), # green + ((color >> 8) & 255), # blue + ((color & 255) / 255.0), # opacity + ] + if color[-1] == 1.0: + color.pop() + else: + space = "rgba" + return space, color + + def __str__(self): + """int array to #rrggbb""" + # pylint: disable=consider-using-f-string + if not self: + return "none" + if self.space == "named": + rgbhex = "#{0:02x}{1:02x}{2:02x}".format(*self) + if rgbhex in COLOR_SVG: + return COLOR_SVG[rgbhex] + self.space = "rgb" + if self.space == "rgb": + return "#{0:02x}{1:02x}{2:02x}".format(*self) + if self.space == "rgba": + if self[3] == 1.0: + return "rgb({:g}, {:g}, {:g})".format(*self[:3]) + return "rgba({:g}, {:g}, {:g}, {:g})".format(*self) + if self.space == "hsl": + return "hsl({0:g}, {1:g}, {2:g})".format(*self) + raise ColorError(f"Can't print colour space '{self.space}'") + + def __int__(self): + """int array to large integer""" + if not self: + return -1 + color = self.to_rgba() + return ( + (color[0] << 24) + + (color[1] << 16) + + (color[2] << 8) + + (int(color[3] * 255)) + ) + + def to(self, space): # pylint: disable=invalid-name + """Dynamic caller for to_hsl, to_rgb, etc""" + return getattr(self, "to_" + space)() + + def to_hsl(self): + """Turn this color into a Hue/Saturation/Lightness colour space""" + if not self and self.space in ("rgb", "named"): + return self.to_rgb().to_hsl() + if self.space == "hsl": + return self + if self.space in ("named"): + return self.to_rgb().to_hsl() + if self.space == "rgb": + return Color(rgb_to_hsl(*self.to_floats()), space="hsl") + raise ColorError(f"Unknown color conversion {self.space}->hsl") + + def to_rgb(self): + """Turn this color into a Red/Green/Blue colour space""" + if not self and self.space in ("rgb", "named"): + return Color([0, 0, 0]) + if self.space == "rgb": + return self + if self.space in ("rgba", "named"): + return Color(self[:3], space="rgb") + if self.space == "hsl": + return Color(hsl_to_rgb(*self.to_floats()), space="rgb") + raise ColorError(f"Unknown color conversion {self.space}->rgb") + + def to_rgba(self, alpha=1.0): + """Turn this color isn't an RGB with Alpha colour space""" + if self.space == "rgba": + return self + return Color(self.to_rgb() + [alpha], "rgba") + + def to_floats(self): + """Returns the colour values as percentage floats (0.0 - 1.0)""" + return [val / 255.0 for val in self] + + def to_named(self): + """Convert this color to a named color if possible""" + if not self: + return Color() + return Color(COLOR_SVG.get(str(self), str(self))) + + def interpolate(self, other, fraction): + """Interpolate two colours by the given fraction + + .. versionadded:: 1.1""" + from .tween import ColorInterpolator # pylint: disable=import-outside-toplevel + + return ColorInterpolator(self, other).interpolate(fraction) + + @staticmethod + def isnone(x): + """Checks if a given color is none + + .. versionadded:: 1.2""" + + if x is None or (isinstance(x, str) and x.lower() == "none"): + return True + return False + + @staticmethod + def iscolor(x, accept_none=False): + """Checks if a given value can be parsed as a color + + .. versionadded:: 1.2""" + if isinstance(x, str) and (accept_none or not (Color.isnone(x))): + try: + Color(x) + return True + except (ColorError): + pass + if isinstance(x, Color): + return True + return False + + +def rgb_to_hsl(red, green, blue): + """RGB to HSL colour conversion""" + rgb_max = max(red, green, blue) + rgb_min = min(red, green, blue) + delta = rgb_max - rgb_min + hsl = [0.0, 0.0, (rgb_max + rgb_min) / 2.0] + if delta != 0: + if hsl[2] <= 0.5: + hsl[1] = delta / (rgb_max + rgb_min) + else: + hsl[1] = delta / (2 - rgb_max - rgb_min) + + if red == rgb_max: + hsl[0] = (green - blue) / delta + elif green == rgb_max: + hsl[0] = 2.0 + (blue - red) / delta + elif blue == rgb_max: + hsl[0] = 4.0 + (red - green) / delta + + hsl[0] /= 6.0 + if hsl[0] < 0: + hsl[0] += 1 + if hsl[0] > 1: + hsl[0] -= 1 + return hsl + + +def hsl_to_rgb(hue, sat, light): + """HSL to RGB Color Conversion""" + if sat == 0: + return [light, light, light] # Gray + + if light < 0.5: + val2 = light * (1 + sat) + else: + val2 = light + sat - light * sat + val1 = 2 * light - val2 + return [ + _hue_to_rgb(val1, val2, hue * 6 + 2.0), + _hue_to_rgb(val1, val2, hue * 6), + _hue_to_rgb(val1, val2, hue * 6 - 2.0), + ] + + +def _hue_to_rgb(val1, val2, hue): + if hue < 0: + hue += 6.0 + if hue > 6: + hue -= 6.0 + if hue < 1: + return val1 + (val2 - val1) * hue + if hue < 3: + return val2 + if hue < 4: + return val1 + (val2 - val1) * (4 - hue) + return val1 diff --git a/share/extensions/inkex/command.py b/share/extensions/inkex/command.py new file mode 100644 index 0000000..8f9abbc --- /dev/null +++ b/share/extensions/inkex/command.py @@ -0,0 +1,309 @@ +# coding=utf-8 +# +# Copyright (C) 2019 Martin Owens +# +# 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, USA. +# +""" +This API provides methods for calling Inkscape to execute a given +Inkscape command. This may be needed for various compiling options +(e.g., png), running other extensions or performing other options only +available via the shell API. + +Best practice is to avoid using this API except when absolutely necessary, +since it is resource-intensive to invoke a new Inkscape instance. + +However, in any circumstance when it is necessary to call Inkscape, it +is strongly recommended that you do so through this API, rather than calling +it yourself, to take advantage of the security settings and testing functions. + +""" + +import os +import sys +from shutil import which as warlock + +from subprocess import Popen, PIPE +from tempfile import TemporaryDirectory +from typing import List +from lxml.etree import ElementTree + +from .elements import SvgDocumentElement + +INKSCAPE_EXECUTABLE_NAME = os.environ.get("INKSCAPE_COMMAND") +if INKSCAPE_EXECUTABLE_NAME is None: + if sys.platform == "win32": + # prefer inkscape.exe over inkscape.com which spawns a command window + INKSCAPE_EXECUTABLE_NAME = "inkscape.exe" + else: + INKSCAPE_EXECUTABLE_NAME = "inkscape" + + +class CommandNotFound(IOError): + """Command is not found""" + + +class ProgramRunError(ValueError): + """A specialized ValueError that is raised when a call to an external command fails. + It stores additional information about a failed call to an external program. + + If only the ``program`` parameter is given, it is interpreted as the error message. + Otherwise, the error message is compiled from all constructor parameters.""" + + program: str + """The absolute path to the called executable""" + + returncode: int + """Return code of the program call""" + + stderr: str + """stderr stream output of the call""" + + stdout: str + """stdout stream output of the call""" + + arguments: List + """Arguments of the call""" + + def __init__(self, program, returncode=None, stderr=None, stdout=None, args=None): + self.program = program + self.returncode = returncode + self.stderr = stderr + self.stdout = stdout + self.arguments = args + super().__init__(str(self)) + + def __str__(self): + if self.returncode is None: + return self.program + return ( + f"Return Code: {self.returncode}: {self.stderr}\n{self.stdout}" + f"\nargs: {self.args}" + ) + + +def which(program): + """ + Attempt different methods of trying to find if the program exists. + """ + if os.path.isabs(program) and os.path.isfile(program): + return program + # On Windows, shutil.which may give preference to .py files in the current directory + # (such as pdflatex.py), e.g. if .PY is in pathext, because the current directory is + # prepended to PATH. This can be suppressed by explicitly appending the current + # directory. + + try: + if sys.platform == "win32": + prog = warlock(program, path=os.environ["PATH"] + ";" + os.curdir) + if prog: + return prog + except ImportError: + pass + + try: + # Python3 only version of which + prog = warlock(program) + if prog: + return prog + except ImportError: + pass # python2 + + # There may be other methods for doing a `which` command for other + # operating systems; These should go here as they are discovered. + + raise CommandNotFound(f"Can not find the command: '{program}'") + + +def write_svg(svg, *filename): + """Writes an svg to the given filename""" + filename = os.path.join(*filename) + if os.path.isfile(filename): + return filename + with open(filename, "wb") as fhl: + if isinstance(svg, SvgDocumentElement): + svg = ElementTree(svg) + if hasattr(svg, "write"): + # XML document + svg.write(fhl) + elif isinstance(svg, bytes): + fhl.write(svg) + else: + raise ValueError("Not sure what type of SVG data this is.") + return filename + + +def to_arg(arg, oldie=False): + """Convert a python argument to a command line argument""" + if isinstance(arg, (tuple, list)): + (arg, val) = arg + arg = "-" + arg + if len(arg) > 2 and not oldie: + arg = "-" + arg + if val is True: + return arg + if val is False: + return None + return f"{arg}={str(val)}" + return str(arg) + + +def to_args(prog, *positionals, **arguments): + """Compile arguments and keyword arguments into a list of strings which Popen will + understand. + + :param prog: + Program executable prepended to the output. + :type first: ``str`` + + :Arguments: + * (``str``) -- String added as given + * (``tuple``) -- Ordered version of Kwyward Arguments, see below + + :Keyword Arguments: + * *name* (``str``) -- + Becomes ``--name="val"`` + * *name* (``bool``) -- + Becomes ``--name`` + * *name* (``list``) -- + Becomes ``--name="val1"`` ... + * *n* (``str``) -- + Becomes ``-n=val`` + * *n* (``bool``) -- + Becomes ``-n`` + + :return: Returns a list of compiled arguments ready for Popen. + :rtype: ``list[str]`` + """ + args = [prog] + oldie = arguments.pop("oldie", False) + for arg, value in arguments.items(): + arg = arg.replace("_", "-").strip() + + if isinstance(value, tuple): + value = list(value) + elif not isinstance(value, list): + value = [value] + + for val in value: + args.append(to_arg((arg, val), oldie)) + + args += [to_arg(pos, oldie) for pos in positionals if pos is not None] + # Filter out empty non-arguments + return [arg for arg in args if arg is not None] + + +def to_args_sorted(prog, *positionals, **arguments): + """same as :func:`to_args`, but keyword arguments are sorted beforehand + + .. versionadded:: 1.2""" + return to_args(prog, *positionals, **dict(sorted(arguments.items()))) + + +def _call(program, *args, **kwargs): + stdin = kwargs.pop("stdin", None) + if isinstance(stdin, str): + stdin = stdin.encode("utf-8") + inpipe = PIPE if stdin else None + + args = to_args(which(program), *args, **kwargs) + + kwargs = {} + if sys.platform == "win32": + kwargs["creationflags"] = 0x08000000 # create no console window + + with Popen( + args, + shell=False, # Never have shell=True + stdin=inpipe, # StdIn not used (yet) + stdout=PIPE, # Grab any output (return it) + stderr=PIPE, # Take all errors, just incase + **kwargs, + ) as process: + (stdout, stderr) = process.communicate(input=stdin) + if process.returncode == 0: + return stdout + raise ProgramRunError(program, process.returncode, stderr, stdout, args) + + +def call(program, *args, **kwargs): + """ + Generic caller to open any program and return its stdout:: + + stdout = call('executable', arg1, arg2, dash_dash_arg='foo', d=True, ...) + + Will raise :class:`ProgramRunError` if return code is not 0. + + Keyword arguments: + return_binary: Should stdout return raw bytes (default: False) + + .. versionadded:: 1.1 + stdin: The string or bytes containing the stdin (default: None) + + All other arguments converted using :func:`to_args` function. + """ + # We use this long input because it's less likely to conflict with --binary= + binary = kwargs.pop("return_binary", False) + stdout = _call(program, *args, **kwargs) + # Convert binary to string when we wish to have strings we do this here + # so the mock tests will also run the conversion (always returns bytes) + if not binary and isinstance(stdout, bytes): + return stdout.decode(sys.stdout.encoding or "utf-8") + return stdout + + +def inkscape(svg_file, *args, **kwargs): + """ + Call Inkscape with the given svg_file and the given arguments, see call() + """ + return call(INKSCAPE_EXECUTABLE_NAME, svg_file, *args, **kwargs) + + +def inkscape_command(svg, select=None, verbs=()): + """ + Executes a list of commands, a mixture of verbs, selects etc. + + inkscape_command('', ('verb', 'VerbName'), ...) + """ + with TemporaryDirectory(prefix="inkscape-command") as tmpdir: + svg_file = write_svg(svg, tmpdir, "input.svg") + select = ("select", select) if select else None + verbs += ("FileSave", "FileQuit") + inkscape(svg_file, select, batch_process=True, verb=";".join(verbs)) + with open(svg_file, "rb") as fhl: + return fhl.read() + + +def take_snapshot(svg, dirname, name="snapshot", ext="png", dpi=96, **kwargs): + """ + Take a snapshot of the given svg file. + + Resulting filename is yielded back, after generator finishes, the + file is deleted so you must deal with the file inside the for loop. + """ + svg_file = write_svg(svg, dirname, name + ".svg") + ext_file = os.path.join(dirname, name + "." + str(ext).lower()) + inkscape( + svg_file, export_dpi=dpi, export_filename=ext_file, export_type=ext, **kwargs + ) + return ext_file + + +def is_inkscape_available(): + """Return true if the Inkscape executable is available.""" + try: + return bool(which(INKSCAPE_EXECUTABLE_NAME)) + except CommandNotFound: + return False diff --git a/share/extensions/inkex/css.py b/share/extensions/inkex/css.py new file mode 100644 index 0000000..ebb9234 --- /dev/null +++ b/share/extensions/inkex/css.py @@ -0,0 +1,61 @@ +# coding=utf-8 +# +# Copyright (C) 2021 - Jonathan Neuhauser +# +# 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. +# + +"""Toplevel CSS utils that do not depend on other inkex functionality + +.. versionadded:: 1.2 + Previously a part of :py:mod:`inkex.styles`""" + + +import re +import cssselect + + +class ConditionalRule: + """A single css rule + + .. versionchanged:: 1.2 + The CSS rule is now processed using cssselect.""" + + step_to_xpath = [ + # namespace addition + (re.compile(r"(::|\/)([a-z]+)(?=\W)(?!-)"), r"\1svg:\2"), + ] + + def __init__(self, rule): + self.rule = rule.strip() + self.selector = cssselect.parse(self.rule)[0] + + def __str__(self): + return self.rule + + def to_xpath(self): + """Attempt to convert the rule into a simplified xpath""" + # the space in the end is needed for the negative lookbehind in the regex, will + # be removed on return + ret = cssselect.HTMLTranslator().selector_to_xpath(self.selector) + " " + for matcher, replacer in self.step_to_xpath: + ret = matcher.sub(replacer, ret) + return ret.strip() + + def get_specificity(self): + """gets the css specificity of this selector + + .. versionadded:: 1.2""" + return self.selector.specificity() diff --git a/share/extensions/inkex/deprecated-simple/README.rst b/share/extensions/inkex/deprecated-simple/README.rst new file mode 100644 index 0000000..df3e2dc --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/README.rst @@ -0,0 +1,4 @@ +# coding=utf-8This directory contains compatibility layers for all the `simple` modules, such as `simplepath` and `simplestyle` + +This directory IS NOT a module path, to denote this we are using a dash in the name and there is no '__init__.py' + diff --git a/share/extensions/inkex/deprecated-simple/bezmisc.py b/share/extensions/inkex/deprecated-simple/bezmisc.py new file mode 100644 index 0000000..92b63f6 --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/bezmisc.py @@ -0,0 +1,46 @@ +# coding=utf-8 +# +# 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. +# +# pylint: disable=invalid-name,unused-argument +"""Deprecated bezmisc API""" + +from inkex.deprecated import deprecate +from inkex import bezier + +bezierparameterize = deprecate(bezier.bezierparameterize) +linebezierintersect = deprecate(bezier.linebezierintersect) +bezierpointatt = deprecate(bezier.bezierpointatt) +bezierslopeatt = deprecate(bezier.bezierslopeatt) +beziertatslope = deprecate(bezier.beziertatslope) +tpoint = deprecate(bezier.tpoint) +beziersplitatt = deprecate(bezier.beziersplitatt) +pointdistance = deprecate(bezier.pointdistance) +Gravesen_addifclose = deprecate(bezier.addifclose) +balf = deprecate(bezier.balf) +bezierlengthSimpson = deprecate(bezier.bezierlength) +beziertatlength = deprecate(bezier.beziertatlength) +bezierlength = bezierlengthSimpson + + +@deprecate +def Simpson(func, a, b, n_limit, tolerance): + """bezier.simpson(a, b, n_limit, tolerance, balf_arguments)""" + raise AttributeError( + """Because bezmisc.Simpson used global variables, it's not possible to + call the replacement code automatically. In fact it's unlikely you were + using the code or functionality you think you were since it's a highly + broken way of writing python.""" + ) diff --git a/share/extensions/inkex/deprecated-simple/cspsubdiv.py b/share/extensions/inkex/deprecated-simple/cspsubdiv.py new file mode 100644 index 0000000..91b2237 --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/cspsubdiv.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# +# 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. +# +# pylint: disable=invalid-name +"""Deprecated cspsubdiv API""" + +from inkex.deprecated import deprecate +from inkex import bezier + +maxdist = deprecate(bezier.maxdist) +cspsubdiv = deprecate(bezier.cspsubdiv) +subdiv = deprecate(bezier.subdiv) diff --git a/share/extensions/inkex/deprecated-simple/cubicsuperpath.py b/share/extensions/inkex/deprecated-simple/cubicsuperpath.py new file mode 100644 index 0000000..cb6f124 --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/cubicsuperpath.py @@ -0,0 +1,52 @@ +# coding=utf-8 +# +# 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. +# +# pylint: disable=invalid-name +"""Deprecated cubic super path API""" + +from inkex.deprecated import deprecate +from inkex import paths + + +@deprecate +def ArcToPath(p1, params): + return paths.arc_to_path(p1, params) + + +@deprecate +def CubicSuperPath(simplepath): + return paths.Path(simplepath).to_superpath() + + +@deprecate +def unCubicSuperPath(csp): + return paths.CubicSuperPath(csp).to_path().to_arrays() + + +@deprecate +def parsePath(d): + return paths.CubicSuperPath(paths.Path(d)) + + +@deprecate +def formatPath(p): + return str(paths.Path(unCubicSuperPath(p))) + + +matprod = deprecate(paths.matprod) +rotmat = deprecate(paths.rotmat) +applymat = deprecate(paths.applymat) +norm = deprecate(paths.norm) diff --git a/share/extensions/inkex/deprecated-simple/ffgeom.py b/share/extensions/inkex/deprecated-simple/ffgeom.py new file mode 100644 index 0000000..2feb3bd --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/ffgeom.py @@ -0,0 +1,92 @@ +# coding=utf-8 +# +# 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. +# +# pylint: disable=invalid-name,missing-docstring +"""Deprecated ffgeom API""" + +from collections import namedtuple + +from inkex.deprecated import deprecate +from inkex.transforms import DirectedLineSegment as NewSeg + +try: + NaN = float("NaN") +except ValueError: + PosInf = 1e300000 + NaN = PosInf / PosInf + + +class Point(namedtuple("Point", "x y")): + __slots__ = () + + def __getitem__(self, key): + if isinstance(key, str): + key = "xy".index(key) + return super(Point, self).__getitem__(key) + + +class Segment(NewSeg): + @deprecate + def __init__(self, e0, e1): + """inkex.transforms.Segment(((x1, y1), (x2, y2)))""" + if isinstance(e0, dict): + e0 = (e0["x"], e0["y"]) + if isinstance(e1, dict): + e1 = (e1["x"], e1["y"]) + super(Segment, self).__init__((e0, e1)) + + def __getitem__(self, key): + if key: + return {"x": self.x.maximum, "y": self.y.maximum} + return {"x": self.x.minimum, "y": self.y.minimum} + + delta_x = lambda self: self.width + delta_y = lambda self: self.height + run = delta_x + rise = delta_y + + def distanceToPoint(self, p): + return self.distance_to_point(p["x"], p["y"]) + + def perpDistanceToPoint(self, p): + return self.perp_distance(p["x"], p["y"]) + + def angle(self): + return super(Segment, self).angle + + def length(self): + return super(Segment, self).length + + def pointAtLength(self, length): + return self.point_at_length(length) + + def pointAtRatio(self, ratio): + return self.point_at_ratio(ratio) + + def createParallel(self, p): + self.parallel(p["x"], p["y"]) + + +@deprecate +def intersectSegments(s1, s2): + """transforms.Segment(s1).intersect(s2)""" + return Point(*s1.intersect(s2)) + + +@deprecate +def dot(s1, s2): + """transforms.Segment(s1).dot(s2)""" + return s1.dot(s2) diff --git a/share/extensions/inkex/deprecated-simple/run_command.py b/share/extensions/inkex/deprecated-simple/run_command.py new file mode 100755 index 0000000..84f4a4b --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/run_command.py @@ -0,0 +1,79 @@ +# coding=utf-8 +# +# Copyright (C) 2008 Stephen Silver +# +# 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 +# +""" +Deprecated module for running SVG-generating commands in Inkscape extensions +""" +import os +import sys +import tempfile +from subprocess import Popen, PIPE + +from inkex.deprecated import deprecate + + +def run(command_format, prog_name): + """inkex.commands.call(...)""" + svgfile = tempfile.mktemp(".svg") + command = command_format % svgfile + msg = None + # ps2pdf may attempt to write to the current directory, which may not + # be writeable, so we switch to the temp directory first. + try: + os.chdir(tempfile.gettempdir()) + except IOError: + pass + + try: + proc = Popen(command, shell=True, stdout=PIPE, stderr=PIPE) + return_code = proc.wait() + out = proc.stdout.read() + err = proc.stderr.read() + + if msg is None: + if return_code: + msg = "{} failed:\n{}\n{}\n".format(prog_name, out, err) + elif err: + sys.stderr.write( + "{} executed but logged the following error:\n{}\n{}\n".format( + prog_name, out, err + ) + ) + except Exception as inst: + msg = "Error attempting to run {}: {}".format(prog_name, str(inst)) + + # If successful, copy the output file to stdout. + if msg is None: + if os.name == "nt": # make stdout work in binary on Windows + import msvcrt + + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + try: + with open(svgfile, "rb") as fhl: + sys.stdout.write(fhl.read().decode(sys.stdout.encoding)) + except IOError as inst: + msg = "Error reading temporary file: {}".format(str(inst)) + + try: + # Clean up. + os.remove(svgfile) + except (IOError, OSError): + pass + + # Output error message (if any) and exit. + return msg diff --git a/share/extensions/inkex/deprecated-simple/simplepath.py b/share/extensions/inkex/deprecated-simple/simplepath.py new file mode 100644 index 0000000..6eaaf3b --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/simplepath.py @@ -0,0 +1,68 @@ +# coding=utf-8 +# COPYRIGHT +# +# pylint: disable=invalid-name +# +""" +Depreicated simplepath replacements with documentation +""" + +import math +from inkex.deprecated import deprecate, DeprecatedDict +from inkex.transforms import Transform +from inkex.paths import Path + +pathdefs = DeprecatedDict( + { + "M": ["L", 2, [float, float], ["x", "y"]], + "L": ["L", 2, [float, float], ["x", "y"]], + "H": ["H", 1, [float], ["x"]], + "V": ["V", 1, [float], ["y"]], + "C": [ + "C", + 6, + [float, float, float, float, float, float], + ["x", "y", "x", "y", "x", "y"], + ], + "S": ["S", 4, [float, float, float, float], ["x", "y", "x", "y"]], + "Q": ["Q", 4, [float, float, float, float], ["x", "y", "x", "y"]], + "T": ["T", 2, [float, float], ["x", "y"]], + "A": [ + "A", + 7, + [float, float, float, int, int, float, float], + ["r", "r", "a", 0, "s", "x", "y"], + ], + "Z": ["L", 0, [], []], + } +) + + +@deprecate +def parsePath(d): + """element.path.to_arrays()""" + return Path(d).to_arrays() + + +@deprecate +def formatPath(a): + """str(element.path) or str(Path(array))""" + return str(Path(a)) + + +@deprecate +def translatePath(p, x, y): + """Path(array).translate(x, y)""" + p[:] = Path(p).translate(x, y).to_arrays() + + +@deprecate +def scalePath(p, x, y): + """Path(array).scale(x, y)""" + p[:] = Path(p).scale(x, y).to_arrays() + + +@deprecate +def rotatePath(p, a, cx=0, cy=0): + """Path(array).rotate(angle_degrees, (center_x, center_y))""" + p[:] = Path(p).rotate(math.degrees(a), (cx, cy)).to_arrays() diff --git a/share/extensions/inkex/deprecated-simple/simplestyle.py b/share/extensions/inkex/deprecated-simple/simplestyle.py new file mode 100644 index 0000000..cab6d9d --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/simplestyle.py @@ -0,0 +1,55 @@ +# coding=utf-8 +# COPYRIGHT +"""DOCSTRING""" + +import inkex +from inkex.colors import SVG_COLOR as svgcolors +from inkex.deprecated import deprecate + + +@deprecate +def parseStyle(s): + """dict(inkex.Style.parse_str(s))""" + return dict(inkex.Style.parse_str(s)) + + +@deprecate +def formatStyle(a): + """str(inkex.Style(a))""" + return str(inkex.Style(a)) + + +@deprecate +def isColor(c): + """inkex.colors.is_color(c)""" + return inkex.colors.is_color(c) + + +@deprecate +def parseColor(c): + """inkex.Color(c).to_rgb()""" + return tuple(inkex.Color(c).to_rgb()) + + +@deprecate +def formatColoria(a): + """str(inkex.Color(a))""" + return str(inkex.Color(a)) + + +@deprecate +def formatColorfa(a): + """str(inkex.Color(a))""" + return str(inkex.Color(a)) + + +@deprecate +def formatColor3i(r, g, b): + """str(inkex.Color((r, g, b)))""" + return str(inkex.Color((r, g, b))) + + +@deprecate +def formatColor3f(r, g, b): + """str(inkex.Color((r, g, b)))""" + return str(inkex.Color((r, g, b))) diff --git a/share/extensions/inkex/deprecated-simple/simpletransform.py b/share/extensions/inkex/deprecated-simple/simpletransform.py new file mode 100644 index 0000000..f408cd0 --- /dev/null +++ b/share/extensions/inkex/deprecated-simple/simpletransform.py @@ -0,0 +1,122 @@ +# coding=utf-8 +# +# pylint: disable=invalid-name +# +""" +Depreicated simpletransform replacements with documentation +""" + +import warnings + +from inkex.deprecated import deprecate +from inkex.transforms import Transform, BoundingBox, cubic_extrema +from inkex.paths import Path + +import inkex, cubicsuperpath + + +def _lists(mat): + return [list(row) for row in mat] + + +@deprecate +def parseTransform(transf, mat=None): + """Transform(str).matrix""" + t = Transform(transf) + if mat is not None: + t = Transform(mat) @ t + return _lists(t.matrix) + + +@deprecate +def formatTransform(mat): + """str(Transform(mat))""" + if len(mat) == 3: + warnings.warn("3x3 matrices not suported") + mat = mat[:2] + return str(Transform(mat)) + + +@deprecate +def invertTransform(mat): + """-Transform(mat)""" + return _lists((-Transform(mat)).matrix) + + +@deprecate +def composeTransform(mat1, mat2): + """Transform(M1) * Transform(M2)""" + return _lists((Transform(mat1) @ Transform(mat2)).matrix) + + +@deprecate +def composeParents(node, mat): + """elem.composed_transform() or elem.transform * Transform(mat)""" + return (node.transform @ Transform(mat)).matrix + + +@deprecate +def applyTransformToNode(mat, node): + """elem.transform = Transform(mat) * elem.transform""" + node.transform = Transform(mat) @ node.transform + + +@deprecate +def applyTransformToPoint(mat, pt): + """Transform(mat).apply_to_point(pt)""" + pt2 = Transform(mat).apply_to_point(pt) + # Apply in place as original method was modifying arrays in place. + # but don't do this in your code! This is not good code design. + pt[0] = pt2[0] + pt[1] = pt2[1] + + +@deprecate +def applyTransformToPath(mat, path): + """Path(path).transform(mat)""" + return Path(path).transform(Transform(mat)).to_arrays() + + +@deprecate +def fuseTransform(node): + """node.apply_transform()""" + return node.apply_transform() + + +@deprecate +def boxunion(b1, b2): + """list(BoundingBox(b1) + BoundingBox(b2))""" + bbox = BoundingBox(b1[:2], b1[2:]) + BoundingBox(b2[:2], b2[2:]) + return bbox.x.minimum, bbox.x.maximum, bbox.y.minimum, bbox.y.maximum + + +@deprecate +def roughBBox(path): + """list(Path(path)).bounding_box())""" + bbox = Path(path).bounding_box() + return bbox.x.minimum, bbox.x.maximum, bbox.y.minimum, bbox.y.maximum + + +@deprecate +def refinedBBox(path): + """list(Path(path)).bounding_box())""" + bbox = Path(path).bounding_box() + return bbox.x.minimum, bbox.x.maximum, bbox.y.minimum, bbox.y.maximum + + +@deprecate +def cubicExtrema(y0, y1, y2, y3): + """from inkex.transforms import cubic_extrema""" + return cubic_extrema(y0, y1, y2, y3) + + +@deprecate +def computeBBox(aList, mat=[[1, 0, 0], [0, 1, 0]]): + """sum([node.bounding_box() for node in aList])""" + return sum([node.bounding_box() for node in aList], None) + + +@deprecate +def computePointInNode(pt, node, mat=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): + """(-Transform(node.transform * mat)).apply_to_point(pt)""" + return (-Transform(node.transform * mat)).apply_to_point(pt) diff --git a/share/extensions/inkex/deprecated/__init__.py b/share/extensions/inkex/deprecated/__init__.py new file mode 100644 index 0000000..180a1c2 --- /dev/null +++ b/share/extensions/inkex/deprecated/__init__.py @@ -0,0 +1,3 @@ +from .main import * +from .meta import deprecate, _deprecated +from .deprecatedeffect import DeprecatedEffect, Effect diff --git a/share/extensions/inkex/deprecated/deprecatedeffect.py b/share/extensions/inkex/deprecated/deprecatedeffect.py new file mode 100644 index 0000000..ee13670 --- /dev/null +++ b/share/extensions/inkex/deprecated/deprecatedeffect.py @@ -0,0 +1,313 @@ +# coding=utf-8 +# +# Copyright (C) 2018 - Martin Owens +# +# 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. +# +""" +Deprecation functionality for the pre-1.0 Inkex main effect class. +""" +# +# We ignore a lot of pylint warnings here: +# +# pylint: disable=invalid-name,unused-argument,missing-docstring,too-many-public-methods +# + +import sys +import argparse +from argparse import ArgumentParser + +from .. import utils +from .. import base +from ..base import SvgThroughMixin, InkscapeExtension +from ..localization import inkex_gettext as _ +from .meta import _deprecated + + +class DeprecatedEffect: + """An Inkscape effect, takes SVG in and outputs SVG, providing a deprecated layer""" + + options = argparse.Namespace() + + def __init__(self): + super().__init__() + self._doc_ids = None + self._args = None + + # These are things we reference in the deprecated code, they are provided + # by the new effects code, but we want to keep this as a Mixin so these + # items will keep pylint happy and let use check our code as we write. + if not hasattr(self, "svg"): + from ..elements import SvgDocumentElement + + self.svg = SvgDocumentElement() + if not hasattr(self, "arg_parser"): + self.arg_parser = ArgumentParser() + if not hasattr(self, "run"): + self.run = self.affect + + @classmethod + def _deprecated( + cls, name, msg=_("{} is deprecated and should be removed"), stack=3 + ): + """Give the user a warning about their extension using a deprecated API""" + _deprecated( + msg.format("Effect." + name, cls=cls.__module__ + "." + cls.__name__), + stack=stack, + ) + + @property + def OptionParser(self): + self._deprecated( + "OptionParser", + _( + "{} or `optparse` has been deprecated and replaced with `argparser`. " + "You must change `self.OptionParser.add_option` to " + "`self.arg_parser.add_argument`; the arguments are similar." + ), + ) + return self + + def add_option(self, *args, **kw): + # Convert type string into type method as needed + if "type" in kw: + kw["type"] = { + "string": str, + "int": int, + "float": float, + "inkbool": utils.Boolean, + }.get(kw["type"]) + if kw.get("action", None) == "store": + # Default store action not required, removed. + kw.pop("action") + args = [arg for arg in args if arg != ""] + self.arg_parser.add_argument(*args, **kw) + + def effect(self): + self._deprecated( + "effect", + _( + "{} method is now a required method. It should " + "be created on {cls}, even if it does nothing." + ), + ) + + @property + def current_layer(self): + self._deprecated( + "current_layer", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.get_current_layer()` instead." + ), + ) + return self.svg.get_current_layer() + + @property + def view_center(self): + self._deprecated( + "view_center", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.get_center_position()` instead." + ), + ) + return self.svg.namedview.center + + @property + def selected(self): + self._deprecated( + "selected", + _( + "{} is now a dict in the SvgDocumentElement class. " + "Use `self.svg.selected`." + ), + ) + return {elem.get("id"): elem for elem in self.svg.selected} + + @property + def doc_ids(self): + self._deprecated( + "doc_ids", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.get_ids()` instead." + ), + ) + if self._doc_ids is None: + self._doc_ids = dict.fromkeys(self.svg.get_ids()) + return self._doc_ids + + def getdocids(self): + self._deprecated( + "getdocids", _("Use `self.svg.get_ids()` instead of {} and `doc_ids`.") + ) + self._doc_ids = None + self.svg.ids.clear() + + def getselected(self): + self._deprecated("getselected", _("{} has been removed")) + + def getElementById(self, eid): + self._deprecated( + "getElementById", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.getElementById(eid)` instead." + ), + ) + return self.svg.getElementById(eid) + + def xpathSingle(self, xpath): + self._deprecated( + "xpathSingle", + _( + "{} is now a new method in the SvgDocumentElement class. " + "Use `self.svg.getElement(path)` instead." + ), + ) + return self.svg.getElement(xpath) + + def getParentNode(self, node): + self._deprecated( + "getParentNode", + _("{} is no longer in use. Use the lxml `.getparent()` method instead."), + ) + return node.getparent() + + def getNamedView(self): + self._deprecated( + "getNamedView", + _( + "{} is now a property of the SvgDocumentElement class. " + "Use `self.svg.namedview` to access this element." + ), + ) + return self.svg.namedview + + def createGuide(self, posX, posY, angle): + from ..elements import Guide + + self._deprecated( + "createGuide", + _( + "{} is now a method of the namedview element object. " + "Use `self.svg.namedview.add(Guide().move_to(x, y, a))` instead." + ), + ) + return self.svg.namedview.add(Guide().move_to(posX, posY, angle)) + + def affect( + self, args=sys.argv[1:], output=True + ): # pylint: disable=dangerous-default-value + # We need a list as the default value to preserve backwards compatibility + self._deprecated( + "affect", _("{} is now `Effect.run()`. The `output` argument has changed.") + ) + self._args = args[-1:] + return self.run(args=args) + + @property + def args(self): + self._deprecated("args", _("self.args[-1] is now self.options.input_file.")) + return self._args + + @property + def svg_file(self): + self._deprecated("svg_file", _("self.svg_file is now self.options.input_file.")) + return self.options.input_file + + def save_raw(self, ret): + # Derived class may implement "output()" + # Attention: 'cubify.py' implements __getattr__ -> hasattr(self, 'output') + # returns True + if hasattr(self.__class__, "output"): + self._deprecated("output", "Use `save()` or `save_raw()` instead.", stack=5) + return getattr(self, "output")() + return base.InkscapeExtension.save_raw(self, ret) + + def uniqueId(self, old_id, make_new_id=True): + self._deprecated( + "uniqueId", + _( + "{} is now a method in the SvgDocumentElement class. " + " Use `self.svg.get_unique_id(old_id)` instead." + ), + ) + return self.svg.get_unique_id(old_id) + + def getDocumentWidth(self): + self._deprecated( + "getDocumentWidth", + _( + "{} is now a property of the SvgDocumentElement class. " + "Use `self.svg.width` instead." + ), + ) + return self.svg.get("width") + + def getDocumentHeight(self): + self._deprecated( + "getDocumentHeight", + _( + "{} is now a property of the SvgDocumentElement class. " + "Use `self.svg.height` instead." + ), + ) + return self.svg.get("height") + + def getDocumentUnit(self): + self._deprecated( + "getDocumentUnit", + _( + "{} is now a property of the SvgDocumentElement class. " + "Use `self.svg.unit` instead." + ), + ) + return self.svg.unit + + def unittouu(self, string): + self._deprecated( + "unittouu", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.unittouu(str)` instead." + ), + ) + return self.svg.unittouu(string) + + def uutounit(self, val, unit): + self._deprecated( + "uutounit", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.uutounit(value, unit)` instead." + ), + ) + return self.svg.uutounit(val, unit) + + def addDocumentUnit(self, value): + self._deprecated( + "addDocumentUnit", + _( + "{} is now a method in the SvgDocumentElement class. " + "Use `self.svg.add_unit(value)` instead." + ), + ) + return self.svg.add_unit(value) + + +class Effect(SvgThroughMixin, DeprecatedEffect, InkscapeExtension): + """An Inkscape effect, takes SVG in and outputs SVG""" diff --git a/share/extensions/inkex/deprecated/main.py b/share/extensions/inkex/deprecated/main.py new file mode 100644 index 0000000..a747bda --- /dev/null +++ b/share/extensions/inkex/deprecated/main.py @@ -0,0 +1,178 @@ +# coding=utf-8 +# +# Copyright (C) 2018 - Martin Owens +# +# 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. +# +""" +Provide some documentation to existing extensions about why they're failing. +""" +# +# We ignore a lot of pylint warnings here: +# +# pylint: disable=invalid-name,unused-argument,missing-docstring,too-many-public-methods +# + +import os +import sys +import warnings +import argparse + +from ..transforms import Transform +from .. import utils +from .. import units +from ..elements._base import BaseElement, ShapeElement +from ..elements._selected import ElementList +from .meta import deprecate, _deprecated + +warnings.simplefilter("default") +# To load each of the deprecated sub-modules (the ones without a namespace) +# we will add the directory to our pythonpath so older scripts can find them + +INKEX_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +SIMPLE_DIR = os.path.join(INKEX_DIR, "deprecated-simple") + +if os.path.isdir(SIMPLE_DIR): + sys.path.append(SIMPLE_DIR) + + +class DeprecatedDict(dict): + @deprecate + def __getitem__(self, key): + return super().__getitem__(key) + + @deprecate + def __iter__(self): + return super().__iter__() + + +# legacy inkex members + + +class lazyproxy: + """Proxy, use as decorator on a function with provides the wrapped object. + The decorated function is called when a member is accessed on the proxy. + """ + + def __init__(self, getwrapped): + """ + :param getwrapped: Callable which returns the wrapped object + """ + self._getwrapped = getwrapped + + def __getattr__(self, name): + return getattr(self._getwrapped(), name) + + def __call__(self, *args, **kwargs): + return self._getwrapped()(*args, **kwargs) + + +@lazyproxy +def localize(): + _deprecated("inkex.localize was moved to inkex.localization.localize.", stack=3) + from ..localization import localize as wrapped + + return wrapped + + +def are_near_relative(a, b, eps): + _deprecated( + "inkex.are_near_relative was moved to " "inkex.units.are_near_relative", stack=2 + ) + return units.are_near_relative(a, b, eps) + + +def debug(what): + _deprecated("inkex.debug was moved to inkex.utils.debug.", stack=2) + return utils.debug(what) + + +# legacy inkex members <= 0.48.x + + +def unittouu(string): + _deprecated( + "inkex.unittouu is now a method in the SvgDocumentElement class. " + "Use `self.svg.unittouu(str)` instead.", + stack=2, + ) + return units.convert_unit(string, "px") + + +# optparse.Values.ensure_value + + +def ensure_value(self, attr, value): + _deprecated("Effect().options.ensure_value was removed.", stack=2) + if getattr(self, attr, None) is None: + setattr(self, attr, value) + return getattr(self, attr) + + +argparse.Namespace.ensure_value = ensure_value # type: ignore + + +@deprecate +def zSort(inNode, idList): + """self.svg.get_z_selected()""" + sortedList = [] + theid = inNode.get("id") + if theid in idList: + sortedList.append(theid) + for child in inNode: + if len(sortedList) == len(idList): + break + sortedList += zSort(child, idList) + return sortedList + + +# This can't be handled as a mixin class because of circular importing. +def description(self, value): + """Use elem.desc = value""" + self.desc = value + + +BaseElement.description = deprecate(description, "1.1") + + +def composed_style(element: ShapeElement): + """Calculate the final styles applied to this element + This function has been deprecated in favor of BaseElement.specified_style()""" + return element.specified_style() + + +ShapeElement.composed_style = deprecate(composed_style, "1.2") + + +def paint_order(selection: ElementList): + """Use :func:`rendering_order`""" + return selection.rendering_order() + + +ElementList.paint_order = deprecate(paint_order, "1.2") # type: ignore + + +def transform_imul(self, matrix): + """Use @= operator instead""" + return self.__imatmul__(matrix) + + +def transform_mul(self, matrix): + """Use @ operator instead""" + return self.__matmul__(matrix) + + +Transform.__imul__ = deprecate(transform_imul, "1.2") # type: ignore +Transform.__mul__ = deprecate(transform_mul, "1.2") # type: ignore diff --git a/share/extensions/inkex/deprecated/meta.py b/share/extensions/inkex/deprecated/meta.py new file mode 100644 index 0000000..cebd93c --- /dev/null +++ b/share/extensions/inkex/deprecated/meta.py @@ -0,0 +1,109 @@ +# coding=utf-8 +# +# Copyright (C) 2018 - Martin Owens +# +# 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. +# +""" +Deprecation functionality which does not require imports from Inkex. +""" + +import os +import traceback +import warnings +from typing import Optional + +try: + DEPRECATION_LEVEL = int(os.environ.get("INKEX_DEPRECATION_LEVEL", 1)) +except ValueError: + DEPRECATION_LEVEL = 1 + + +def _deprecated(msg, stack=2, level=DEPRECATION_LEVEL): + """Internal method for raising a deprecation warning""" + if level > 1: + msg += " ; ".join(traceback.format_stack()) + if level: + warnings.warn(msg, category=DeprecationWarning, stacklevel=stack + 1) + + +def deprecate(func, version: Optional[str] = None): + r"""Function decorator for deprecation functions which have a one-liner + equivalent in the new API. The one-liner has to passed as a string + to the decorator. + + >>> @deprecate + >>> def someOldFunction(*args): + >>> '''Example replacement code someNewFunction('foo', ...)''' + >>> someNewFunction('foo', *args) + + Or if the args API is the same: + + >>> someOldFunction = deprecate(someNewFunction) + + """ + + def _inner(*args, **kwargs): + _deprecated(f"{func.__module__}.{func.__name__} -> {func.__doc__}", stack=2) + return func(*args, **kwargs) + + _inner.__name__ = func.__name__ + if func.__doc__: + if version is None: + _inner.__doc__ = "Deprecated -> " + func.__doc__ + else: + _inner.__doc__ = f"""{func.__doc__}\n\n.. deprecated:: {version}\n""" + return _inner + + +class DeprecatedSvgMixin: + """Mixin which adds deprecated API elements to the SvgDocumentElement""" + + @property + def selected(self): + """svg.selection""" + return self.selection + + @deprecate + def set_selected(self, *ids): + r"""svg.selection.set(\*ids)""" + return self.selection.set(*ids) + + @deprecate + def get_z_selected(self): + """svg.selection.rendering_order()""" + return self.selection.rendering_order() + + @deprecate + def get_selected(self, *types): + r"""svg.selection.filter(\*types).values()""" + return self.selection.filter(*types).values() + + @deprecate + def get_selected_or_all(self, *types): + """Set select_all = True in extension class""" + if not self.selection: + self.selection.set_all() + return self.selection.filter(*types) + + @deprecate + def get_selected_bbox(self): + """selection.bounding_box()""" + return self.selection.bounding_box() + + @deprecate + def get_first_selected(self, *types): + r"""selection.filter(\*types).first() or [0] if you'd like an error""" + return self.selection.filter(*types).first() diff --git a/share/extensions/inkex/elements/__init__.py b/share/extensions/inkex/elements/__init__.py new file mode 100644 index 0000000..021d47b --- /dev/null +++ b/share/extensions/inkex/elements/__init__.py @@ -0,0 +1,55 @@ +""" +Element based interface provides the bulk of features that allow you to +interact directly with the SVG xml interface. + +See the documentation for each of the elements for details on how it works. +""" + +from ._utils import addNS, NSS +from ._parser import SVG_PARSER, load_svg +from ._base import ShapeElement, BaseElement +from ._svg import SvgDocumentElement +from ._groups import Group, Layer, Anchor, Marker, ClipPath, Mask +from ._polygons import PathElement, Polyline, Polygon, Line, Rectangle, Circle, Ellipse +from ._text import ( + FlowRegion, + FlowRoot, + FlowPara, + FlowDiv, + FlowSpan, + TextElement, + TextPath, + Tspan, + SVGfont, + FontFace, + Glyph, + MissingGlyph, +) +from ._use import Symbol, Use +from ._meta import ( + Defs, + StyleElement, + Script, + Desc, + Title, + NamedView, + Guide, + Metadata, + ForeignObject, + Switch, + Grid, + Page, +) +from ._filters import ( + Filter, + Pattern, + Gradient, + LinearGradient, + RadialGradient, + PathEffect, + Stop, + MeshGradient, + MeshRow, + MeshPatch, +) +from ._image import Image diff --git a/share/extensions/inkex/elements/_base.py b/share/extensions/inkex/elements/_base.py new file mode 100644 index 0000000..492278e --- /dev/null +++ b/share/extensions/inkex/elements/_base.py @@ -0,0 +1,755 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Sergei Izmailov +# Thomas Holder +# +# 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. +# +# pylint: disable=arguments-differ +""" +Provide extra utility to each svg element type specific to its type. + +This is useful for having a common interface for each element which can +give path, transform, and property access easily. +""" +from __future__ import annotations + +from copy import deepcopy +from typing import Any, Tuple, Optional, overload, TypeVar, List +from lxml import etree + +from ..interfaces.IElement import IBaseElement, ISVGDocumentElement + +from ..base import SvgOutputMixin +from ..paths import Path +from ..styles import Style, Classes +from ..transforms import Transform, BoundingBox +from ..utils import FragmentError +from ..units import convert_unit, render_unit, parse_unit +from ._utils import ChildToProperty, NSS, addNS, removeNS, splitNS +from ..properties import BaseStyleValue, all_properties +from ._selected import ElementList +from ._parser import NodeBasedLookup, SVG_PARSER + +T = TypeVar("T", bound="BaseElement") # pylint: disable=invalid-name + + +class BaseElement(IBaseElement): + """Provide automatic namespaces to all calls""" + + # pylint: disable=too-many-public-methods + + def __init_subclass__(cls): + if cls.tag_name: + NodeBasedLookup.register_class(cls) + + @classmethod + def is_class_element( # pylint: disable=unused-argument + cls, elem: etree.Element + ) -> bool: + """Hook to do more restrictive check in addition to (ns,tag) match + + .. versionadded:: 1.2 + The function has been made public.""" + return True + + tag_name = "" + + @property + def TAG(self): # pylint: disable=invalid-name + """Return the tag_name without NS""" + if not self.tag_name: + return removeNS(super().tag)[-1] + return removeNS(self.tag_name)[-1] + + @classmethod + def new(cls, *children, **attrs): + """Create a new element, converting attrs values to strings.""" + obj = cls(*children) + obj.update(**attrs) + return obj + + NAMESPACE = property(lambda self: splitNS(self.tag_name)[0]) + """Get namespace of element""" + + PARSER = SVG_PARSER + """A reference to the :attr:`inkex.elements._parser.SVG_PARSER`""" + WRAPPED_ATTRS = ( + # (prop_name, [optional: attr_name], cls) + ("transform", Transform), + ("style", Style), + ("classes", "class", Classes), + ) # type: Tuple[Tuple[Any, ...], ...] + """A list of attributes that are automatically converted to objects.""" + + # We do this because python2 and python3 have different ways + # of combining two dictionaries that are incompatible. + # This allows us to update these with inheritance. + @property + def wrapped_attrs(self): + """Map attributes to property name and wrapper class""" + return {row[-2]: (row[0], row[-1]) for row in self.WRAPPED_ATTRS} + + @property + def wrapped_props(self): + """Map properties to attribute name and wrapper class""" + return {row[0]: (row[-2], row[-1]) for row in self.WRAPPED_ATTRS} + + typename = property(lambda self: type(self).__name__) + """Type name of the element""" + xml_path = property(lambda self: self.getroottree().getpath(self)) + """XPath representation of the element in its tree + + .. versionadded:: 1.1""" + desc = ChildToProperty("svg:desc", prepend=True) + """The element's long-form description (for accessibility purposes) + + .. versionadded:: 1.1""" + title = ChildToProperty("svg:title", prepend=True) + """The element's short-form description (for accessibility purposes) + + .. versionadded:: 1.1""" + + def __getattr__(self, name): + """Get the attribute, but load it if it is not available yet""" + if name in self.wrapped_props: + (attr, cls) = self.wrapped_props[name] + # The reason we do this here and not in _init is because lxml + # is inconsistant about when elements are initialised. + # So we make this a lazy property. + def _set_attr(new_item): + if new_item: + self.set(attr, str(new_item)) + else: + self.attrib.pop(attr, None) # pylint: disable=no-member + + # pylint: disable=no-member + value = cls(self.attrib.get(attr, None), callback=_set_attr) + if name == "style": + value.element = self + setattr(self, name, value) + return value + raise AttributeError(f"Can't find attribute {self.typename}.{name}") + + def __setattr__(self, name, value): + """Set the attribute, update it if needed""" + if name in self.wrapped_props: + (attr, cls) = self.wrapped_props[name] + # Don't call self.set or self.get (infinate loop) + if value: + if not isinstance(value, cls): + value = cls(value) + self.attrib[attr] = str(value) + else: + self.attrib.pop(attr, None) # pylint: disable=no-member + else: + super().__setattr__(name, value) + + def get(self, attr, default=None): + """Get element attribute named, with addNS support.""" + if attr in self.wrapped_attrs: + (prop, _) = self.wrapped_attrs[attr] + value = getattr(self, prop, None) + # We check the boolean nature of the value, because empty + # transformations and style attributes are equiv to not-existing + ret = str(value) if value else (default or None) + return ret + return super().get(addNS(attr), default) + + def set(self, attr, value): + """Set element attribute named, with addNS support""" + if attr in self.wrapped_attrs: + # Always keep the local wrapped class up to date. + (prop, cls) = self.wrapped_attrs[attr] + setattr(self, prop, cls(value)) + value = getattr(self, prop) + if not value: + return + if value is None: + self.attrib.pop(addNS(attr), None) # pylint: disable=no-member + else: + value = str(value) + super().set(addNS(attr), value) + + def update(self, **kwargs): + """ + Update element attributes using keyword arguments + + Note: double underscore is used as namespace separator, + i.e. "namespace__attr" argument name will be treated as "namespace:attr" + + :param kwargs: dict with name=value pairs + :return: self + """ + for name, value in kwargs.items(): + self.set(name, value) + return self + + def pop(self, attr, default=None): + """Delete/remove the element attribute named, with addNS support.""" + if attr in self.wrapped_attrs: + # Always keep the local wrapped class up to date. + (prop, cls) = self.wrapped_attrs[attr] + value = getattr(self, prop) + setattr(self, prop, cls(None)) + return value + return self.attrib.pop(addNS(attr), default) # pylint: disable=no-member + + @overload + def add( + self, child1: BaseElement, child2: BaseElement, *children: BaseElement + ) -> Tuple[BaseElement]: + ... + + @overload + def add(self, child: T) -> T: + ... + + def add(self, *children): + """ + Like append, but will do multiple children and will return + children or only child + """ + for child in children: + self.append(child) + return children if len(children) != 1 else children[0] + + def tostring(self): + """Return this element as it would appear in an svg document""" + # This kind of hack is pure maddness, but etree provides very little + # in the way of fragment printing, prefering to always output valid xml + + svg = SvgOutputMixin.get_template(width=0, height=0).getroot() + svg.append(self.copy()) + return svg.tostring().split(b">\n ", 1)[-1][:-6] + + def set_random_id( + self, + prefix: Optional[str] = None, + size: Optional[int] = None, + backlinks: bool = False, + blacklist: Optional[List[str]] = None, + ): + """Sets the id attribute if it is not already set. + + The id consists of a prefix and an appended random integer of length size. + Args: + prefix (str, optional): the prefix of the new ID. Defaults to the tag name. + size (Optional[int], optional): number of digits of the second part of the + id. If None, the length is chosen based on the amount of existing + objects. Defaults to None. + + .. versionchanged:: 1.2 + The default of this value has been changed from 4 to None. + backlinks (bool, optional): Whether to update the links in existing objects + that reference this element. Defaults to False. + blacklist (List[str], optional): An additional list of ids that are not + allowed to be used. This is useful when bulk inserting objects. + Defaults to None. + + .. versionadded:: 1.2 + """ + prefix = str(self) if prefix is None else prefix + self.set_id( + self.root.get_unique_id(prefix, size=size, blacklist=blacklist), + backlinks=backlinks, + ) + + def set_random_ids( + self, + prefix: Optional[str] = None, + levels: int = -1, + backlinks: bool = False, + blacklist: Optional[List[str]] = None, + ): + """Same as set_random_id, but will apply also to children + + The id consists of a prefix and an appended random integer of length size. + Args: + prefix (str, optional): the prefix of the new ID. Defaults to the tag name. + levels (int, optional): the depth of the tree traversion, if negative, no + limit is imposed. Defaults to -1. + backlinks (bool, optional): Whether to update the links in existing objects + that reference this element. Defaults to False. + blacklist (List[str], optional): An additional list of ids that are not + allowed to be used. This is useful when bulk inserting objects. + Defaults to None. + + .. versionadded:: 1.2 + """ + self.set_random_id(prefix=prefix, backlinks=backlinks, blacklist=blacklist) + if levels != 0: + for child in self: + if hasattr(child, "set_random_ids"): + child.set_random_ids( + prefix=prefix, levels=levels - 1, backlinks=backlinks + ) + + eid = property(lambda self: self.get_id()) + """Property to access the element's id; will set a new unique id if not set.""" + + def get_id(self, as_url=0) -> str: + """Get the id for the element, will set a new unique id if not set. + + as_url - If set to 1, returns #{id} as a string + If set to 2, returns url(#{id}) as a string + + Args: + as_url (int, optional): + - If set to 1, returns #{id} as a string + - If set to 2, returns url(#{id}) as a string. + + Defaults to 0. + + .. versionadded:: 1.1 + + Returns: + str: formatted id + """ + if "id" not in self.attrib: + self.set_random_id(self.TAG) + eid = self.get("id") + if as_url > 0: + eid = "#" + eid + if as_url > 1: + eid = f"url({eid})" + return eid + + def set_id(self, new_id, backlinks=False): + """Set the id and update backlinks to xlink and style urls if needed""" + old_id = self.get("id", None) + self.set("id", new_id) + if backlinks and old_id: + for elem in self.root.getElementsByHref(old_id): + elem.href = self + for attr in ["clip-path", "mask"]: + for elem in self.root.getElementsByHref(old_id, attribute=attr): + elem.set(attr, self.get_id(2)) + for elem in self.root.getElementsByStyleUrl(old_id): + elem.style.update_urls(old_id, new_id) + + @property + def root(self): + """Get the root document element from any element descendent""" + root, parent = self, self + while parent is not None: + root, parent = parent, parent.getparent() + + if not isinstance(root, ISVGDocumentElement): + raise FragmentError("Element fragment does not have a document root!") + return root + + def get_or_create(self, xpath, nodeclass=None, prepend=False): + """Get or create the given xpath, pre/append new node if not found. + + .. versionchanged:: 1.1 + The ``nodeclass`` attribute is optional; if not given, it is looked up + using :func:`~inkex.elements._parser.NodeBasedLookup.find_class`""" + node = self.findone(xpath) + if node is None: + if nodeclass is None: + nodeclass = NodeBasedLookup.find_class(xpath) + node = nodeclass() + if prepend: + self.insert(0, node) + else: + self.append(node) + return node + + def descendants(self): + """Walks the element tree and yields all elements, parent first + + .. versionchanged:: 1.1 + The ``*types`` attribute was removed + + """ + + return ElementList( + self.root, + [ + element + for element in self.iter() + if isinstance(element, (BaseElement, str)) + ], + ) + + def ancestors(self, elem=None, stop_at=()): + """ + Walk the parents and yield all the ancestor elements, parent first + + Args: + elem (BaseElement, optional): If provided, it will stop at the last common + ancestor. Defaults to None. + + .. versionadded:: 1.1 + + stop_at (tuple, optional): If provided, it will stop at the first parent + that is in this list. Defaults to (). + + .. versionadded:: 1.1 + + Returns: + ElementList: list of ancestors + """ + + return ElementList(self.root, self._ancestors(elem=elem, stop_at=stop_at)) + + def _ancestors(self, elem, stop_at): + if isinstance(elem, BaseElement): + stop_at = list(elem.ancestors()) + for parent in self.iterancestors(): + yield parent + if parent in stop_at: + break + + def backlinks(self, *types): + """Get elements which link back to this element, like ancestors but via + xlinks""" + if not types or isinstance(self, types): + yield self + my_id = self.get("id") + if my_id is not None: + elems = list(self.root.getElementsByHref(my_id)) + list( + self.root.getElementsByStyleUrl(my_id) + ) + for elem in elems: + if hasattr(elem, "backlinks"): + for child in elem.backlinks(*types): + yield child + + def xpath(self, pattern, namespaces=NSS): # pylint: disable=dangerous-default-value + """Wrap xpath call and add svg namespaces""" + return super().xpath(pattern, namespaces=namespaces) + + def findall( + self, pattern, namespaces=NSS + ): # pylint: disable=dangerous-default-value + """Wrap findall call and add svg namespaces""" + return super().findall(pattern, namespaces=namespaces) + + def findone(self, xpath): + """Gets a single element from the given xpath or returns None""" + el_list = self.xpath(xpath) + return el_list[0] if el_list else None + + def delete(self): + """Delete this node from it's parent node""" + if self.getparent() is not None: + self.getparent().remove(self) + + def remove_all(self, *types): + """Remove all children or child types + + .. versionadded:: 1.1""" + types = tuple(NodeBasedLookup.find_class(t) for t in types) + for child in self: + if not types or isinstance(child, types): + self.remove(child) + + def replace_with(self, elem): + """Replace this element with the given element""" + self.addnext(elem) + if not elem.get("id") and self.get("id"): + elem.set("id", self.get("id")) + if not elem.label and self.label: + elem.label = self.label + self.delete() + return elem + + def copy(self): + """Make a copy of the element and return it""" + elem = deepcopy(self) + elem.set("id", None) + return elem + + def duplicate(self): + """Like copy(), but the copy stays in the tree and sets a random id on the + duplicate. + + .. versionchanged:: 1.2 + A random id is also set on all the duplicate's descendants""" + elem = self.copy() + self.addnext(elem) + elem.set_random_ids() + return elem + + def __str__(self): + # We would do more here, but lxml is VERY unpleseant when it comes to + # namespaces, basically over printing details and providing no + # supression mechanisms to turn off xml's over engineering. + return str(self.tag).split("}", maxsplit=1)[-1] + + @property + def href(self): + """Returns the referred-to element if available + + .. versionchanged:: 1.1 + A setter for href was added.""" + ref = self.get("xlink:href") + if not ref: + return None + return self.root.getElementById(ref.strip("#")) + + @href.setter + def href(self, elem): + """Set the href object""" + if isinstance(elem, BaseElement): + elem = elem.get_id() + self.set("xlink:href", "#" + elem) + + @property + def label(self): + """Returns the inkscape label""" + return self.get("inkscape:label", None) + + @label.setter + def label(self, value): + """Sets the inkscape label""" + self.set("inkscape:label", str(value)) + + def is_sensitive(self): + """Return true if this element is sensitive in inkscape + + .. versionadded:: 1.1""" + return self.get("sodipodi:insensitive", None) != "true" + + def set_sensitive(self, sensitive=True): + """Set the sensitivity of the element/layer + + .. versionadded:: 1.1""" + # Sensitive requires None instead of 'false' + self.set("sodipodi:insensitive", ["true", None][sensitive]) + + @property + def unit(self): + """Return the unit being used by the owning document, cached + + .. versionadded:: 1.1""" + try: + return self.root.unit + except FragmentError: + return "px" # Don't cache. + + @staticmethod + def to_dimensional(value, to_unit="px"): + """Convert a value given in user units (px) the given unit type + + .. versionadded:: 1.2""" + return convert_unit(value, to_unit) + + @staticmethod + def to_dimensionless(value): + """Convert a length value into user units (px) + + .. versionadded:: 1.2""" + return convert_unit(value, "px") + + def uutounit(self, value, to_unit="px"): + """Convert a unit value to a given unit. If the value does not have a unit, + "Document" units are assumed. "Document units" are an Inkscape-specific concept. + For most use-cases, :func:`to_dimensional` is more appropriate. + + .. versionadded:: 1.1""" + return convert_unit(value, to_unit, default=self.unit) + + def unittouu(self, value): + """Convert a unit value into document units. "Document unit" is an + Inkscape-specific concept. For most use-cases, :func:`viewport_to_unit` (when + the size of an object given in viewport units is needed) or + :func:`to_dimensionless` (when the equivalent value without unit is needed) is + more appropriate. + + .. versionadded:: 1.1""" + return convert_unit(value, self.unit) + + def unit_to_viewport(self, value, unit="px"): + """Converts a length value to viewport units, as defined by the width/height + element on the root (i.e. applies the equivalent transform of the viewport) + + .. versionadded:: 1.2""" + return self.to_dimensional( + self.to_dimensionless(value) * self.root.equivalent_transform_scale, unit + ) + + def viewport_to_unit(self, value, unit="px"): + """Converts a length given on the viewport to the specified unit in the user + coordinate system + + .. versionadded:: 1.2""" + return self.to_dimensional( + self.to_dimensionless(value) / self.root.equivalent_transform_scale, unit + ) + + def add_unit(self, value): + """Add document unit when no unit is specified in the string. + + .. versionadded:: 1.1""" + return render_unit(value, self.unit) + + def cascaded_style(self): + """Returns the cascaded style of an element (all rules that apply the element + itself), based on the stylesheets, the presentation attributes and the inline + style using the respective specificity of the style. + + see https://www.w3.org/TR/CSS22/cascade.html#cascading-order + + .. versionadded:: 1.2 + + Returns: + Style: the cascaded style + + """ + return Style.cascaded_style(self) + + def specified_style(self): + """Returns the specified style of an element, i.e. the cascaded style + + inheritance, see https://www.w3.org/TR/CSS22/cascade.html#specified-value. + + Returns: + Style: the specified style + + .. versionadded:: 1.2 + """ + return Style.specified_style(self) + + def presentation_style(self): + """Return presentation attributes of an element as style + + .. versionadded:: 1.2""" + style = Style() + for key in self.keys(): + if key in all_properties and all_properties[key][2]: + style[key] = BaseStyleValue.factory( + declaration=key + ": " + self.attrib[key] + ) + return style + + def composed_transform(self, other=None): + """Calculate every transform down to the other element + if none specified the transform is to the root document element + """ + parent = self.getparent() + if parent is not None and isinstance(parent, BaseElement): + return parent.composed_transform() @ self.transform + return self.transform + + +NodeBasedLookup.default = BaseElement + + +class ShapeElement(BaseElement): + """Elements which have a visible representation on the canvas""" + + @property + def path(self): + """Gets the outline or path of the element, this may be a simple bounding box""" + return Path(self.get_path()) + + @path.setter + def path(self, path): + self.set_path(path) + + @property + def clip(self): + """Gets the clip path element (if any) + + .. versionadded:: 1.1""" + ref = self.get("clip-path") + if not ref: + return None + return self.root.getElementById(ref) + + @clip.setter + def clip(self, elem): + self.set("clip-path", elem.get_id(as_url=2)) + + def get_path(self) -> Path: + """Generate a path for this object which can inform the bounding box""" + raise NotImplementedError( + f"Path should be provided by svg elem {self.typename}." + ) + + def set_path(self, path): + """Set the path for this object (if possible)""" + raise AttributeError( + f"Path can not be set on this element: {self.typename} <- {path}." + ) + + def to_path_element(self): + """Replace this element with a path element""" + from ._polygons import PathElement + + elem = PathElement() + elem.path = self.path + elem.style = self.effective_style() + elem.transform = self.transform + return elem + + def effective_style(self): + """Without parent styles, what is the effective style is""" + return self.style + + def bounding_box(self, transform=None): + # type: (Optional[Transform]) -> Optional[BoundingBox] + """BoundingBox of the shape + + .. versionchanged:: 1.1 + result adjusted for element's clip path if applicable.""" + shape_box = self.shape_box(transform) + clip = self.clip + if clip is None or shape_box is None: + return shape_box + return shape_box & clip.bounding_box(Transform(transform) @ self.transform) + + def shape_box(self, transform=None): + # type: (Optional[Transform]) -> Optional[BoundingBox] + """BoundingBox of the unclipped shape + + .. versionadded:: 1.1 + Previous :func:`bounding_box` function, returning the bounding box + without computing the effect of a possible clip.""" + path = self.path.to_absolute() + if transform is True: + path = path.transform(self.composed_transform()) + else: + path = path.transform(self.transform) + if transform: # apply extra transformation + path = path.transform(transform) + return path.bounding_box() + + def is_visible(self): + """Returns false if the css says this object is invisible + + .. versionadded:: 1.1""" + if self.style.get("display", "") == "none": + return False + if not float(self.style.get("opacity", 1.0)): + return False + return True + + def get_line_height_uu(self): + """Returns the specified value of line-height, in user units + + .. versionadded:: 1.1""" + style = self.specified_style() + font_size = style("font-size") # already in uu + line_height = style("line-height") + parsed = parse_unit(line_height) + if parsed is None: + return font_size * 1.2 + if parsed[1] == "%": + return font_size * parsed[0] * 0.01 + return self.to_dimensionless(line_height) diff --git a/share/extensions/inkex/elements/_filters.py b/share/extensions/inkex/elements/_filters.py new file mode 100644 index 0000000..ce86507 --- /dev/null +++ b/share/extensions/inkex/elements/_filters.py @@ -0,0 +1,367 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Sergei Izmailov +# Thomas Holder +# +# 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. +# +# pylint: disable=arguments-differ +""" +Element interface for patterns, filters, gradients and path effects. +""" +from __future__ import annotations +from typing import List, Tuple, TYPE_CHECKING, Optional + +from lxml import etree + +from ..transforms import Transform +from ..utils import parse_percent + +from ..styles import Style + +from ._utils import addNS +from ._base import BaseElement + + +if TYPE_CHECKING: + from ._svg import SvgDocumentElement + + +class Filter(BaseElement): + """A filter (usually in defs)""" + + tag_name = "filter" + + def add_primitive(self, fe_type, **args): + """Create a filter primitive with the given arguments""" + elem = etree.SubElement(self, addNS(fe_type, "svg")) + elem.update(**args) + return elem + + class Primitive(BaseElement): + """Any filter primitive""" + + class Blend(Primitive): + """Blend Filter element""" + + tag_name = "feBlend" + + class ColorMatrix(Primitive): + """ColorMatrix Filter element""" + + tag_name = "feColorMatrix" + + class ComponentTransfer(Primitive): + """ComponentTransfer Filter element""" + + tag_name = "feComponentTransfer" + + class Composite(Primitive): + """Composite Filter element""" + + tag_name = "feComposite" + + class ConvolveMatrix(Primitive): + """ConvolveMatrix Filter element""" + + tag_name = "feConvolveMatrix" + + class DiffuseLighting(Primitive): + """DiffuseLightning Filter element""" + + tag_name = "feDiffuseLighting" + + class DisplacementMap(Primitive): + """Flood Filter element""" + + tag_name = "feDisplacementMap" + + class Flood(Primitive): + """DiffuseLightning Filter element""" + + tag_name = "feFlood" + + class GaussianBlur(Primitive): + """GaussianBlur Filter element""" + + tag_name = "feGaussianBlur" + + class Image(Primitive): + """Image Filter element""" + + tag_name = "feImage" + + class Merge(Primitive): + """Merge Filter element""" + + tag_name = "feMerge" + + class Morphology(Primitive): + """Morphology Filter element""" + + tag_name = "feMorphology" + + class Offset(Primitive): + """Offset Filter element""" + + tag_name = "feOffset" + + class SpecularLighting(Primitive): + """SpecularLighting Filter element""" + + tag_name = "feSpecularLighting" + + class Tile(Primitive): + """Tile Filter element""" + + tag_name = "feTile" + + class Turbulence(Primitive): + """Turbulence Filter element""" + + tag_name = "feTurbulence" + + +class Stop(BaseElement): + """Gradient stop + + .. versionadded:: 1.1""" + + tag_name = "stop" + + @property + def offset(self) -> float: + """The offset of the gradient stop""" + return self.get("offset") + + @offset.setter + def offset(self, number): + self.set("offset", number) + + def interpolate(self, other, fraction): + """Interpolate gradient stops""" + from ..tween import StopInterpolator + + return StopInterpolator(self, other).interpolate(fraction) + + +class Pattern(BaseElement): + """Pattern element which is used in the def to control repeating fills""" + + tag_name = "pattern" + WRAPPED_ATTRS = BaseElement.WRAPPED_ATTRS + (("patternTransform", Transform),) + + +class Gradient(BaseElement): + """A gradient instruction usually in the defs.""" + + WRAPPED_ATTRS = BaseElement.WRAPPED_ATTRS + (("gradientTransform", Transform),) + """Additional to the :attr:`~inkex.elements._base.BaseElement.WRAPPED_ATTRS` of + :class:`~inkex.elements._base.BaseElement`, ``gradientTransform`` is wrapped.""" + + orientation_attributes = () # type: Tuple[str, ...] + """ + .. versionadded:: 1.1 + """ + + @property + def stops(self): + """Return an ordered list of own or linked stop nodes + + .. versionadded:: 1.1""" + gradcolor = ( + self.href + if isinstance(self.href, (LinearGradient, RadialGradient)) + else self + ) + return sorted( + [child for child in gradcolor if isinstance(child, Stop)], + key=lambda x: parse_percent(x.offset), + ) + + @property + def stop_offsets(self): + # type: () -> List[float] + """Return a list of own or linked stop offsets + + .. versionadded:: 1.1""" + return [child.offset for child in self.stops] + + @property + def stop_styles(self): # type: () -> List[Style] + """Return a list of own or linked offset styles + + .. versionadded:: 1.1""" + return [child.style for child in self.stops] + + def remove_orientation(self): + """Remove all orientation attributes from this element + + .. versionadded:: 1.1""" + for attr in self.orientation_attributes: + self.pop(attr) + + def interpolate( + self, + other: LinearGradient, + fraction: float, + svg: Optional[SvgDocumentElement] = None, + ): + """Interpolate with another gradient. + + .. versionadded:: 1.1""" + from ..tween import GradientInterpolator + + return GradientInterpolator(self, other, svg).interpolate(fraction) + + def stops_and_orientation(self): + """Return a copy of all the stops in this gradient + + .. versionadded:: 1.1""" + stops = self.copy() + stops.remove_orientation() + orientation = self.copy() + orientation.remove_all(Stop) + return stops, orientation + + +class LinearGradient(Gradient): + """LinearGradient element""" + + tag_name = "linearGradient" + orientation_attributes = ("x1", "y1", "x2", "y2") + """ + .. versionadded:: 1.1 + """ + + def apply_transform(self): # type: () -> None + """Apply transform to orientation points and set it to identity. + .. versionadded:: 1.1 + """ + trans = self.pop("gradientTransform") + pt1 = ( + self.to_dimensionless(self.get("x1")), + self.to_dimensionless(self.get("y1")), + ) + pt2 = ( + self.to_dimensionless(self.get("x2")), + self.to_dimensionless(self.get("y2")), + ) + p1t = trans.apply_to_point(pt1) + p2t = trans.apply_to_point(pt2) + self.update( + x1=self.to_dimensionless(p1t[0]), + y1=self.to_dimensionless(p1t[1]), + x2=self.to_dimensionless(p2t[0]), + y2=self.to_dimensionless(p2t[1]), + ) + + +class RadialGradient(Gradient): + """RadialGradient element""" + + tag_name = "radialGradient" + orientation_attributes = ("cx", "cy", "fx", "fy", "r") + """ + .. versionadded:: 1.1 + """ + + def apply_transform(self): # type: () -> None + """Apply transform to orientation points and set it to identity. + + .. versionadded:: 1.1 + """ + trans = self.pop("gradientTransform") + pt1 = ( + self.to_dimensionless(self.get("cx")), + self.to_dimensionless(self.get("cy")), + ) + pt2 = ( + self.to_dimensionless(self.get("fx")), + self.to_dimensionless(self.get("fy")), + ) + p1t = trans.apply_to_point(pt1) + p2t = trans.apply_to_point(pt2) + self.update( + cx=self.to_dimensionless(p1t[0]), + cy=self.to_dimensionless(p1t[1]), + fx=self.to_dimensionless(p2t[0]), + fy=self.to_dimensionless(p2t[1]), + ) + + +class PathEffect(BaseElement): + """Inkscape LPE element""" + + tag_name = "inkscape:path-effect" + + +class MeshGradient(Gradient): + """Usable MeshGradient XML base class + + .. versionadded:: 1.1""" + + tag_name = "meshgradient" + + @classmethod + def new_mesh(cls, pos=None, rows=1, cols=1, autocollect=True): + """Return skeleton of 1x1 meshgradient definition.""" + # initial point + if pos is None or len(pos) != 2: + pos = [0.0, 0.0] + # create nested elements for rows x cols mesh + meshgradient = cls() + for _ in range(rows): + meshrow: BaseElement = meshgradient.add(MeshRow()) + for _ in range(cols): + meshrow.append(MeshPatch()) + # set meshgradient attributes + meshgradient.set("gradientUnits", "userSpaceOnUse") + meshgradient.set("x", pos[0]) + meshgradient.set("y", pos[1]) + if autocollect: + meshgradient.set("inkscape:collect", "always") + return meshgradient + + +class MeshRow(BaseElement): + """Each row of a mesh gradient + + .. versionadded:: 1.1""" + + tag_name = "meshrow" + + +class MeshPatch(BaseElement): + """Each column or 'patch' in a mesh gradient + + .. versionadded:: 1.1""" + + tag_name = "meshpatch" + + def stops(self, edges, colors): + """Add or edit meshpatch stops with path and stop-color.""" + # iterate stops based on number of edges (path data) + for i, edge in enumerate(edges): + if i < len(self): + stop = self[i] + else: + stop = self.add(Stop()) + + # set edge path data + stop.set("path", str(edge)) + # set stop color + stop.style["stop-color"] = str(colors[i % 2]) diff --git a/share/extensions/inkex/elements/_groups.py b/share/extensions/inkex/elements/_groups.py new file mode 100644 index 0000000..c66bfe3 --- /dev/null +++ b/share/extensions/inkex/elements/_groups.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Sergei Izmailov +# Ryan Jarvis +# +# 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. +# +# pylint: disable=arguments-differ +""" +Interface for all group based elements such as Groups, Use, Markers etc. +""" + +from lxml import etree # pylint: disable=unused-import + +from ..paths import Path +from ..transforms import Transform + +from ._utils import addNS +from ._base import ShapeElement + +try: + from typing import Optional # pylint: disable=unused-import +except ImportError: + pass + + +class GroupBase(ShapeElement): + """Base Group element""" + + def get_path(self): + ret = Path() + for child in self: + if isinstance(child, ShapeElement): + ret += child.path.transform(child.transform) + return ret + + def shape_box(self, transform=None): + bbox = None + effective_transform = Transform(transform) @ self.transform + for child in self: + if isinstance(child, ShapeElement): + child_bbox = child.bounding_box(transform=effective_transform) + if child_bbox is not None: + bbox += child_bbox + return bbox + + +class Group(GroupBase): + """Any group element (layer or regular group)""" + + tag_name = "g" + + @classmethod + def new(cls, label, *children, **attrs): + attrs["inkscape:label"] = label + return super().new(*children, **attrs) + + def effective_style(self): + """A blend of each child's style mixed together (last child wins)""" + style = self.style + for child in self: + style.update(child.effective_style()) + return style + + @property + def groupmode(self): + """Return the type of group this is""" + return self.get("inkscape:groupmode", "group") + + +class Layer(Group): + """Inkscape extension of svg:g""" + + def _init(self): + self.set("inkscape:groupmode", "layer") + + @classmethod + def is_class_element(cls, elem): + # type: (etree.Element) -> bool + return elem.attrib.get(addNS("inkscape:groupmode"), None) == "layer" + + +class Anchor(GroupBase): + """An anchor or link tag""" + + tag_name = "a" + + @classmethod + def new(cls, href, *children, **attrs): + attrs["xlink:href"] = href + return super().new(*children, **attrs) + + +class ClipPath(GroupBase): + """A path used to clip objects""" + + tag_name = "clipPath" + + +class Marker(GroupBase): + """The element defines the graphic that is to be used for drawing + arrowheads or polymarkers on a given , , or + element.""" + + tag_name = "marker" + + +class Mask(GroupBase): + """An alpha mask for compositing an object into the background + + .. versionadded:: 1.2""" + + tag_name = "mask" diff --git a/share/extensions/inkex/elements/_image.py b/share/extensions/inkex/elements/_image.py new file mode 100644 index 0000000..9294d73 --- /dev/null +++ b/share/extensions/inkex/elements/_image.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 - Martin Owens +# +# 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. +# +""" +Image element interface. +""" + +from ._polygons import RectangleBase + + +class Image(RectangleBase): + """Provide a useful extension for image elements""" + + tag_name = "image" diff --git a/share/extensions/inkex/elements/_meta.py b/share/extensions/inkex/elements/_meta.py new file mode 100644 index 0000000..e9eeb0f --- /dev/null +++ b/share/extensions/inkex/elements/_meta.py @@ -0,0 +1,293 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Maren Hachmann +# +# 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. +# +# pylint: disable=arguments-differ +""" +Provide extra utility to each svg element type specific to its type. + +This is useful for having a common interface for each element which can +give path, transform, and property access easily. +""" + +from __future__ import annotations +import math + +from typing import Optional + +from lxml import etree + +from ..styles import StyleSheet +from ..transforms import Vector2d, VectorLike, DirectedLineSegment + +from ._base import BaseElement + + +class Defs(BaseElement): + """A header defs element, one per document""" + + tag_name = "defs" + + +class StyleElement(BaseElement): + """A CSS style element containing multiple style definitions""" + + tag_name = "style" + + def set_text(self, content): + """Sets the style content text as a CDATA section""" + self.text = etree.CDATA(str(content)) + + def stylesheet(self): + """Return the StyleSheet() object for the style tag""" + return StyleSheet(self.text, callback=self.set_text) + + +class Script(BaseElement): + """A javascript tag in SVG""" + + tag_name = "script" + + def set_text(self, content): + """Sets the style content text as a CDATA section""" + self.text = etree.CDATA(str(content)) + + +class Desc(BaseElement): + """Description element""" + + tag_name = "desc" + + +class Title(BaseElement): + """Title element""" + + tag_name = "title" + + +class NamedView(BaseElement): + """The NamedView element is Inkscape specific metadata about the file""" + + tag_name = "sodipodi:namedview" + + current_layer = property(lambda self: self.get("inkscape:current-layer")) + + @property + def center(self): + """Returns view_center in terms of document units""" + return Vector2d( + self.root.viewport_to_unit(self.get("inkscape:cx") or 0), + self.root.viewport_to_unit(self.get("inkscape:cy") or 0), + ) + + def get_guides(self): + """Returns a list of guides""" + return self.findall("sodipodi:guide") + + def new_guide(self, position, orient=True, name=None): + """Creates a new guide in this namedview + + Args: + position: a float containing the y position for ``orient is True``, or + the x position for ``orient is False`` + + .. versionchanged:: 1.2 + Alternatively, the position may be given as Tuple (or VectorLike) + orient: True for horizontal, False for Vertical + + .. versionchanged:: 1.2 + Tuple / Vector specifying x and y coordinates of the normal vector + of the guide. + name: label of the guide + + Returns: + the created guide""" + if orient is True: + elem = Guide().move_to(0, position, (0, 1)) + elif orient is False: + elem = Guide().move_to(position, 0, (1, 0)) + else: + elem = Guide().move_to(*position, orient) + if name: + elem.set("inkscape:label", str(name)) + return self.add(elem) + + def new_unique_guide( + self, position: VectorLike, orientation: VectorLike + ) -> Optional[Guide]: + """Add a guide iif there is no guide that looks the same. + + .. versionadded:: 1.2""" + elem = Guide().move_to(position[0], position[1], orientation) + return self.add(elem) if self.get_similar_guide(elem) is None else None + + def get_similar_guide(self, other: Guide) -> Optional[Guide]: + """Check if the namedview contains a guide that looks identical to one + defined by (position, orientation). If such a guide exists, return it; + otherwise, return None. + + .. versionadded:: 1.2""" + for guide in self.get_guides(): + if Guide.guides_coincident(guide, other): + return guide + return None + + def get_pages(self): + """Returns a list of pages + + .. versionadded:: 1.2""" + return self.findall("inkscape:page") + + def new_page(self, x, y, width, height, label=None): + """Creates a new page in this namedview + + .. versionadded:: 1.2""" + elem = Page(width=width, height=height, x=x, y=y) + if label: + elem.set("inkscape:label", str(label)) + return self.add(elem) + + +class Guide(BaseElement): + """An inkscape guide""" + + tag_name = "sodipodi:guide" + + @property + def orientation(self) -> Vector2d: + """Vector normal to the guide + + .. versionadded:: 1.2""" + return Vector2d(self.get("orientation"), fallback=(1, 0)) + + is_horizontal = property( + lambda self: self.orientation[0] == 0 and self.orientation[1] != 0 + ) + is_vertical = property( + lambda self: self.orientation[0] != 0 and self.orientation[1] == 0 + ) + + @property + def point(self) -> Vector2d: + """Position of the guide handle. The y coordinate is flipped and relative + to the bottom of the viewbox, this is a remnant of the pre-1.0 coordinate system + """ + return Vector2d(self.get("position"), fallback=(0, 0)) + + @classmethod + def new(cls, pos_x, pos_y, angle, **attrs): + guide = super().new(**attrs) + guide.move_to(pos_x, pos_y, angle=angle) + return guide + + def move_to(self, pos_x, pos_y, angle=None): + """ + Move this guide to the given x,y position, + + Angle may be a float or integer, which will change the orientation. Alternately, + it may be a pair of numbers (tuple) which will set the orientation directly. + If not given at all, the orientation remains unchanged. + """ + self.set("position", f"{float(pos_x):g},{float(pos_y):g}") + if isinstance(angle, str): + if "," not in angle: + angle = float(angle) + + if isinstance(angle, (float, int)): + # Generate orientation from angle + angle = (math.sin(math.radians(angle)), -math.cos(math.radians(angle))) + + if isinstance(angle, (tuple, list)) and len(angle) == 2: + angle = ",".join(f"{i:g}" for i in angle) + + if angle is not None: + self.set("orientation", angle) + return self + + @staticmethod + def guides_coincident(guide1, guide2): + """Check if two guides defined by (position, orientation) and (opos, oor) look + identical (i.e. the position lies on the other guide AND the guide is + (anti)parallel to the other guide). + + .. versionadded:: 1.2""" + # normalize orientations first + orientation = guide1.orientation / guide1.orientation.length + oor = guide2.orientation / guide2.orientation.length + + position = guide1.point + opos = guide2.point + + return ( + DirectedLineSegment( + position, position + Vector2d(orientation[1], -orientation[0]) + ).perp_distance(*opos) + < 1e-6 + and abs(abs(orientation[1] * oor[0]) - abs(orientation[0] * oor[1])) < 1e-6 + ) + + +class Metadata(BaseElement): + """Inkscape Metadata element""" + + tag_name = "metadata" + + +class ForeignObject(BaseElement): + """SVG foreignObject element""" + + tag_name = "foreignObject" + + +class Switch(BaseElement): + """A switch element""" + + tag_name = "switch" + + +class Grid(BaseElement): + """A namedview grid child""" + + tag_name = "inkscape:grid" + + +class Page(BaseElement): + """A namedview page child + + .. versionadded:: 1.2""" + + tag_name = "inkscape:page" + + width = property(lambda self: self.to_dimensionless(self.get("width") or 0)) + height = property(lambda self: self.to_dimensionless(self.get("height") or 0)) + x = property(lambda self: self.to_dimensionless(self.get("x") or 0)) + y = property(lambda self: self.to_dimensionless(self.get("y") or 0)) + + @classmethod + def new(cls, width, height, x, y): + """Creates a new page element in the namedview""" + page = super().new() + page.move_to(x, y) + page.set("width", width) + page.set("height", height) + return page + + def move_to(self, x, y): + """Move this page to the given x,y position""" + self.set("position", f"{float(x):g},{float(y):g}") + return self diff --git a/share/extensions/inkex/elements/_parser.py b/share/extensions/inkex/elements/_parser.py new file mode 100644 index 0000000..0357eec --- /dev/null +++ b/share/extensions/inkex/elements/_parser.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Sergei Izmailov +# Thomas Holder +# +# 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. +# + +"""Utilities for parsing SVG documents. + +.. versionadded:: 1.2 + Separated out from :py:mod:`inkex.elements._base`""" + +from collections import defaultdict +from typing import DefaultDict, List, Any, Type + +from lxml import etree + +from ..interfaces.IElement import IBaseElement + +from ._utils import splitNS +from ..utils import errormsg +from ..localization import inkex_gettext as _ + + +class NodeBasedLookup(etree.PythonElementClassLookup): + """ + We choose what kind of Elements we should return for each element, providing useful + SVG based API to our extensions system. + """ + + default: Type[IBaseElement] + + # (ns,tag) -> list(cls) ; ascending priority + lookup_table = defaultdict(list) # type: DefaultDict[str, List[Any]] + + @classmethod + def register_class(cls, klass): + """Register the given class using it's attached tag name""" + cls.lookup_table[splitNS(klass.tag_name)].append(klass) + + @classmethod + def find_class(cls, xpath): + """Find the class for this type of element defined by an xpath + + .. versionadded:: 1.1""" + if isinstance(xpath, type): + return xpath + for kls in cls.lookup_table[splitNS(xpath.split("/")[-1])]: + # TODO: We could create a apply the xpath attrs to the test element + # to narrow the search, but this does everything we need right now. + test_element = kls() + if kls.is_class_element(test_element): + return kls + raise KeyError(f"Could not find svg tag for '{xpath}'") + + def lookup(self, doc, element): # pylint: disable=unused-argument + """Lookup called by lxml when assigning elements their object class""" + try: + for kls in reversed(self.lookup_table[splitNS(element.tag)]): + if kls.is_class_element(element): # pylint: disable=protected-access + return kls + except TypeError: + # Handle non-element proxies case + # The documentation implies that it's not possible + # Didn't found a reliable way to check whether proxy corresponds to element + # or not + # Look like lxml issue to me. + # The troubling element is "" + return None + return NodeBasedLookup.default + + +SVG_PARSER = etree.XMLParser(huge_tree=True, strip_cdata=False, recover=True) +SVG_PARSER.set_element_class_lookup(NodeBasedLookup()) + + +def load_svg(stream): + """Load SVG file using the SVG_PARSER""" + if (isinstance(stream, str) and stream.lstrip().startswith("<")) or ( + isinstance(stream, bytes) and stream.lstrip().startswith(b"<") + ): + parsed = etree.ElementTree(etree.fromstring(stream, parser=SVG_PARSER)) + else: + parsed = etree.parse(stream, parser=SVG_PARSER) + if len(SVG_PARSER.error_log) > 0: + errormsg( + _( + "A parsing error occured, which means you are likely working with " + "a non-conformant SVG file. The following errors were found:\n" + ) + ) + for __, element in enumerate(SVG_PARSER.error_log): + errormsg( + _("{}. Line {}, column {}").format( + element.message, element.line, element.column + ) + ) + errormsg( + _( + "\nProcessing will continue; however we encourage you to fix your" + " file manually." + ) + ) + return parsed diff --git a/share/extensions/inkex/elements/_polygons.py b/share/extensions/inkex/elements/_polygons.py new file mode 100644 index 0000000..4f88a3a --- /dev/null +++ b/share/extensions/inkex/elements/_polygons.py @@ -0,0 +1,507 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Sergei Izmailov +# Thomas Holder +# +# 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. +# +# pylint: disable=arguments-differ +""" +Interface for all shapes/polygons such as lines, paths, rectangles, circles etc. +""" + +from math import cos, pi, sin +from typing import Optional, Tuple +from ..paths import Arc, Curve, Move, Path, ZoneClose +from ..paths import Line as PathLine +from ..transforms import Transform, ImmutableVector2d, Vector2d +from ..bezier import pointdistance + +from ._utils import addNS +from ._base import ShapeElement + + +class PathElementBase(ShapeElement): + """Base element for path based shapes""" + + get_path = lambda self: Path(self.get("d")) + + @classmethod + def new(cls, path, **attrs): + return super().new(d=Path(path), **attrs) + + def set_path(self, path): + """Set the given data as a path as the 'd' attribute""" + self.set("d", str(Path(path))) + + def apply_transform(self): + """Apply the internal transformation to this node and delete""" + if "transform" in self.attrib: + self.path = self.path.transform(self.transform) + self.set("transform", Transform()) + + @property + def original_path(self): + """Returns the original path if this is a LPE, or the path if not""" + return Path(self.get("inkscape:original-d", self.path)) + + @original_path.setter + def original_path(self, path): + if addNS("inkscape:original-d") in self.attrib: + self.set("inkscape:original-d", str(Path(path))) + else: + self.path = path + + +class PathElement(PathElementBase): + """Provide a useful extension for path elements""" + + tag_name = "path" + + @staticmethod + def _arcpath( + cx: float, + cy: float, + rx: float, + ry: float, + start: float, + end: float, + arctype: str, + ) -> Optional[Path]: + """Compute the path for an arc defined by Inkscape-specific attributes. + + For details on arguments, see :func:`arc`. + + .. versionadded:: 1.2""" + if abs(rx) < 1e-8 or abs(ry) < 1e-8: + return None + incr = end - start + if incr < 0: + incr += 2 * pi + numsegs = min(1 + int(incr * 2.0 / pi), 4) + incr = incr / numsegs + + computed = Path() + computed.append(Move(cos(start), sin(start))) + for seg in range(1, numsegs + 1): + computed.append( + Arc(1, 1, 0, 0, 1, cos(start + seg * incr), sin(start + seg * incr)) + ) + if abs(incr * numsegs - 2 * pi) > 1e-8 and ( + arctype in ("slice", "") + ): # slice is default + computed.append(PathLine(0, 0)) + if arctype != "arc": + computed.append(ZoneClose()) + computed.transform( + Transform().add_translate(cx, cy).add_scale(rx, ry), inplace=True + ) + return computed.to_relative() + + @classmethod + def arc( + cls, center, rx, ry=None, arctype="", pathonly=False, **kw + ): # pylint: disable=invalid-name + """Generates a sodipodi elliptical arc (special type). Also computes the path + that Inkscape uses under the hood. + All data may be given as parseable strings or using numeric data types. + + Args: + center (tuple-like): Coordinates of the star/polygon center as tuple or + Vector2d + rx (Union[float, str]): Radius in x direction + ry (Union[float, str], optional): Radius in y direction. If not given, + ry=rx. Defaults to None. + arctype (str, optional): "arc", "chord" or "slice". Defaults to "", i.e. + "slice". + + .. versionadded:: 1.2 + Previously set to "arc" as fixed value + pathonly (bool, optional): Whether to create the path without + Inkscape-specific attributes. Defaults to False. + + .. versionadded:: 1.2 + Keyword args: + start (Union[float, str]): start angle in radians + end (Union[float, str]): end angle in radians + open (str): whether the path should be open (true/false). Not used in + Inkscape > 1.1 + + Returns: + PathElement : the created star/polygon + """ + others = [(name, kw.pop(name, None)) for name in ("start", "end", "open")] + elem = cls(**kw) + elem.set("sodipodi:cx", center[0]) + elem.set("sodipodi:cy", center[1]) + elem.set("sodipodi:rx", rx) + elem.set("sodipodi:ry", ry or rx) + elem.set("sodipodi:type", "arc") + if arctype != "": + elem.set("sodipodi:arc-type", arctype) + for name, value in others: + if value is not None: + elem.set("sodipodi:" + name, str(value).lower()) + + path = cls._arcpath( + float(center[0]), + float(center[1]), + float(rx), + float(ry or rx), + float(elem.get("sodipodi:start", 0)), + float(elem.get("sodipodi:end", 2 * pi)), + arctype, + ) + if pathonly: + elem = cls(**kw) + if path is not None: + elem.path = path + return elem + + @staticmethod + def _starpath( + c: Tuple[float, float], + sides: int, + r: Tuple[float, float], # pylint: disable=invalid-name + arg: Tuple[float, float], + rounded: float, + flatsided: bool, + ): + """Helper method to generate the path for an Inkscape star/ polygon; randomized + is ignored. + + For details on arguments, see :func:`star`. + + .. versionadded:: 1.2""" + + def _star_get_xy(point, index): + cur_arg = arg[point] + 2 * pi / sides * (index % sides) + return Vector2d(*c) + r[point] * Vector2d(cos(cur_arg), sin(cur_arg)) + + def _rot90_rel(origin, other): + """Returns a unit length vector at 90 deg from origin to other""" + return ( + 1 + / pointdistance(other, origin) + * Vector2d(other.y - origin.y, other.x - origin.x) + ) + + def _star_get_curvepoint(point, index, is_prev: bool): + index = index % sides + orig = _star_get_xy(point, index) + previ = (index - 1 + sides) % sides + nexti = (index + 1) % sides + # neighbors of the current point depend on polygon or star + prev = ( + _star_get_xy(point, previ) + if flatsided + else _star_get_xy(1 - point, index if point == 1 else previ) + ) + nextp = ( + _star_get_xy(point, nexti) + if flatsided + else _star_get_xy(1 - point, index if point == 0 else nexti) + ) + mid = 0.5 * (prev + nextp) + # direction of bezier handles + rot = _rot90_rel(orig, mid + 100000 * _rot90_rel(mid, nextp)) + ret = ( + rounded + * rot + * ( + -1 * pointdistance(prev, orig) + if is_prev + else pointdistance(nextp, orig) + ) + ) + return orig + ret + + pointy = abs(rounded) < 1e-4 + result = Path() + result.append(Move(*_star_get_xy(0, 0))) + for i in range(0, sides): + # draw to point type 1 for stars + if not flatsided: + if pointy: + result.append(PathLine(*_star_get_xy(1, i))) + else: + result.append( + Curve( + *_star_get_curvepoint(0, i, False), + *_star_get_curvepoint(1, i, True), + *_star_get_xy(1, i), + ) + ) + # draw to point type 0 for both stars and rectangles + if pointy and i < sides - 1: + result.append(PathLine(*_star_get_xy(0, i + 1))) + if not pointy: + if not flatsided: + result.append( + Curve( + *_star_get_curvepoint(1, i, False), + *_star_get_curvepoint(0, i + 1, True), + *_star_get_xy(0, i + 1), + ) + ) + else: + result.append( + Curve( + *_star_get_curvepoint(0, i, False), + *_star_get_curvepoint(0, i + 1, True), + *_star_get_xy(0, i + 1), + ) + ) + + result.append(ZoneClose()) + return result.to_relative() + + @classmethod + def star( + cls, + center, + radii, + sides=5, + rounded=0, + args=(0, 0), + flatsided=False, + pathonly=False, + ): + """Generate a sodipodi star / polygon. Also computes the path that Inkscape uses + under the hood. The arguments for center, radii, sides, rounded and args can be + given as strings or as numeric data. + + .. versionadded:: 1.1 + + Args: + center (Tuple-like): Coordinates of the star/polygon center as tuple or + Vector2d + radii (tuple): Radii of the control points, i.e. their distances from the + center. The control points are specified in polar coordinates. Only the + first control point is used for polygons. + sides (int, optional): Number of sides / tips of the polygon / star. + Defaults to 5. + rounded (int, optional): Controls the rounding radius of the polygon / star. + For `rounded=0`, only straight lines are used. Defaults to 0. + args (tuple, optional): Angle between horizontal axis and control points. + Defaults to (0,0). + + .. versionadded:: 1.2 + Previously fixed to (0.85, 1.3) + flatsided (bool, optional): True for polygons, False for stars. + Defaults to False. + + .. versionadded:: 1.2 + pathonly (bool, optional): Whether to create the path without + Inkscape-specific attributes. Defaults to False. + + .. versionadded:: 1.2 + + Returns: + PathElement : the created star/polygon + """ + elem = cls() + elem.set("sodipodi:cx", center[0]) + elem.set("sodipodi:cy", center[1]) + elem.set("sodipodi:r1", radii[0]) + elem.set("sodipodi:r2", radii[1]) + elem.set("sodipodi:arg1", args[0]) + elem.set("sodipodi:arg2", args[1]) + elem.set("sodipodi:sides", max(sides, 3) if flatsided else max(sides, 2)) + elem.set("inkscape:rounded", rounded) + elem.set("inkscape:flatsided", str(flatsided).lower()) + elem.set("sodipodi:type", "star") + + path = cls._starpath( + (float(center[0]), float(center[1])), + int(sides), + (float(radii[0]), float(radii[1])), + (float(args[0]), float(args[1])), + float(rounded), + flatsided, + ) + if pathonly: + elem = cls() + # inkex.errormsg(path) + if path is not None: + elem.path = path + + return elem + + +class Polyline(ShapeElement): + """Like a path, but made up of straight line segments only""" + + tag_name = "polyline" + + def get_path(self): + return Path("M" + self.get("points")) + + def set_path(self, path): + points = [f"{x:g},{y:g}" for x, y in Path(path).end_points] + self.set("points", " ".join(points)) + + +class Polygon(ShapeElement): + """A closed polyline""" + + tag_name = "polygon" + get_path = lambda self: Path("M" + self.get("points") + " Z") + + +class Line(ShapeElement): + """A line segment connecting two points""" + + tag_name = "line" + x1 = property(lambda self: self.to_dimensionless(self.get("x1", 0))) + y1 = property(lambda self: self.to_dimensionless(self.get("y1", 0))) + x2 = property(lambda self: self.to_dimensionless(self.get("x2", 0))) + y2 = property(lambda self: self.to_dimensionless(self.get("y2", 0))) + get_path = lambda self: Path(f"M{self.x1},{self.y1} L{self.x2},{self.y2}") + + @classmethod + def new(cls, start, end, **attrs): + start = Vector2d(start) + end = Vector2d(end) + return super().new(x1=start.x, y1=start.y, x2=end.x, y2=end.y, **attrs) + + +class RectangleBase(ShapeElement): + """Provide a useful extension for rectangle elements""" + + left = property(lambda self: self.to_dimensionless(self.get("x", "0"))) + top = property(lambda self: self.to_dimensionless(self.get("y", "0"))) + right = property(lambda self: self.left + self.width) + bottom = property(lambda self: self.top + self.height) + width = property(lambda self: self.to_dimensionless(self.get("width", "0"))) + height = property(lambda self: self.to_dimensionless(self.get("height", "0"))) + rx = property( + lambda self: self.to_dimensionless(self.get("rx", self.get("ry", 0.0))) + ) + ry = property( + lambda self: self.to_dimensionless(self.get("ry", self.get("rx", 0.0))) + ) # pylint: disable=invalid-name + + def get_path(self): + """Calculate the path as the box around the rect""" + if self.rx: + rx, ry = self.rx, self.ry # pylint: disable=invalid-name + cpts = [self.left + rx, self.right - rx, self.top + ry, self.bottom - ry] + return ( + f"M {cpts[0]},{self.top}" + f"L {cpts[1]},{self.top} " + f"A {self.rx},{self.ry} 0 0 1 {self.right},{cpts[2]}" + f"L {self.right},{cpts[3]} " + f"A {self.rx},{self.ry} 0 0 1 {cpts[1]},{self.bottom}" + f"L {cpts[0]},{self.bottom} " + f"A {self.rx},{self.ry} 0 0 1 {self.left},{cpts[3]}" + f"L {self.left},{cpts[2]} " + f"A {self.rx},{self.ry} 0 0 1 {cpts[0]},{self.top} z" + ) + + return f"M {self.left},{self.top} h{self.width}v{self.height}h{-self.width} z" + + +class Rectangle(RectangleBase): + """Provide a useful extension for rectangle elements""" + + tag_name = "rect" + + @classmethod + def new(cls, left, top, width, height, **attrs): + return super().new(x=left, y=top, width=width, height=height, **attrs) + + +class EllipseBase(ShapeElement): + """Absorbs common part of Circle and Ellipse classes""" + + def get_path(self): + """Calculate the arc path of this circle""" + rx, ry = self._rxry() + cx, y = self.center.x, self.center.y - ry + return ( + "M {cx},{y} " + "a {rx},{ry} 0 1 0 {rx}, {ry} " + "a {rx},{ry} 0 0 0 -{rx}, -{ry} z" + ).format(cx=cx, y=y, rx=rx, ry=ry) + + @property + def center(self): + """Return center of circle/ellipse""" + return ImmutableVector2d( + self.to_dimensionless(self.get("cx", "0")), + self.to_dimensionless(self.get("cy", "0")), + ) + + @center.setter + def center(self, value): + value = Vector2d(value) + self.set("cx", value.x) + self.set("cy", value.y) + + def _rxry(self): + # type: () -> Vector2d + """Helper function""" + raise NotImplementedError() + + @classmethod + def new(cls, center, radius, **attrs): + circle = super().new(**attrs) + circle.center = center + circle.radius = radius + return circle + + +class Circle(EllipseBase): + """Provide a useful extension for circle elements""" + + tag_name = "circle" + + @property + def radius(self) -> float: + """Return radius of circle""" + return self.to_dimensionless(self.get("r", "0")) + + @radius.setter + def radius(self, value): + self.set("r", self.to_dimensionless(value)) + + def _rxry(self): + r = self.radius + return Vector2d(r, r) + + +class Ellipse(EllipseBase): + """Provide a similar extension to the Circle interface for ellipses""" + + tag_name = "ellipse" + + @property + def radius(self) -> ImmutableVector2d: + """Return radii of ellipse""" + return ImmutableVector2d( + self.to_dimensionless(self.get("rx", "0")), + self.to_dimensionless(self.get("ry", "0")), + ) + + @radius.setter + def radius(self, value): + value = Vector2d(value) + self.set("rx", str(value.x)) + self.set("ry", str(value.y)) + + def _rxry(self): + return self.radius diff --git a/share/extensions/inkex/elements/_selected.py b/share/extensions/inkex/elements/_selected.py new file mode 100644 index 0000000..9f23e59 --- /dev/null +++ b/share/extensions/inkex/elements/_selected.py @@ -0,0 +1,237 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# +# 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.,Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +""" +When elements are selected, these structures provide an advanced API. + +.. versionadded:: 1.1 +""" + +from collections import OrderedDict +from typing import Any, overload, Union, Optional + +from ..interfaces.IElement import IBaseElement +from ._utils import natural_sort_key +from ..localization import inkex_gettext +from ..utils import AbortExtension + + +class ElementList(OrderedDict): + """ + A list of elements, selected by id, iterator or xpath + + This may look like a dictionary, but it is really a list of elements. + The default iterator is the element objects themselves (not keys) and it is + possible to key elements by their numerical index. + + It is also possible to look up items by their id and the element object itself. + """ + + def __init__(self, svg, _iter=None): + self.svg = svg + self.ids = OrderedDict() + super().__init__() + if _iter is not None: + self.set(*list(_iter)) + + def __iter__(self): + return self.values().__iter__() + + def __getitem__(self, key): + return super().__getitem__(self._to_key(key)) + + def __contains__(self, key): + return super().__contains__(self._to_key(key)) + + def __setitem__(self, orig_key, elem): + + if orig_key != elem and orig_key != elem.get("id"): + raise ValueError(f"Refusing to set bad key in ElementList {orig_key}") + if isinstance(elem, str): + key = elem + elem = self.svg.getElementById(elem, literal=True) + if elem is None: + return + if isinstance(elem, IBaseElement): + # Selection is a list of elements to select + key = elem.xml_path + element_id = elem.get("id") + if element_id is not None: + self.ids[element_id] = key + super().__setitem__(key, elem) + else: + kind = type(elem).__name__ + raise ValueError(f"Unknown element type: {kind}") + + @overload + def _to_key(self, key: None, default: Any) -> Any: + ... + + @overload + def _to_key(self, key: Union[int, IBaseElement, str], default: Any) -> str: + ... + + def _to_key(self, key, default=None) -> str: + """Takes a key (id, element, etc) and returns an xml_path key""" + + if self and key is None: + key = default + if isinstance(key, int): + return list(self.keys())[key] + if isinstance(key, IBaseElement): + return key.xml_path + if isinstance(key, str) and key[0] != "/": + return self.ids.get(key, key) + return key + + def clear(self): + """Also clear ids""" + self.ids.clear() + super().clear() + + def set(self, *ids): + """ + Sets the currently selected elements to these ids, any existing + selection is cleared. + + Arguments a list of element ids, element objects or + a single xpath expression starting with ``//``. + + All element objects must have an id to be correctly set. + + >>> selection.set("rect123", "path456", "text789") + >>> selection.set(elem1, elem2, elem3) + >>> selection.set("//rect") + """ + self.clear() + self.add(*ids) + + def pop(self, key=None): + """Remove the key item or remove the last item selected""" + item = super().pop(self._to_key(key, default=-1)) + self.ids.pop(item.get("id")) + return item + + def add(self, *ids): + """Like set() but does not clear first""" + # Allow selecting of xpath elements directly + if len(ids) == 1 and isinstance(ids[0], str) and ids[0].startswith("//"): + ids = self.svg.xpath(ids[0]) + + for elem in ids: + self[elem] = elem # This doesn't matter + + def rendering_order(self): + """Get the selected elements by z-order (stacking order), ordered from bottom to + top + + .. versionadded:: 1.2 + :func:`paint_order` has been renamed to :func:`rendering_order`""" + new_list = ElementList(self.svg) + # the elements are stored with their xpath index, so a natural sort order + # '3' < '20' < '100' has to be applied + new_list.set( + *[ + elem + for _, elem in sorted( + self.items(), key=lambda x: natural_sort_key(x[0]) + ) + ] + ) + return new_list + + def filter(self, *types): + """Filter selected elements of the given type, returns a new SelectedElements + object""" + return ElementList( + self.svg, [e for e in self if not types or isinstance(e, types)] + ) + + def filter_nonzero(self, *types, error_msg: Optional[str] = None): + """Filter selected elements of the given type, returns a new SelectedElements + object. If the selection is empty, abort the extension. + + .. versionadded:: 1.2 + + :param error_msg: e + :type error_msg: str, optional + + Args: + *types (Type) : type(s) to filter the selection by + error_msg (str, optional): error message that is displayed if the selection + is empty, defaults to + ``_("Please select at least one element of type(s) {}")``. + Defaults to None. + + Raises: + AbortExtension: if the selection is empty + + Returns: + ElementList: filtered selection + """ + filtered = self.filter(*types) + if not filtered: + if error_msg is None: + error_msg = inkex_gettext( + "Please select at least one element of the following type(s): {}" + ).format(", ".join([type.__name__ for type in types])) + raise AbortExtension(error_msg) + return filtered + + def get(self, *types): + """Like filter, but will enter each element searching for any child of the given + types""" + + def _recurse(elem): + if not types or isinstance(elem, types): + yield elem + for child in elem: + yield from _recurse(child) + + return ElementList( + self.svg, + [ + r + for e in self + for r in _recurse(e) + if isinstance(r, (IBaseElement, str)) + ], + ) + + def id_dict(self): + """For compatibility, return regular dictionary of id -> element pairs""" + return {eid: self[xid] for eid, xid in self.ids.items()} + + def bounding_box(self): + """ + Gets a :class:`inkex.transforms.BoundingBox` object for the selected items. + + Text objects have a bounding box without width or height that only + reflects the coordinate of their anchor. If a text object is a part of + the selection's boundary, the bounding box may be inaccurate. + + When no object is selected or when the object's location cannot be + determined (e.g. empty group or layer), all coordinates will be None. + """ + return sum([elem.bounding_box() for elem in self], None) + + def first(self): + """Returns the first item in the selected list""" + for elem in self: + return elem + return None diff --git a/share/extensions/inkex/elements/_svg.py b/share/extensions/inkex/elements/_svg.py new file mode 100644 index 0000000..00228b1 --- /dev/null +++ b/share/extensions/inkex/elements/_svg.py @@ -0,0 +1,371 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Thomas Holder +# Sergei Izmailov +# Windell Oskay +# +# 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. +# +# pylint: disable=attribute-defined-outside-init +# +""" +Provide a way to load lxml attributes with an svg API on top. +""" + +import random +import math +import re + +from lxml import etree + +from ..css import ConditionalRule +from ..interfaces.IElement import ISVGDocumentElement + +from ..deprecated.meta import DeprecatedSvgMixin, deprecate +from ..units import discover_unit, parse_unit +from ._selected import ElementList +from ..transforms import BoundingBox +from ..styles import StyleSheets + +from ._base import BaseElement +from ._meta import StyleElement + +from typing import Optional, List + +if False: # pylint: disable=using-constant-test + import typing # pylint: disable=unused-import + + +class SvgDocumentElement(DeprecatedSvgMixin, ISVGDocumentElement, BaseElement): + """Provide access to the document level svg functionality""" + + # pylint: disable=too-many-public-methods + tag_name = "svg" + + selection: ElementList + """The selection as passed by Inkscape (readonly)""" + + def _init(self): + self.current_layer = None + self.view_center = (0.0, 0.0) + self.selection = ElementList(self) + self.ids = {} + + def tostring(self): + """Convert document to string""" + return etree.tostring(etree.ElementTree(self)) + + def get_ids(self): + """Returns a set of unique document ids""" + if not self.ids: + self.ids = set(self.xpath("//@id")) + return self.ids + + def get_unique_id( + self, + prefix: str, + size: Optional[int] = None, + blacklist: Optional[List[str]] = None, + ): + """Generate a new id from an existing old_id + + The id consists of a prefix and an appended random integer with size digits. + + If size is not given, it is determined automatically from the length of + existing ids, i.e. those in the document plus those in the blacklist. + + Args: + prefix (str): the prefix of the new ID. + size (Optional[int], optional): number of digits of the second part of the + id. If None, the length is chosen based on the amount of existing + objects. Defaults to None. + + .. versionchanged:: 1.1 + The default of this parameter has been changed from 4 to None. + blacklist (Optional[Iterable[str]], optional): An additional iterable of ids + that are not allowed to be used. This is useful when bulk inserting + objects. + Defaults to None. + + .. versionadded:: 1.2 + + Returns: + _type_: _description_ + """ + ids = self.get_ids() + if size is None: + size = max(math.ceil(math.log10(len(ids) or 1000)) + 1, 4) + if blacklist is not None: + ids.update(blacklist) + new_id = None + _from = 10**size - 1 + _to = 10**size + while new_id is None or new_id in ids: + # Do not use randint because py2/3 incompatibility + new_id = prefix + str(int(random.random() * _from - _to) + _to) + self.ids.add(new_id) + return new_id + + def get_page_bbox(self): + """Gets the page dimensions as a bbox""" + return BoundingBox( + (0, float(self.viewbox_width)), (0, float(self.viewbox_height)) + ) + + def get_current_layer(self): + """Returns the currently selected layer""" + layer = self.getElementById(self.namedview.current_layer, "svg:g") + if layer is None: + return self + return layer + + def getElement(self, xpath): # pylint: disable=invalid-name + """Gets a single element from the given xpath or returns None""" + return self.findone(xpath) + + def getElementById( + self, eid: str, elm="*", literal=False + ): # pylint: disable=invalid-name + """Get an element in this svg document by it's ID attribute. + + Args: + eid (str): element id + elm (str, optional): element type, including namespace, e.g. ``svg:path``. + Defaults to "*". + literal (bool, optional): If ``False``, ``#url()`` is stripped from ``eid``. + Defaults to False. + + .. versionadded:: 1.1 + + Returns: + Union[BaseElement, None]: found element + """ + if eid is not None and not literal: + eid = eid.strip()[4:-1] if eid.startswith("url(") else eid + eid = eid.lstrip("#") + return self.getElement(f'//{elm}[@id="{eid}"]') + + def getElementByName(self, name, elm="*"): # pylint: disable=invalid-name + """Get an element by it's inkscape:label (aka name)""" + return self.getElement(f'//{elm}[@inkscape:label="{name}"]') + + def getElementsByClass(self, class_name): # pylint: disable=invalid-name + """Get elements by it's class name""" + + return self.xpath(ConditionalRule(f".{class_name}").to_xpath()) + + def getElementsByHref( + self, eid: str, attribute="xlink:href" + ): # pylint: disable=invalid-name + """Get elements that reference the element with id eid. + + Args: + eid (str): _description_ + attribute (str, optional): Attribute to look for. + Valid choices: "xlink:href", "mask", "clip-path". + Defaults to "xlink:href". + + .. versionadded:: 1.2 + + Returns: + Any: list of elements + """ + if attribute == "xlink:href": + return self.xpath(f'//*[@xlink:href="#{eid}"]') + elif attribute == "mask": + return self.xpath(f'//*[@mask="url(#{eid})"]') + elif attribute == "clip-path": + return self.xpath(f'//*[@clip-path="url(#{eid})"]') + + def getElementsByStyleUrl(self, eid, style=None): # pylint: disable=invalid-name + """Get elements by a style attribute url""" + url = f"url(#{eid})" + if style is not None: + url = style + ":" + url + return self.xpath(f'//*[contains(@style,"{url}")]') + + @property + def name(self): + """Returns the Document Name""" + return self.get("sodipodi:docname", "") + + @property + def namedview(self): + """Return the sp namedview meta information element""" + return self.get_or_create("//sodipodi:namedview", prepend=True) + + @property + def metadata(self): + """Return the svg metadata meta element container""" + return self.get_or_create("//svg:metadata", prepend=True) + + @property + def defs(self): + """Return the svg defs meta element container""" + return self.get_or_create("//svg:defs", prepend=True) + + def get_viewbox(self): + """Parse and return the document's viewBox attribute""" + try: + ret = [ + float(unit) for unit in re.split(r",\s*|\s+", self.get("viewBox", "0")) + ] + except ValueError: + ret = "" + if len(ret) != 4: + return [0, 0, 0, 0] + return ret + + @property + def viewbox_width(self) -> float: # getDocumentWidth(self): + """Returns the width of the `user coordinate system + `_ in user units, i.e. + the width of the viewbox, as defined in the SVG file. If no viewbox is defined, + the value of the width attribute is returned. If the height is not defined, + returns 0. + + .. versionadded:: 1.2""" + return self.get_viewbox()[2] or self.viewport_width + + @property + def viewport_width(self) -> float: + """Returns the width of the `viewport coordinate system + `_ in user units, i.e. the + width attribute of the svg element converted to px + + .. versionadded:: 1.2""" + return self.to_dimensionless(self.get("width")) or self.get_viewbox()[2] + + @property + def viewbox_height(self) -> float: # getDocumentHeight(self): + """Returns the height of the `user coordinate system + `_ in user units, i.e. the + height of the viewbox, as defined in the SVG file. If no viewbox is defined, the + value of the height attribute is returned. If the height is not defined, + returns 0. + + .. versionadded:: 1.2""" + return self.get_viewbox()[3] or self.viewport_height + + @property + def viewport_height(self) -> float: + """Returns the width of the `viewport coordinate system + `_ in user units, i.e. the + height attribute of the svg element converted to px + + .. versionadded:: 1.2""" + return self.to_dimensionless(self.get("height")) or self.get_viewbox()[3] + + @property + def scale(self): + """Returns the ratio between the viewBox width and the page width. + + .. versionchanged:: 1.2 + Previously, the scale as shown by the document properties was computed, + but the computation of this in core Inkscape changed in Inkscape 1.2, so + this was moved to :attr:`inkscape_scale`.""" + return self._base_scale() + + @property + def inkscape_scale(self): + """Returns the ratio between the viewBox width (in width/height units) and the + page width, which is displayed as "scale" in the Inkscape document + properties. + + .. versionadded:: 1.2""" + + viewbox_unit = ( + parse_unit(self.get("width")) or parse_unit(self.get("height")) or (0, "px") + )[1] + return self._base_scale(viewbox_unit) + + def _base_scale(self, unit="px"): + """Returns what Inkscape shows as "user units per `unit`" + + .. versionadded:: 1.2""" + try: + scale_x = ( + self.to_dimensional(self.viewport_width, unit) / self.viewbox_width + ) + scale_y = ( + self.to_dimensional(self.viewport_height, unit) / self.viewbox_height + ) + value = max([scale_x, scale_y]) + return 1.0 if value == 0 else value + except (ValueError, ZeroDivisionError): + return 1.0 + + @property + def equivalent_transform_scale(self) -> float: + """Return the scale of the equivalent transform of the svg tag, as defined by + https://www.w3.org/TR/SVG2/coords.html#ComputingAViewportsTransform + (highly simplified) + + .. versionadded:: 1.2""" + return self.scale + + @property + def unit(self): + """Returns the unit used for in the SVG document. + In the case the SVG document lacks an attribute that explicitly + defines what units are used for SVG coordinates, it tries to calculate + the unit from the SVG width and viewBox attributes. + Defaults to 'px' units.""" + if not hasattr(self, "_unit"): + self._unit = "px" # Default is px + viewbox = self.get_viewbox() + if viewbox and set(viewbox) != {0}: + self._unit = discover_unit(self.get("width"), viewbox[2], default="px") + return self._unit + + @property + def document_unit(self): + """Returns the display unit (Inkscape-specific attribute) of the document + + .. versionadded:: 1.2""" + return self.namedview.get("inkscape:document-units", "px") + + @property + def stylesheets(self): + """Get all the stylesheets, bound together to one, (for reading)""" + sheets = StyleSheets(self) + for node in self.xpath("//svg:style"): + sheets.append(node.stylesheet()) + return sheets + + @property + def stylesheet(self): + """Return the first stylesheet or create one if needed (for writing)""" + for sheet in self.stylesheets: + return sheet + + style_node = StyleElement() + self.defs.append(style_node) + return style_node.stylesheet() + + +def width(self): + """Use :func:`viewport_width` instead""" + return self.viewport_width + + +def height(self): + """Use :func:`viewport_height` instead""" + return self.viewport_height + + +SvgDocumentElement.width = property(deprecate(width, "1.2")) +SvgDocumentElement.height = property(deprecate(height, "1.2")) diff --git a/share/extensions/inkex/elements/_text.py b/share/extensions/inkex/elements/_text.py new file mode 100644 index 0000000..8fc1756 --- /dev/null +++ b/share/extensions/inkex/elements/_text.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Thomas Holder +# +# 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. +# +# pylint: disable=arguments-differ +""" +Provide text based element classes interface. + +Because text is not rendered at all, no information about a text's path +size or actual location can be generated yet. +""" +from __future__ import annotations + +from tempfile import TemporaryDirectory + +from ..interfaces.IElement import BaseElementProtocol +from ..paths import Path +from ..transforms import Transform, BoundingBox +from ..command import inkscape, write_svg +from ._base import BaseElement, ShapeElement +from ._polygons import PathElementBase + + +class TextBBMixin: # pylint: disable=too-few-public-methods + """Mixin to query the bounding box from Inkscape + + .. versionadded:: 1.2""" + + def get_inkscape_bbox(self: BaseElementProtocol) -> BoundingBox: + """Query the bbbox of a single object. This calls the Inkscape command, + so it is rather slow to use in a loop.""" + with TemporaryDirectory(prefix="inkscape-command") as tmpdir: + svg_file = write_svg(self.root, tmpdir, "input.svg") + out = inkscape(svg_file, "-X", "-Y", "-W", "-H", query_id=self.get_id()) + out = list(map(self.root.viewport_to_unit, out.splitlines())) + if len(out) != 4: + raise ValueError("Error: Bounding box computation failed") + return BoundingBox.new_xywh(*out) + + +class FlowRegion(ShapeElement): + """SVG Flow Region (SVG 2.0)""" + + tag_name = "flowRegion" + + def get_path(self): + # This ignores flowRegionExcludes + return sum([child.path for child in self], Path()) + + +class FlowRoot(ShapeElement, TextBBMixin): + """SVG Flow Root (SVG 2.0)""" + + tag_name = "flowRoot" + + @property + def region(self): + """Return the first flowRegion in this flowRoot""" + return self.findone("svg:flowRegion") + + def get_path(self): + region = self.region + return region.get_path() if region is not None else Path() + + +class FlowPara(ShapeElement): + """SVG Flow Paragraph (SVG 2.0)""" + + tag_name = "flowPara" + + def get_path(self): + # XXX: These empty paths mean the bbox for text elements will be nothing. + return Path() + + +class FlowDiv(ShapeElement): + """SVG Flow Div (SVG 2.0)""" + + tag_name = "flowDiv" + + def get_path(self): + # XXX: These empty paths mean the bbox for text elements will be nothing. + return Path() + + +class FlowSpan(ShapeElement): + """SVG Flow Span (SVG 2.0)""" + + tag_name = "flowSpan" + + def get_path(self): + # XXX: These empty paths mean the bbox for text elements will be nothing. + return Path() + + +class TextElement(ShapeElement, TextBBMixin): + """A Text element""" + + tag_name = "text" + x = property(lambda self: self.to_dimensionless(self.get("x", 0))) + y = property(lambda self: self.to_dimensionless(self.get("y", 0))) + + def get_path(self): + return Path() + + def tspans(self): + """Returns all children that are tspan elements""" + return self.findall("svg:tspan") + + def get_text(self, sep="\n"): + """Return the text content including tspans""" + nodes = [self] + list(self.tspans()) + return sep.join([elem.text for elem in nodes if elem.text is not None]) + + def shape_box(self, transform=None): + """ + Returns a horrible bounding box that just contains the coord points + of the text without width or height (which is impossible to calculate) + """ + effective_transform = Transform(transform) @ self.transform + x, y = effective_transform.apply_to_point((self.x, self.y)) + bbox = BoundingBox(x, y) + for tspan in self.tspans(): + bbox += tspan.bounding_box(effective_transform) + return bbox + + +class TextPath(ShapeElement, TextBBMixin): + """A textPath element""" + + tag_name = "textPath" + + def get_path(self): + return Path() + + +class Tspan(ShapeElement, TextBBMixin): + """A tspan text element""" + + tag_name = "tspan" + x = property(lambda self: self.to_dimensionless(self.get("x", 0))) + y = property(lambda self: self.to_dimensionless(self.get("y", 0))) + + @classmethod + def superscript(cls, text): + """Adds a superscript tspan element""" + return cls(text, style="font-size:65%;baseline-shift:super") + + def get_path(self): + return Path() + + def shape_box(self, transform=None): + """ + Returns a horrible bounding box that just contains the coord points + of the text without width or height (which is impossible to calculate) + """ + effective_transform = Transform(transform) @ self.transform + x1, y1 = effective_transform.apply_to_point((self.x, self.y)) + fontsize = self.to_dimensionless(self.style.get("font-size", "12px")) + x2 = self.x + 0 # XXX This is impossible to calculate! + y2 = self.y + float(fontsize) + x2, y2 = effective_transform.apply_to_point((x2, y2)) + return BoundingBox((x1, x2), (y1, y2)) + + +class SVGfont(BaseElement): + """An svg font element""" + + tag_name = "font" + + +class FontFace(BaseElement): + """An svg font font-face element""" + + tag_name = "font-face" + + +class Glyph(PathElementBase): + """An svg font glyph element""" + + tag_name = "glyph" + + +class MissingGlyph(BaseElement): + """An svg font missing-glyph element""" + + tag_name = "missing-glyph" diff --git a/share/extensions/inkex/elements/_use.py b/share/extensions/inkex/elements/_use.py new file mode 100644 index 0000000..78acb61 --- /dev/null +++ b/share/extensions/inkex/elements/_use.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020 Martin Owens +# Thomas Holder +# +# 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. +# +""" +Interface for the Use and Symbol elements +""" + +from ..transforms import Transform + +from ._groups import Group, GroupBase +from ._base import ShapeElement + + +class Symbol(GroupBase): + """SVG symbol element""" + + tag_name = "symbol" + + +class Use(ShapeElement): + """A 'use' element that links to another in the document""" + + tag_name = "use" + + @classmethod + def new(cls, elem, x, y, **attrs): # pylint: disable=arguments-differ + ret = super().new(x=x, y=y, **attrs) + ret.href = elem + return ret + + def get_path(self): + """Returns the path of the cloned href plus any transformation""" + path = self.href.path + path.transform(self.href.transform) + return path + + def effective_style(self): + """Href's style plus this object's own styles""" + style = self.href.effective_style() + style.update(self.style) + return style + + def unlink(self): + """Unlink this clone, replacing it with a copy of the original""" + copy = self.href.copy() + if isinstance(copy, Symbol): + group = Group(**copy.attrib) + group.extend(copy) + copy = group + copy.transform = self.transform @ copy.transform + copy.transform.add_translate( + self.to_dimensionless(self.get("x", 0)), + self.to_dimensionless(self.get("y", 0)), + ) + copy.style = self.style + copy.style + self.replace_with(copy) + copy.set_random_ids() + return copy + + def shape_box(self, transform=None): + """BoundingBox of the unclipped shape + + .. versionadded:: 1.1""" + effective_transform = Transform(transform) @ self.transform + return self.href.bounding_box(effective_transform) diff --git a/share/extensions/inkex/elements/_utils.py b/share/extensions/inkex/elements/_utils.py new file mode 100644 index 0000000..56e1e12 --- /dev/null +++ b/share/extensions/inkex/elements/_utils.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2021 Martin Owens +# +# 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. +# +""" +Useful utilities specifically for elements (that aren't base classes) + +.. versionadded:: 1.1 + Most of the methods in this module were moved from inkex.utils. +""" + +from collections import defaultdict +import re + +# a dictionary of all of the xmlns prefixes in a standard inkscape doc +NSS = { + "sodipodi": "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + "cc": "http://creativecommons.org/ns#", + "ccOLD": "http://web.resource.org/cc/", + "svg": "http://www.w3.org/2000/svg", + "dc": "http://purl.org/dc/elements/1.1/", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "inkscape": "http://www.inkscape.org/namespaces/inkscape", + "xlink": "http://www.w3.org/1999/xlink", + "xml": "http://www.w3.org/XML/1998/namespace", +} +SSN = dict((b, a) for (a, b) in NSS.items()) + + +def addNS(tag, ns=None): # pylint: disable=invalid-name + """Add a known namespace to a name for use with lxml""" + if tag.startswith("{") and ns: + _, tag = removeNS(tag) + if not tag.startswith("{"): + tag = tag.replace("__", ":") + if ":" in tag: + (ns, tag) = tag.rsplit(":", 1) + ns = NSS.get(ns, None) or ns + if ns is not None: + return f"{{{ns}}}{tag}" + return tag + + +def removeNS(name): # pylint: disable=invalid-name + """The reverse of addNS, finds any namespace and returns tuple (ns, tag)""" + if name[0] == "{": + (url, tag) = name[1:].split("}", 1) + return SSN.get(url, "svg"), tag + if ":" in name: + return name.rsplit(":", 1) + return "svg", name + + +def splitNS(name): # pylint: disable=invalid-name + """Like removeNS, but returns a url instead of a prefix""" + (prefix, tag) = removeNS(name) + return (NSS[prefix], tag) + + +def natural_sort_key(key, _nsre=re.compile("([0-9]+)")): + """Helper for a natural sort, see + https://stackoverflow.com/a/16090640/3298143""" + return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(key)] + + +class ChildToProperty(property): + """Use when you have a singleton child element who's text + content is the canonical value for the property""" + + def __init__(self, tag, prepend=False): + super().__init__() + self.tag = tag + self.prepend = prepend + + def __get__(self, obj, klass=None): + elem = obj.findone(self.tag) + return elem.text if elem is not None else None + + def __set__(self, obj, value): + elem = obj.get_or_create(self.tag, prepend=self.prepend) + elem.text = value + + def __delete__(self, obj): + obj.remove_all(self.tag) + + @property + def __doc__(self): + return f"Get, set or delete the {self.tag} property." + + +class CloningVat: + """ + When modifying defs, sometimes we want to know if every backlink would have + needed changing, or it was just some of them. + + This tracks the def elements, their promises and creates clones if needed. + """ + + def __init__(self, svg): + self.svg = svg + self.tracks = defaultdict(set) + self.set_ids = defaultdict(list) + + def track(self, elem, parent, set_id=None, **kwargs): + """Track the element and connected parent""" + elem_id = elem.get("id") + parent_id = parent.get("id") + self.tracks[elem_id].add(parent_id) + self.set_ids[elem_id].append((set_id, kwargs)) + + def process(self, process, types=(), make_clones=True, **kwargs): + """ + Process each tracked item if the backlinks match the parents + + Optionally make clones, process the clone and set the new id. + """ + for elem_id in list(self.tracks): + parents = self.tracks[elem_id] + elem = self.svg.getElementById(elem_id) + backlinks = {blk.get("id") for blk in elem.backlinks(*types)} + if backlinks == parents: + # No need to clone, we're processing on-behalf of all parents + process(elem, **kwargs) + elif make_clones: + clone = elem.copy() + elem.getparent().append(clone) + clone.set_random_id() + for update, upkw in self.set_ids.get(elem_id, ()): + update(elem.get("id"), clone.get("id"), **upkw) + process(clone, **kwargs) diff --git a/share/extensions/inkex/extensions.py b/share/extensions/inkex/extensions.py new file mode 100644 index 0000000..37ead3d --- /dev/null +++ b/share/extensions/inkex/extensions.py @@ -0,0 +1,475 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 Martin Owens +# +# 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. +# +""" +A helper module for creating Inkscape effect extensions + +This provides the basic generic types of extensions which most writers should +use in their code. See below for the different types. +""" + +import os +import re +import sys +import types +from abc import ABC + +from .utils import errormsg, Boolean +from .colors import Color, ColorError +from .elements import ( + load_svg, + BaseElement, + ShapeElement, + Group, + Layer, + Grid, + TextElement, + FlowPara, + FlowDiv, + Pattern, +) +from .elements._utils import CloningVat +from .base import ( + InkscapeExtension, + SvgThroughMixin, + SvgInputMixin, + SvgOutputMixin, + TempDirMixin, +) +from .transforms import Transform +from .elements import LinearGradient, RadialGradient + +# All the names that get added to the inkex API itself. +__all__ = ( + "EffectExtension", + "GenerateExtension", + "InputExtension", + "OutputExtension", + "RasterOutputExtension", + "CallExtension", + "TemplateExtension", + "ColorExtension", + "TextExtension", +) + +stdout = sys.stdout + + +class EffectExtension(SvgThroughMixin, InkscapeExtension, ABC): + """ + Takes the SVG from Inkscape, modifies the selection or the document + and returns an SVG to Inkscape. + """ + + +class OutputExtension(SvgInputMixin, InkscapeExtension): + """ + Takes the SVG from Inkscape and outputs it to something that's not an SVG. + + Used in functions for `Save As` + """ + + def effect(self): + """Effect isn't needed for a lot of Output extensions""" + + def save(self, stream): + """But save certainly is, we give a more exact message here""" + raise NotImplementedError("Output extensions require a save(stream) method!") + + +class RasterOutputExtension(InkscapeExtension): + """ + Takes a PNG from Inkscape and outputs it to another rather format. + + .. versionadded:: 1.1 + """ + + def __init__(self): + super().__init__() + self.img = None + + def load(self, stream): + from PIL import Image + + # disable the PIL decompression bomb DOS attack check. + Image.MAX_IMAGE_PIXELS = None + + self.img = Image.open(stream) + + def effect(self): + """Not needed since image isn't being changed""" + + def save(self, stream): + """Implement raster image saving here from PIL""" + raise NotImplementedError("Raster Output extension requires a save method!") + + +class InputExtension(SvgOutputMixin, InkscapeExtension): + """ + Takes any type of file as input and outputs SVG which Inkscape can read. + + Used in functions for `Open` + """ + + def effect(self): + """Effect isn't needed for a lot of Input extensions""" + + def load(self, stream): + """But load certainly is, we give a more exact message here""" + raise NotImplementedError("Input extensions require a load(stream) method!") + + +class CallExtension(TempDirMixin, InputExtension): + """Call an external program to get the output""" + + input_ext = "svg" + output_ext = "svg" + + def load(self, stream): + pass # Not called (load_raw instead) + + def load_raw(self): + # Don't call InputExtension.load_raw + TempDirMixin.load_raw(self) + input_file = self.options.input_file + + if not isinstance(input_file, str): + data = input_file.read() + input_file = os.path.join(self.tempdir, "input." + self.input_ext) + with open(input_file, "wb") as fhl: + fhl.write(data) + + output_file = os.path.join(self.tempdir, "output." + self.output_ext) + document = self.call(input_file, output_file) or output_file + if isinstance(document, str): + if not os.path.isfile(document): + raise IOError(f"Can't find generated document: {document}") + + if self.output_ext == "svg": + with open(document, "r", encoding="utf-8") as fhl: + document = fhl.read() + if "<" in document: + document = load_svg(document.encode("utf-8")) + else: + with open(document, "rb") as fhl: + document = fhl.read() + + self.document = document + + def call(self, input_file, output_file): + """Call whatever programs are needed to get the desired result.""" + raise NotImplementedError("Call extensions require a call(in, out) method!") + + +class GenerateExtension(EffectExtension): + """ + Does not need any SVG, but instead just outputs an SVG fragment which is + inserted into Inkscape, centered on the selection. + """ + + container_label = "" + container_layer = False + + def generate(self): + """ + Return an SVG fragment to be inserted into the selected layer of the document + OR yield multiple elements which will be grouped into a container group + element which will be given an automatic label and transformation. + """ + raise NotImplementedError("Generate extensions must provide generate()") + + def container_transform(self): + """ + Generate the transformation for the container group, the default is + to return the center position of the svg document or view port. + """ + (pos_x, pos_y) = self.svg.namedview.center + if pos_x is None: + pos_x = 0 + if pos_y is None: + pos_y = 0 + return Transform(translate=(pos_x, pos_y)) + + def create_container(self): + """ + Return the container the generated elements will go into. + + Default is a new layer or current layer depending on the :attr:`container_layer` + flag. + + .. versionadded:: 1.1 + """ + container = (Layer if self.container_layer else Group).new(self.container_label) + if self.container_layer: + self.svg.append(container) + else: + container.transform = self.container_transform() + parent = self.svg.get_current_layer() + try: + parent_transform = parent.composed_transform() + except AttributeError: + pass + else: + container.transform = -parent_transform @ container.transform + parent.append(container) + return container + + def effect(self): + layer = self.svg.get_current_layer() + fragment = self.generate() + if isinstance(fragment, types.GeneratorType): + container = self.create_container() + for child in fragment: + if isinstance(child, BaseElement): + container.append(child) + elif isinstance(fragment, BaseElement): + layer.append(fragment) + else: + errormsg("Nothing was generated\n") + + +class TemplateExtension(EffectExtension): + """ + Provide a standard way of creating templates. + """ + + size_rex = re.compile(r"([\d.]*)(\w\w)?x([\d.]*)(\w\w)?") + template_id = "SVGRoot" + + def __init__(self): + self.svg = None + super().__init__() + # Arguments added on after add_arguments so it can be overloaded cleanly. + self.arg_parser.add_argument("--size", type=self.arg_size(), dest="size") + self.arg_parser.add_argument("--width", type=int, default=800) + self.arg_parser.add_argument("--height", type=int, default=600) + self.arg_parser.add_argument("--orientation", default=None) + self.arg_parser.add_argument("--unit", default="px") + self.arg_parser.add_argument("--grid", type=Boolean) + # self.svg = None + + def get_template(self, **kwargs): + """Can be over-ridden with custom svg loading here""" + return self.document + + def arg_size(self, unit="px"): + """Argument is a string of the form X[unit]xY[unit], default units apply + when missing""" + + def _inner(value): + try: + value = float(value) + return (value, unit, value, unit) + except ValueError: + pass + match = self.size_rex.match(str(value)) + if match is not None: + size = match.groups() + return ( + float(size[0]), + size[1] or unit, + float(size[2]), + size[3] or unit, + ) + return None + + return _inner + + def get_size(self): + """Get the size of the new template (defaults to size options)""" + size = self.options.size + if self.options.size is None: + size = ( + self.options.width, + self.options.unit, + self.options.height, + self.options.unit, + ) + if ( + self.options.orientation == "horizontal" + and size[0] < size[2] + or self.options.orientation == "vertical" + and size[0] > size[2] + ): + size = size[2:4] + size[0:2] + return size + + def effect(self): + """Creates a template, do not over-ride""" + (width, width_unit, height, height_unit) = self.get_size() + width_px = int(self.svg.uutounit(width, "px")) + height_px = int(self.svg.uutounit(height, "px")) + + self.document = self.get_template() + self.svg = self.document.getroot() + self.svg.set("id", self.template_id) + self.svg.set("width", str(width) + width_unit) + self.svg.set("height", str(height) + height_unit) + self.svg.set("viewBox", f"0 0 {width} {height}") + self.set_namedview(width_px, height_px, width_unit) + + def set_namedview(self, width, height, unit): + """Setup the document namedview""" + self.svg.namedview.set("inkscape:document-units", unit) + self.svg.namedview.set("inkscape:zoom", "0.25") + self.svg.namedview.set("inkscape:cx", str(width / 2.0)) + self.svg.namedview.set("inkscape:cy", str(height / 2.0)) + if self.options.grid: + self.svg.namedview.set("showgrid", "true") + self.svg.namedview.add(Grid(type="xygrid")) + + +class ColorExtension(EffectExtension): + """ + A standard way to modify colours in an svg document. + """ + + process_none = False # should we call modify_color for the "none" color. + select_all = (ShapeElement,) + pass_rgba = False + """ + If true, color and opacity are processed together (as RGBA color) + by :func:`modify_color`. + + If false (default), they are processed independently by `modify_color` and + `modify_opacity`. + + .. versionadded:: 1.2 + """ + + def __init__(self): + super().__init__() + self._renamed = {} + + def effect(self): + # Limiting to shapes ignores Gradients (and other things) from the select_all + # this prevents defs from being processed twice. + self._renamed = {} + gradients = CloningVat(self.svg) + for elem in self.svg.selection.get(ShapeElement): + self.process_element(elem, gradients) + gradients.process(self.process_elements, types=(ShapeElement,)) + + def process_elements(self, elem): + """Process multiple elements (gradients)""" + for child in elem.descendants(): + self.process_element(child) + + def process_element(self, elem, gradients=None): + """Process one of the selected elements""" + style = elem.specified_style() + # Colours first + for name in ( + elem.style.associated_props if self.pass_rgba else elem.style.color_props + ): + if name not in style: + continue # we don't want to process default values + try: + value = style(name) + except ColorError: + continue # bad color value, don't touch. + if isinstance(value, Color): + col = Color(value) + if self.pass_rgba: + col = col.to_rgba( + alpha=elem.style(elem.style.associated_props[name]) + ) + rgba_result = self._modify_color(name, col) + elem.style.set_color(rgba_result, name) + + if isinstance(value, (LinearGradient, RadialGradient, Pattern)): + gradients.track(value, elem, self._ref_cloned, style=style, name=name) + if value.href is not None: + gradients.track(value.href, elem, self._xlink_cloned, linker=value) + # Then opacities (usually does nothing) + if self.pass_rgba: + return + for name in elem.style.opacity_props: + value = style(name) + result = self.modify_opacity(name, value) + if result not in (value, 1): # only modify if not equal to old or default + elem.style[name] = result + + def _ref_cloned(self, old_id, new_id, style, name): + self._renamed[old_id] = new_id + style[name] = f"url(#{new_id})" + + def _xlink_cloned(self, old_id, new_id, linker): # pylint: disable=unused-argument + lid = linker.get("id") + linker = self.svg.getElementById(self._renamed.get(lid, lid)) + linker.set("xlink:href", "#" + new_id) + + def _modify_color(self, name, color): + """Pre-process color value to filter out bad colors""" + if color or self.process_none: + return self.modify_color(name, color) + return color + + def modify_color(self, name, color): + """Replace this method with your colour modifier method""" + raise NotImplementedError("Provide a modify_color method.") + + def modify_opacity( + self, name, opacity + ): # pylint: disable=no-self-use, unused-argument + """Optional opacity modification""" + return opacity + + +class TextExtension(EffectExtension): + """ + A base effect for changing text in a document. + """ + + newline = True + newpar = True + + def effect(self): + nodes = self.svg.selection or {None: self.document.getroot()} + for elem in nodes.values(): + self.process_element(elem) + + def process_element(self, node): + """Reverse the node text""" + if node.get("sodipodi:role") == "line": + self.newline = True + elif isinstance(node, (TextElement, FlowPara, FlowDiv)): + self.newline = True + self.newpar = True + + if node.text is not None: + node.text = self.process_chardata(node.text) + self.newline = False + self.newpar = False + + for child in node: + self.process_element(child) + + if node.tail is not None: + node.tail = self.process_chardata(node.tail) + + def process_chardata(self, text): + """Replaceable chardata method for processing the text""" + return "".join(map(self.map_char, text)) + + @staticmethod + def map_char(char): + """Replaceable map_char method for processing each letter""" + raise NotImplementedError( + "Please provide a process_chardata or map_char static method." + ) diff --git a/share/extensions/inkex/gui/README.md b/share/extensions/inkex/gui/README.md new file mode 100644 index 0000000..fb176da --- /dev/null +++ b/share/extensions/inkex/gui/README.md @@ -0,0 +1,15 @@ +# What is inkex.gui + +This module is a Gtk based GUI creator. It helps extensions launch their own user interfaces and can help make sure those interfaces will work on all platforms that inkscape ships with. + +# How do I use it + +You can create custom user interfaces by using the Gnome glade builder program. Once you have a layout of all th widgets you want, you then make a GtkApp and Window classes inside your python program, when the GtkApp is run, th windows will be shown to the user and all signals specified for the widgets will call functions on your window class. + +Please see the existing code for examples of how to do this. + +# This is a fork + +This code was originally part of the package 'gtkme' which contained some part we didn't want to ship. Such as ubuntu indicators and internet pixmaps. To avoid conflicts, our stripped down version of the gtkme module is renamed and placed inside of inkscape's inkex module. + + diff --git a/share/extensions/inkex/gui/__init__.py b/share/extensions/inkex/gui/__init__.py new file mode 100644 index 0000000..27e1b0b --- /dev/null +++ b/share/extensions/inkex/gui/__init__.py @@ -0,0 +1,50 @@ +# +# Copyright 2011-2022 Martin Owens +# +# 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 3 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, see +# +# pylint: disable=wrong-import-position +""" +This a wrapper layer to make interacting with Gtk a little less painful. +The main issues with Gtk is that it expects an aweful lot of the developer, +code which is repeated over and over and patterns which every single developer +will use are not given easy to use convience functions. + +This makes Gtk programming WET, unattractive and error prone. This module steps +inbetween and adds in all those missing bits. It's not meant to replace Gtk and +certainly it's possible to use Gtk and threading directly. + +.. versionadded:: 1.2 +""" + +import threading +import os +import logging + +from ..utils import DependencyError + +try: + import gi + + gi.require_version("Gtk", "3.0") +except ImportError: # pragma: no cover + raise DependencyError( + "You are missing the required libraries for Gtk." + " Please report this problem to the Inkscape developers." + ) + +from .app import GtkApp +from .window import Window, ChildWindow, FakeWidget +from .listview import TreeView, IconView, ViewColumn, ViewSort, Separator +from .pixmap import PixmapManager diff --git a/share/extensions/inkex/gui/app.py b/share/extensions/inkex/gui/app.py new file mode 100644 index 0000000..6b2a0ab --- /dev/null +++ b/share/extensions/inkex/gui/app.py @@ -0,0 +1,176 @@ +# coding=utf-8 +# +# Copyright 2011-2022 Martin Owens +# +# 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 3 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, see +# +""" +Gtk Application base classes, providing a way to load a GtkBuilder +with a specific glade/ui file conaining windows, and building +a usable pythonic interface from them. +""" +import os +import signal +import logging + +from gi.repository import Gtk, GLib + + +class GtkApp: + """ + This wraps gtk builder and allows for some extra functionality with + windows, especially the management of gtk main loops. + + Args: + start_loop (bool, optional): If set to true will start a new gtk main loop. + Defaults to False. + start_gui (bool, optional): Used as local propertes if unset and passed to + primary window when loaded. Defaults to True. + """ + + @property + def prefix(self): + """Folder prefix added to ui_dir""" + return self.kwargs.get("prefix", "") + + @property + def windows(self): + """Returns a list of windows for this app""" + return self.kwargs.get("windows", []) + + @property + def ui_dir(self): + """This is often the local directory""" + return self.kwargs.get("ui_dir", "./") + + @property + def ui_file(self): + """If a single file is used for multiple windows""" + return self.kwargs.get("ui_file", None) + + @property + def app_name(self): + """Set this variable in your class""" + try: + return self.kwargs["app_name"] + except KeyError: + raise NotImplementedError( + "App name is not set, pass in or set 'app_name' in class." + ) + + @property + def window(self): + """Return the primary window""" + return self._primary + + def __init__(self, start_loop=False, start_gui=True, **kwargs): + """Creates a new GtkApp.""" + self.kwargs = kwargs + self._loaded = {} + self._initial = {} + self._primary = None + + self.main_loop = GLib.main_depth() + + # Start with creating all the defined windows. + if start_gui: + self.init_gui() + # Start up a gtk main loop when requested + if start_loop: + self.run() + + def run(self): + """Run the gtk mainloop with ctrl+C and keyboard interupt additions""" + if not Gtk.init_check()[0]: # pragma: no cover + raise RuntimeError( + "Gtk failed to start." " Make sure $DISPLAY variable is set.\n" + ) + try: + # Add a signal to force quit on Ctrl+C (just like the old days) + signal.signal(signal.SIGINT, signal.SIG_DFL) + Gtk.main() + except KeyboardInterrupt: # pragma: no cover + logging.info("User Interputed") + logging.debug("Exiting %s", self.app_name) + + def get_ui_file(self, window): + """Load any given gtk builder file from a standard location.""" + paths = [ + os.path.join(self.ui_dir, self.prefix, f"{window}.ui"), + os.path.join(self.ui_dir, self.prefix, f"{self.ui_file}.ui"), + ] + for path in paths: + if os.path.isfile(path): + return path + raise FileNotFoundError(f"Gtk Builder file is missing: {paths}") + + def init_gui(self): + """Initalise all of our windows and load their signals""" + if self.windows: + for cls in self.windows: + window = cls + logging.debug("Adding window %s to GtkApp", window.name) + self._initial[window.name] = window + for window in self._initial.values(): + if window.primary: + if not self._primary: + self._primary = self.load_window(window.name) + if not self.windows or not self._primary: + raise KeyError(f"No primary window found for '{self.app_name}' app.") + + def load_window(self, name, *args, **kwargs): + """Load a specific window from our group of windows""" + window = self.proto_window(name) + window.init(*args, **kwargs) + return window + + def load_window_extract(self, name, **kwargs): + """Load a child window as a widget container""" + window = self.proto_window(name) + window.load_widgets(**kwargs) + return window.extract() + + def proto_window(self, name): + """ + Loads a glade window as a window without initialisation, used for + extracting widgets from windows without loading them as windows. + """ + logging.debug("Loading '%s' from %s", name, self._initial) + if name in self._initial: + # Create a new instance of this window + window = self._initial[name](self) + # Save the window object linked against the gtk window instance + self._loaded[window.wid] = window + return window + raise KeyError(f"Can't load window '{name}', class not found.") + + def remove_window(self, window): + """Remove the window from the list and exit if none remain""" + if window.wid in self._loaded: + self._loaded.pop(window.wid) + else: + logging.warning("Missing window '%s' on exit.", window.name) + logging.debug("Loaded windows: %s", self._loaded) + if not self._loaded: + self.exit() + + def exit(self): + """Exit our gtk application and kill gtk main if we have to""" + if self.main_loop < GLib.main_depth(): + # Quit Gtk loop if we started one. + tag = self._primary.name if self._primary else "program" + logging.debug("Quit '%s' Main Loop.", tag) + Gtk.main_quit() + # You have to return in order for the loop to exit + return 0 diff --git a/share/extensions/inkex/gui/asyncme.py b/share/extensions/inkex/gui/asyncme.py new file mode 100644 index 0000000..5011c17 --- /dev/null +++ b/share/extensions/inkex/gui/asyncme.py @@ -0,0 +1,330 @@ +# +# Copyright 2015 Ian Denhardt +# +# 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 3 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, see +# +"""Convienience library for concurrency + +GUI apps frequently need concurrency, for example to avoid blocking UI while +doing some long running computation. This module provides helpers for doing +this kind of thing. + +The functions/methods here which spawn callables asynchronously +don't supply a direct way to provide arguments. Instead, the user is +expected to use a lambda, e.g:: + + holding(lck, lambda: do_stuff(1,2,3, x='hello')) + +This is because the calling function may have additional arguments which +could obscure the user's ability to pass arguments expected by the called +function. For example, in the call:: + + holding(lck, lambda: run_task(blocking=True), blocking=False) + +the blocking argument to holding might otherwise conflict with the +blocking argument to run_task. +""" +import time +import threading +from datetime import datetime, timedelta + +from functools import wraps +from typing import Any, Tuple +from gi.repository import Gdk, GLib + + +class Future: + """A deferred result + + A `Future` is a result-to-be; it can be used to deliver a result + asynchronously. Typical usage: + + >>> def background_task(task): + ... ret = Future() + ... def _task(x): + ... return x - 4 + 2 + ... thread = threading.Thread(target=lambda: ret.run(lambda: _task(7))) + ... thread.start() + ... return ret + >>> # Do other stuff + >>> print(ret.wait()) + 5 + + :func:`run` will also propogate exceptions; see it's docstring for details. + """ + + def __init__(self): + self._lock = threading.Lock() + self._value = None + self._exception = None + self._lock.acquire() + + def is_ready(self): + """Return whether the result is ready""" + result = self._lock.acquire(False) + if result: + self._lock.release() + return result + + def wait(self): + """Wait for the result. + + `wait` blocks until the result is ready (either :func:`result` or + :func:`exception` has been called), and then returns it (in the case + of :func:`result`), or raises it (in the case of :func:`exception`). + """ + with self._lock: + if self._exception is None: + return self._value + else: + raise self._exception # pylint: disable=raising-bad-type + + def result(self, value): + """Supply the result as a return value. + + ``value`` is the result to supply; it will be returned when + :func:`wait` is called. + """ + self._value = value + self._lock.release() + + def exception(self, err): + """Supply an exception as the result. + + Args: + err (Exception): an exception, which will be raised when :func:`wait` + is called. + """ + self._exception = err + self._lock.release() + + def run(self, task): + """Calls task(), and supplies the result. + + If ``task`` raises an exception, pass it to :func:`exception`. + Otherwise, pass the return value to :func:`result`. + """ + try: + self.result(task()) + except Exception as err: # pylint: disable=broad-except + self.exception(err) + + +class DebouncedSyncVar: + """A synchronized variable, which debounces its value + + :class:`DebouncedSyncVar` supports three operations: put, replace, and get. + get will only retrieve a value once it has "settled," i.e. at least + a certain amount of time has passed since the last time the value + was modified. + """ + + def __init__(self, delay_seconds=0): + """Create a new dsv with the supplied delay, and no initial value.""" + self._cv = threading.Condition() + self._delay = timedelta(seconds=delay_seconds) + + self._deadline = None + self._value = None + + self._have_value = False + + def set_delay(self, delay_seconds): + """Set the delay in seconds of the debounce.""" + with self._cv: + self._delay = timedelta(seconds=delay_seconds) + + def get(self, blocking=True, remove=True) -> Tuple[Any, bool]: + """Retrieve a value. + + Args: + blocking (bool, optional): if True, block until (1) the dsv has a value + and (2) the value has been unchanged for an amount of time greater + than or equal to the dsv's delay. Otherwise, if these conditions + are not met, return ``(None, False)`` immediately. Defaults to True. + remove (bool, optional): if True, remove the value when returning it. + Otherwise, leave it where it is.. Defaults to True. + + Returns: + Tuple[Any, bool]: Tuple (value, ok). ``value`` is the value of the variable + (if successful, see above), and ok indicates whether or not a value was + successfully retrieved. + """ + while True: + with self._cv: + + # If there's no value, either wait for one or return + # failure. + while not self._have_value: + if blocking: + self._cv.wait() + else: + return None, False # pragma: no cover + + now = datetime.now() + deadline = self._deadline + value = self._value + if deadline <= now: + # Okay, we're good. Remove the value if necessary, and + # return it. + if remove: + self._have_value = False + self._value = None + self._cv.notify() + return value, True + + # Deadline hasn't passed yet. Either wait or return failure. + if blocking: + time.sleep((deadline - now).total_seconds()) + else: + return None, False # pragma: no cover + + def replace(self, value): + """Replace the current value of the dsv (if any) with ``value``. + + replace never blocks (except briefly to aquire the lock). It does not + wait for any unit of time to pass (though it does reset the timer on + completion), nor does it wait for the dsv's value to appear or + disappear. + """ + with self._cv: + self._replace(value) + + def put(self, value): + """Set the dsv's value to ``value``. + + If the dsv already has a value, this blocks until the value is removed. + Upon completion, this resets the timer. + """ + with self._cv: + while self._have_value: + self._cv.wait() + self._replace(value) + + def _replace(self, value): + self._have_value = True + self._value = value + self._deadline = datetime.now() + self._delay + self._cv.notify() + + +def spawn_thread(func): + """Call ``func()`` in a separate thread + + Returns the corresponding :class:`threading.Thread` object. + """ + thread = threading.Thread(target=func) + thread.start() + return thread + + +def in_mainloop(func): + """Run f() in the gtk main loop + + Returns a :class:`Future` object which can be used to retrieve the return + value of the function call. + + :func:`in_mainloop` exists because Gtk isn't threadsafe, and therefore cannot be + manipulated except in the thread running the Gtk main loop. :func:`in_mainloop` + can be used by other threads to manipulate Gtk safely. + """ + future = Future() + + def handler(*_args, **_kwargs): + """Function to be called in the future""" + future.run(func) + + Gdk.threads_add_idle(0, handler, None) + return future + + +def mainloop_only(f): + """A decorator which forces a function to only be run in Gtk's main loop. + + Invoking a decorated function as ``f(*args, **kwargs)`` is equivalent to + using the undecorated function (from a thread other than the one running + the Gtk main loop) as:: + + in_mainloop(lambda: f(*args, **kwargs)).wait() + + :func:`mainloop_only` should be used to decorate functions which are unsafe + to run outside of the Gtk main loop. + """ + + @wraps(f) + def wrapper(*args, **kwargs): + if GLib.main_depth(): + # Already in a mainloop, so just run it. + return f(*args, **kwargs) + return in_mainloop(lambda: f(*args, **kwargs)).wait() + + return wrapper + + +def holding(lock, task, blocking=True): + """Run task() while holding ``lock``. + + Args: + blocking (bool, optional): if True, wait for the lock before running. + Otherwise, if the lock is busy, return None immediately, and don't + spawn `task`. Defaults to True. + + Returns: + Union[Future, None]: The return value is a future which can be used to retrieve + the result of running task (or None if the task was not run). + """ + if not lock.acquire(False): + return None + ret = Future() + + def _target(): + ret.run(task) + if ret._exception: # pragma: no cover + ret.wait() + lock.release() + + threading.Thread(target=_target).start() + return ret + + +def run_or_wait(func): + """A decorator which runs the function using :func:`holding` + + This function creates a single lock for this function and + waits for the lock to release before returning. + + See :func:`holding` above, with ``blocking=True`` + """ + lock = threading.Lock() + + def _inner(*args, **kwargs): + return holding(lock, lambda: func(*args, **kwargs), blocking=True) + + return _inner + + +def run_or_none(func): + """A decorator which runs the function using :func:`holding` + + This function creates a single lock for this function and + returns None if the process is already running (locked) + + See :func:`holding` above with ``blocking=True`` + """ + lock = threading.Lock() + + def _inner(*args, **kwargs): + return holding(lock, lambda: func(*args, **kwargs), blocking=False) + + return _inner diff --git a/share/extensions/inkex/gui/listview.py b/share/extensions/inkex/gui/listview.py new file mode 100644 index 0000000..56939e7 --- /dev/null +++ b/share/extensions/inkex/gui/listview.py @@ -0,0 +1,562 @@ +# +# Copyright 2011-2022 Martin Owens +# +# 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 3 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, see +# +""" +Wraps the gtk treeview and iconview in something a little nicer. +""" + +import logging + +from typing import Tuple, Type, Optional +from gi.repository import Gtk, Gdk, GObject, GdkPixbuf, Pango + +from .pixmap import PixmapManager, SizeFilter + +GOBJ = GObject.TYPE_PYOBJECT + + +def default(item, attr, d=None): + """Python logic to choose an attribute, call it if required and return""" + if hasattr(item, attr): + prop = getattr(item, attr) + if callable(prop): + prop = prop() + return prop + return d + + +def cmp(a, b): + """Compare two objects""" + return (a > b) - (a < b) + + +def item_property(name, d=None): + def inside(item): + return default(item, name, d) + + return inside + + +def label(obj): + if isinstance(obj, tuple): + return " or ".join([label(o) for o in obj]) + if not isinstance(obj, type): + obj = type(obj) + return obj.__name__ + + +class BaseView: + """Controls for tree and icon views, a base class""" + + widget_type: Optional[Type[Gtk.Widget]] = None + + def __init__(self, widget, liststore=None, **kwargs): + if not isinstance(widget, self.widget_type): + lbl1 = label(self.widget_type) + lbl2 = label(widget) + raise TypeError(f"Wrong widget type: Expected {lbl1} got {lbl2}") + + self.selected_signal = kwargs.get("selected", None) + self._iids = [] + self._list = widget + self.args = kwargs + self.selected = None + self._data = None + self.no_dupes = True + self._model = self.create_model(liststore or widget.get_model()) + self._list.set_model(self._model) + self.setup() + + self._list.connect(self.changed_signal, self.item_selected_signal) + + def get_model(self): + """Returns the current data store model""" + return self._model + + def create_model(self, liststore): + """Setup the model and list""" + if not isinstance(liststore, (Gtk.ListStore, Gtk.TreeStore)): + lbl = label(liststore) + raise TypeError(f"Expected List or TreeStore, got {lbl}") + return liststore + + def refresh(self): + """Attempt to refresh the listview""" + self._list.queue_draw() + + def setup(self): + """Setup columns, views, sorting etc""" + pass + + def get_item_id(self, item): + """ + Return an id set against this item. + + If item.get_id() is set then duplicates will be ignored. + """ + if hasattr(item, "get_id"): + return item.get_id() + return None + + def replace(self, new_item, item_iter=None): + """Replace all items, or a single item with object""" + if item_iter: + self.remove_item(item_iter) + self.add_item(new_item) + else: + self.clear() + self._data = new_item + self.add_item(new_item) + + def item_selected(self, item=None, *others): + """Base method result, called as an item is selected""" + if self.selected != item: + self.selected = item + if self.selected_signal and item: + self.selected_signal(item) + + def remove_item(self, item=None): + """Remove an item from this view""" + return self._model.remove(self.get_iter(item)) + + def check_item_id(self, item): + """Item id is recorded to guard against duplicates""" + iid = self.get_item_id(item) + if iid in self._iids and self.no_dupes: + raise ValueError(f"Will not add duplicate row {iid}") + if iid: + self._iids.append(iid) + + def __iter__(self): + ret = [] + + def collect_all(store, treepath, treeiter): + ret.append((self.get_item(treeiter), treepath, treeiter)) + + self._model.foreach(collect_all) + return ret.__iter__() + + def set_sensitive(self, sen=True): + """Proxy the GTK property for sensitivity""" + self._list.set_sensitive(sen) + + def clear(self): + """Clear all items from this treeview""" + self._iids = [] + self._model.clear() + + def item_double_clicked(self, *items): + """What happens when you double click an item""" + return items # Nothing + + def get_item(self, item_iter): + """Return the object of attention from an iter""" + return self._model[self.get_iter(item_iter)][0] + + def get_iter(self, item, path=False): + """Return the iter given the item""" + if isinstance(item, Gtk.TreePath): + return item if path else self._model.get_iter(item) + if isinstance(item, Gtk.TreeIter): + return self._model.get_path(item) if path else item + for src_item, src_path, src_iter in self: + if item == src_item: + return src_path if path else src_iter + return None + + +class TreeView(BaseView): + """Controls and operates a tree view.""" + + column_size = 16 + widget_type = Gtk.TreeView + changed_signal = "cursor_changed" + + def setup(self): + """Setup the treeview""" + self._sel = self._list.get_selection() + self._sel.set_mode(Gtk.SelectionMode.MULTIPLE) + self._list.connect("button-press-event", self.item_selected_signal) + # Separators should do something + self._list.set_row_separator_func(TreeView.is_separator, None) + super().setup() + + @staticmethod + def is_separator(model, item_iter, data): + """Internal function for seperator checking""" + return isinstance(model.get_value(item_iter, 0), Separator) + + def get_selected_items(self): + """Return a list of selected item objects""" + return [self.get_item(row) for row in self._sel.get_selected_rows()[1]] + + def set_selected_items(self, *items): + """Select the given items""" + self._sel.unselect_all() + for item in items: + path_item = self.get_iter(item, path=True) + if path_item is not None: + self._sel.select_path(path_item) + + def is_selected(self, item): + """Return true if the item is selected""" + return self._sel.iter_is_selected(self.get_iter(item)) + + def add(self, target, parent=None): + """Add all items from the target to the treeview""" + for item in target: + self.add_item(item, parent=parent) + + def add_item(self, item, parent=None): + """Add a single item image to the control, returns the TreePath""" + if item is not None: + self.check_item_id(item) + return self._add_item([item], self.get_iter(parent)) + raise ValueError("Item can not be None.") + + def _add_item(self, item, parent): + return self.get_iter(self._model.append(parent, item), path=True) + + def item_selected_signal(self, *args, **kwargs): + """Signal for selecting an item""" + return self.item_selected(*self.get_selected_items()) + + def item_button_clicked(self, _, event): + """Signal for mouse button click""" + if event is None or event.type == Gdk.EventType._2BUTTON_PRESS: + self.item_double_clicked(*self.get_selected_items()) + + def expand_item(self, item, expand=True): + """Expand one of our nodes""" + self._list.expand_row(self.get_iter(item, path=True), expand) + + def create_model(self, liststore=None): + """Set up an icon view for showing gallery images""" + if liststore is None: + liststore = Gtk.TreeStore(GOBJ) + return super().create_model(liststore) + + def create_column(self, name, expand=True): + """ + Create and pack a new column to this list. + + name - Label in the column header + expand - Should the column expand + """ + return ViewColumn(self._list, name, expand=expand) + + def create_sort(self, *args, **kwargs): + """ + Create and attach a sorting view to this list. + + see ViewSort arguments for details. + """ + return ViewSort(self._list, *args, **kwargs) + + +class ComboBox(TreeView): + """Controls and operates a combo box list.""" + + widget_type = Gtk.ComboBox + changed_signal = "changed" + + def setup(self): + pass + + def get_selected_item(self): + """Return the selected item of this combo box""" + return self.get_item(self._list.get_active_iter()) + + def set_selected_item(self, item): + """Set the given item as the selected item""" + self._list.set_active_iter(self.get_iter(item)) + + def is_selected(self, item): + """Returns true if this item is the selected item""" + return self.get_selected_item() == item + + def get_selected_items(self): + """Return a list of selected items (one)""" + return [self.get_selected_item()] + + +class IconView(BaseView): + """Allows a simpler IconView for DBus List Objects""" + + widget_type = Gtk.IconView + changed_signal = "selection-changed" + + def __init__(self, widget, pixmaps, *args, **kwargs): + super().__init__(widget, *args, **kwargs) + self.pixmaps = pixmaps + + def set_selected_item(self, item): + """Sets the selected item to this item""" + path = self.get_iter(item, path=True) + if path: + self._list.set_cursor(path, None, False) + + def get_selected_items(self): + """Return the seleced item""" + return [self.get_item(path) for path in self._list.get_selected_items()] + + def create_model(self, liststore): + """Setup the icon view control and model""" + if not liststore: + liststore = Gtk.ListStore(GOBJ, str, GdkPixbuf.Pixbuf) + return super().create_model(liststore) + + def setup(self): + """Setup the columns for the iconview""" + self._list.set_markup_column(1) + self._list.set_pixbuf_column(2) + super().setup() + + def add(self, target): + """Add all items from the target to the iconview""" + for item in target: + self.add_item(item) + + def add_item(self, item): + """Add a single item image to the control""" + if item is not None: + self.check_item_id(item) + return self._add_item(item) + raise ValueError("Item can not be None.") + + def get_markup(self, item): + """Default text return for markup.""" + return default(item, "name", str(item)) + + def get_icon(self, item): + """Default icon return, pixbuf or gnome theme name""" + return default(item, "icon", None) + + def _get_icon(self, item): + return self.pixmaps.get(self.get_icon(item), item=item) + + def _add_item(self, item): + """ + Each item's properties must be stuffed into the ListStore directly + or the IconView won't see them, but only if on auto. + """ + if not isinstance(item, (tuple, list)): + item = [item, self.get_markup(item), self._get_icon(item)] + return self._model.append(item) + + def item_selected_signal(self, *args, **kwargs): + """Item has been selected""" + return self.item_selected(*self.get_selected_items()) + + +class ViewSort(object): + """ + A sorting function for use is ListViews + + ascending - Boolean which direction to sort + contains - Contains this string + data - A string or function to get data from each item. + exact - Compare to this exact string instead. + """ + + def __init__(self, widget, data=None, ascending=False, exact=None, contains=None): + self.tree = None + self.data = data + self.asc = ascending + self.comp = exact.lower() if exact else None + self.cont = contains + self.tree = widget + self.resort() + + def get_data(self, model, list_iter): + """Generate sortable data from the item""" + item = model.get_value(list_iter, 0) + if isinstance(self.data, str): + value = getattr(item, self.data) + elif callable(self.data): + value = self.data(item) + return value + + def sort_func(self, model, iter1, iter2, data): + """Called by Gtk to sort items""" + value1 = self.get_data(model, iter1) + value2 = self.get_data(model, iter2) + if value1 == None or value2 == None: + return 0 + if self.comp: + if cmp(self.comp, value1.lower()) == 0: + return 1 + elif cmp(self.comp, value2.lower()) == 0: + return -1 + return 0 + elif self.cont: + if self.cont in value1.lower(): + return 1 + elif self.cont in value2.lower(): + return -1 + return 0 + if value1 < value2: + return 1 + if value2 < value1: + return -1 + return 0 + + def resort(self): + model = self.tree.get_model() + model.set_sort_func(0, self.sort_func, None) + if self.asc: + model.set_sort_column_id(0, Gtk.SortType.ASCENDING) + else: + model.set_sort_column_id(0, Gtk.SortType.DESCENDING) + + +class ViewColumn(object): + """ + Add a column to a gtk treeview. + + name - The column name used as a label. + expand - Set column expansion. + """ + + def __init__(self, widget, name, expand=False): + if isinstance(widget, Gtk.TreeView): + column = Gtk.TreeViewColumn((name)) + column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + column.set_expand(expand) + self._column = column + widget.append_column(self._column) + else: + # Deal with possible drop down lists + self._column = widget + + def add_renderer(self, renderer, func, expand=True): + """Set a custom renderer""" + self._column.pack_start(renderer, expand) + self._column.set_cell_data_func(renderer, func, None) + return renderer + + def add_image_renderer(self, icon, pad=0, pixmaps=None, size=None): + """ + Set the image renderer + + icon - The function that returns the image to be dsplayed. + pad - The amount of padding around the image. + pixmaps - The pixmap manager to use to get images. + size - Restrict the images to this size. + """ + # Manager where icons will be pulled from + filters = [SizeFilter] if size else [] + pixmaps = pixmaps or PixmapManager( + "", pixmap_dir="./", filters=filters, size=size + ) + + renderer = Gtk.CellRendererPixbuf() + renderer.set_property("ypad", pad) + renderer.set_property("xpad", pad) + func = self.image_func(icon or self.default_icon, pixmaps) + return self.add_renderer(renderer, func, expand=False) + + def add_text_renderer(self, text, wrap=None, template=None): + """ + Set the text renderer. + + text - the function that returns the text to be displayed. + wrap - The wrapping setting for this renderer. + template - A standard template used for this text markup. + """ + + renderer = Gtk.CellRendererText() + if wrap is not None: + renderer.props.wrap_width = wrap + renderer.props.wrap_mode = Pango.WrapMode.WORD + + renderer.props.background_set = True + renderer.props.foreground_set = True + + func = self.text_func(text or self.default_text, template) + return self.add_renderer(renderer, func, expand=True) + + @classmethod + def clean(cls, text, markup=False): + """Clean text of any pango markup confusing chars""" + if text is None: + text = "" + if isinstance(text, (str, int, float)): + if markup: + text = str(text).replace("<", "<").replace(">", ">") + return str(text).replace("&", "&") + elif isinstance(text, dict): + return dict([(k, cls.clean(v)) for k, v in text.items()]) + elif isinstance(text, (list, tuple)): + return tuple([cls.clean(value) for value in text]) + raise TypeError("Unknown value type for text: %s" % str(type(text))) + + def get_callout(self, call, default=None): + """Returns the right kind of method""" + if isinstance(call, str): + call = item_property(call, default) + return call + + def text_func(self, call, template=None): + """Wrap up our text functionality""" + callout = self.get_callout(call) + + def internal(column, cell, model, item_iter, data): + if TreeView.is_separator(model, item_iter, data): + return + item = model.get_value(item_iter, 0) + markup = template is not None + text = callout(item) + if isinstance(template, str): + text = template.format(self.clean(text, markup=True)) + else: + text = self.clean(text) + cell.set_property("markup", str(text)) + + return internal + + def image_func(self, call, pixmaps=None): + """Wrap, wrap wrap the func""" + callout = self.get_callout(call) + + def internal(column, cell, model, item_iter, data): + if TreeView.is_separator(model, item_iter, data): + return + item = model.get_value(item_iter, 0) + icon = callout(item) + # The or blank asks for the default icon from the pixmaps + if isinstance(icon or "", str) and pixmaps: + # Expect a Gnome theme icon + icon = pixmaps.get(icon) + elif icon: + icon = pixmaps.apply_filters(icon) + + cell.set_property("pixbuf", icon) + cell.set_property("visible", True) + + return internal + + def default_text(self, item): + """Default text return for markup.""" + return default(item, "name", str(item)) + + def default_icon(self, item): + """Default icon return, pixbuf or gnome theme name""" + return default(item, "icon", None) + + +class Separator: + """Reprisentation of a separator in a list""" diff --git a/share/extensions/inkex/gui/pixmap.py b/share/extensions/inkex/gui/pixmap.py new file mode 100644 index 0000000..02f4ce8 --- /dev/null +++ b/share/extensions/inkex/gui/pixmap.py @@ -0,0 +1,346 @@ +# +# Copyright 2011-2022 Martin Owens +# +# 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 3 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, see +# +""" +Provides wrappers for pixmap access. +""" + +import os +import logging + +from typing import List +from collections.abc import Iterable +from gi.repository import Gtk, GLib, GdkPixbuf + +ICON_THEME = Gtk.IconTheme.get_default() +BILINEAR = GdkPixbuf.InterpType.BILINEAR +HYPER = GdkPixbuf.InterpType.HYPER + +SIZE_ASPECT = 0 +SIZE_ASPECT_GROW = 1 +SIZE_ASPECT_CROP = 2 +SIZE_STRETCH = 3 + + +class PixmapLoadError(ValueError): + """Failed to load a pixmap""" + + +class PixmapFilter: # pylint: disable=too-few-public-methods + """Base class for filtering the pixmaps in a manager's output. + + required - List of values required for this filter. + + Use: + + class Foo(PixmapManager): + filters = [ PixmapFilterFoo ] + + """ + + required: List[str] = [] + optional: List[str] = [] + + def __init__(self, **kwargs): + self.enabled = True + for key in self.required: + if key not in kwargs: + self.enabled = False + else: + setattr(self, key, kwargs[key]) + + for key in self.optional: + if key in kwargs: + setattr(self, key, kwargs[key]) + + def filter(self, img, **kwargs): + """Run filter, replace this methodwith your own""" + raise NotImplementedError( + "Please add 'filter' method to your PixmapFilter class %s." + % type(self).__name__ + ) + + @staticmethod + def to_size(dat): + """Tries to calculate a size that will work for the data""" + if isinstance(dat, (int, float)): + return (dat, dat) + if isinstance(dat, Iterable) and len(dat) >= 2: + return (dat[0], dat[1]) + return None + + +class OverlayFilter(PixmapFilter): + """Adds an overlay to output images, overlay can be any name that + the owning pixmap manager can find. + + overlay : Name of overlay image + position : Location of the image: + 0 - Full size (1 to 1 overlay, default) + (x,y) - Percentage from one end to the other position 0-1 + alpha : Blending alpha, 0 - 255 + + """ + + optional = ["position", "overlay", "alpha"] + + def __init__(self, *args, **kwargs): + self.position = (0, 0) + self.overlay = None + self.alpha = 255 + super().__init__(*args, **kwargs) + self.pad_x, self.pad_y = self.to_size(self.position) + + def get_overlay(self, **kwargs): + if "manager" not in kwargs: + raise ValueError("PixmapManager must be provided when adding an overlay.") + return kwargs["manager"].get( + kwargs.get("overlay", None) or self.overlay, no_overlay=True + ) + + def filter(self, img, no_overlay=False, **kwargs): + # Recursion protection + if no_overlay: + return img + + overlay = self.get_overlay(**kwargs) + if overlay: + img = img.copy() + + (x, y, width, height) = self.set_position(overlay, img) + overlay.composite( + img, x, y, width, height, x, y, 1, 1, BILINEAR, self.alpha + ) + return img + + def set_position(self, overlay, img): + """Sets the position of img on the given width and height""" + img_w, img_h = img.get_width(), img.get_height() + ovl_w, ovl_h = overlay.get_width(), overlay.get_height() + return ( + max([0, (img_w - ovl_w) * self.pad_x]), + max([0, (img_h - ovl_h) * self.pad_y]), + min([ovl_w, img_w]), + min([ovl_h, img_h]), + ) + + +class SizeFilter(PixmapFilter): + """Resizes images to a certain size: + + resize_mode - Way in which the size is calculated + 0 - Best Aspect, don't grow + 1 - Best Aspect, grow + 2 - Cropped Aspect + 3 - Stretch + """ + + required = ["size"] + optional = ["resize_mode"] + + def __init__(self, *args, **kwargs): + self.size = None + self.resize_mode = SIZE_ASPECT + super().__init__(*args, **kwargs) + self.img_w, self.img_h = self.to_size(self.size) or (0, 0) + + def aspect(self, img_w, img_h): + """Get the aspect ratio of the image resized""" + if self.resize_mode == SIZE_STRETCH: + return (self.img_w, self.img_h) + + if ( + self.resize_mode == SIZE_ASPECT + and img_w < self.img_w + and img_h < self.img_h + ): + return (img_w, img_h) + (pcw, pch) = (self.img_w / img_w, self.img_h / img_h) + factor = ( + max(pcw, pch) if self.resize_mode == SIZE_ASPECT_CROP else min(pcw, pch) + ) + return (int(img_w * factor), int(img_h * factor)) + + def filter(self, img, **kwargs): + if self.size is not None: + (width, height) = self.aspect(img.get_width(), img.get_height()) + return img.scale_simple(width, height, HYPER) + return img + + +class PadFilter(SizeFilter): + """Add padding to the image to make it a standard size""" + + optional = ["padding"] + + def __init__(self, *args, **kwargs): + self.size = None + self.padding = 0.5 + super().__init__(*args, **kwargs) + self.pad_x, self.pad_y = self.to_size(self.padding) + + def filter(self, img, **kwargs): + (width, height) = (img.get_width(), img.get_height()) + if width < self.img_w or height < self.img_h: + target = GdkPixbuf.Pixbuf.new( + img.get_colorspace(), + True, + img.get_bits_per_sample(), + max([width, self.img_w]), + max([height, self.img_h]), + ) + target.fill(0x0) # Transparent black + + x = (target.get_width() - width) * self.pad_x + y = (target.get_height() - height) * self.pad_y + + img.composite(target, x, y, width, height, x, y, 1, 1, BILINEAR, 255) + return target + return img + + +class PixmapManager: + """Manage a set of cached pixmaps, returns the default image + if it can't find one or the missing image if that's available.""" + + missing_image = "image-missing" + default_image = "application-default-icon" + icon_theme = ICON_THEME + theme_size = 32 + filters: List[type] = [] + pixmap_dir = None + + def __init__(self, location="", **kwargs): + self.location = location + if self.pixmap_dir and not os.path.isabs(location): + self.location = os.path.join(self.pixmap_dir, location) + + self.loader_size = PixmapFilter.to_size(kwargs.pop("load_size", None)) + + # Add any instance specified filters first + self._filters = [] + for item in kwargs.get("filters", []) + self.filters: + if isinstance(item, PixmapFilter): + self._filters.append(item) + elif callable(item): + # Now add any class specified filters with optional kwargs + self._filters.append(item(**kwargs)) + + self.cache = {} + self.get_pixmap(self.default_image) + + def get(self, *args, **kwargs): + """Get a pixmap of any kind""" + return self.get_pixmap(*args, **kwargs) + + def get_missing_image(self): + """Get a missing image when other images aren't found""" + return self.get(self.missing_image) + + @staticmethod + def data_is_file(data): + """Test the file to see if it's a filename or not""" + return isinstance(data, str) and " +# +# 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 3 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, see +# +""" +Structures for consistant testing of Gtk GUI programs. +""" + +import sys +from gi.repository import Gtk, GLib + + +class MainLoopProtection: + """ + This protection class provides a way to launch the Gtk mainloop in a test + friendly way. + + Exception handling hooks provide a way to see errors that happen + inside the main loop, raising them back to the caller. + A full timeout in seconds stops the gtk mainloop from operating + beyond a set time, acting as a kill switch in the event something + has gone horribly wrong. + + Use: + with MainLoopProtection(timeout=10s): + app.run() + """ + + def __init__(self, timeout=10): + self.timeout = timeout * 1000 + self._hooked = None + self._old_excepthook = None + + def __enter__(self): + # replace sys.excepthook with our own and remember hooked raised error + self._old_excepthook = sys.excepthook + sys.excepthook = self.excepthook + # Remove mainloop by force if it doesn't die within 10 seconds + self._timeout = GLib.timeout_add(self.timeout, self.idle_exit) + + def __exit__(self, exc, value, traceback): # pragma: no cover + """Put the except handler back, cancel the timer and raise if needed""" + if self._old_excepthook: + sys.excepthook = self._old_excepthook + # Remove the timeout, so we don't accidentally kill later mainloops + if self._timeout: + GLib.source_remove(self._timeout) + # Raise an exception if one happened during the test run + if self._hooked: + exc, value, traceback = self._hooked + if value and traceback: + raise value.with_traceback(traceback) + + def idle_exit(self): # pragma: no cover + """Try to going to kill any running mainloop.""" + GLib.idle_add(Gtk.main_quit) + + def excepthook(self, ex_type, ex_value, traceback): # pragma: no cover + """Catch errors thrown by the Gtk mainloop""" + self.idle_exit() + # Remember the exception data for raising inside the test context + if ex_value is not None: + self._hooked = [ex_type, ex_value, traceback] + # Fallback and double print the exception (remove if double printing is problematic) + return self._old_excepthook(ex_type, ex_value, traceback) diff --git a/share/extensions/inkex/gui/window.py b/share/extensions/inkex/gui/window.py new file mode 100644 index 0000000..a5c1ef6 --- /dev/null +++ b/share/extensions/inkex/gui/window.py @@ -0,0 +1,201 @@ +# +# Copyright 2012-2022 Martin Owens +# +# 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 3 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, see +# +# pylint: disable=too-many-instance-attributes +""" +Wraps the gtk windows with something a little nicer. +""" +import logging + +from gi.repository import Gtk + +PROPS = { + "Box": ["expand", "fill", "padding", "pack-type"], + "Grid": ["top-attach", "left-attach", "height", "width"], + "Table": ["top-attach", "left-attach", "bottom-attach", "right-attach"], +} + + +def protect(cls, *methods): + """Simple check for protecting an inherrited class from having + certain methods over-ridden""" + if not isinstance(cls, type): + cls = type(cls) + for method in methods: + if method in cls.__dict__: # pragma: no cover + raise RuntimeError( + f"{cls.__name__} in {cls.__module__} has" f" protected def {method}()" + ) + + +class Window: + """ + This wraps gtk windows and allows for having parent windows + + name = 'name-of-the-window' + + Should the window be the first loaded and end gtk when closed: + + primary = True/False + """ + + primary = True + name = None + + def __init__(self, gapp): + self.gapp = gapp + self.dead = False + self.parent = None + self.args = () + ui_file = gapp.get_ui_file(self.name) + + # Setup the gtk app connection + self.w_tree = Gtk.Builder() + self.widget = self.w_tree.get_object + self.w_tree.set_translation_domain(gapp.app_name) + self.w_tree.add_from_file(ui_file) + + # Setup the gtk builder window + self.window = self.widget(self.name) + if not self.window: # pragma: no cover + raise KeyError(f"Missing window widget '{self.name}' from '{ui_file}'") + + # Give us a window id to track this window + self.wid = str(hash(self.window)) + + def extract(self): + """Extract this window's container for use in other apps""" + for child in self.window.get_children(): + self.window.remove(child) + return child + + def init(self, parent=None, **kwargs): + """Initialise the window within the GtkApp""" + if "replace" not in kwargs: + protect(self, "destroy", "exit", "load_window", "proto_window") + self.args = kwargs + # Set object defaults + self.parent = parent + + self.w_tree.connect_signals(self) + + # These are some generic convience signals + self.window.connect("destroy", self.exit) + + # If we have a parent window, then we expect not to quit + if self.parent: + self.window.set_transient_for(self.parent) + self.parent.set_sensitive(False) + + # We may have some more gtk widgets to setup + self.load_widgets(**self.args) + self.window.show() + + def load_window(self, name, *args, **kwargs): + """Load child window, automatically sets parent""" + kwargs["parent"] = self.window + return self.gapp.load_window(name, *args, **kwargs) + + def load_widgets(self): + """Child class should use this to create widgets""" + + def destroy(self, widget=None): # pylint: disable=unused-argument + """Destroy the window""" + logging.debug("Destroying Window '%s'", self.name) + self.window.destroy() + # We don't need to call self.exit(), handeled by window event. + + def pre_exit(self): + """Internal method for what to do when the window has died""" + + def exit(self, widget=None): + """Called when the window needs to exit.""" + # Is the signal called by the window or by something else? + if not widget or not isinstance(widget, Gtk.Window): + self.destroy() + # Clean up any required processes + self.pre_exit() + if self.parent: + # We assume the parent didn't load another gtk loop + self.parent.set_sensitive(True) + # Exit our entire app if this is the primary window + # Or just remove from parent window list, which may still exit. + if self.primary: + logging.debug("Exiting the application") + self.gapp.exit() + else: + logging.debug("Removing Window %s from parent", self.name) + self.gapp.remove_window(self) + # Now finish up what ever is left to do now the window is dead. + self.dead = True + self.post_exit() + return widget + + def post_exit(self): + """Called after we've killed the window""" + + def if_widget(self, name): + """ + Attempt to get the widget from gtk, but if not return a fake that won't + cause any trouble if we don't further check if it's real. + """ + return self.widget(name) or FakeWidget(name) + + def replace(self, old, new): + """Replace the old widget with the new widget""" + if isinstance(old, str): + old = self.widget(old) + if isinstance(new, str): + new = self.widget(new) + target = old.get_parent() + source = new.get_parent() + if target is not None: + if source is not None: + source.remove(new) + target.remove(old) + target.add(new) + + @staticmethod + def get_widget_name(obj): + """Return the widget's name in the builder file""" + return Gtk.Buildable.get_name(obj) + + +class ChildWindow(Window): + """ + Base class for child window objects, these child windows are typically + window objects in the same gtk builder file as their parents. If you just want + to make a window that interacts with a parent window, use the normal + Window class and call with the optional parent attribute. + """ + + primary = False + + +class FakeWidget: + """A fake widget class that can take calls""" + + def __init__(self, name): + self._name = name + + def __getattr__(self, name): + def _fake(*args, **kwargs): + logging.info("Calling fake method: %s:%s", args, kwargs) + + return _fake + + def __bool__(self): + return False diff --git a/share/extensions/inkex/interfaces/IElement.py b/share/extensions/inkex/interfaces/IElement.py new file mode 100644 index 0000000..3e9df53 --- /dev/null +++ b/share/extensions/inkex/interfaces/IElement.py @@ -0,0 +1,39 @@ +"""Element abstractions for type comparisons without circular imports + +.. versionadded:: 1.2""" + +from __future__ import annotations + +from abc import ABC, abstractmethod + +import sys +from lxml import etree + +if sys.version_info >= (3, 8): + from typing import Protocol +else: + from typing_extensions import Protocol + + +class IBaseElement(ABC, etree.ElementBase): + """Abstraction for BaseElement to avoid circular imports""" + + @abstractmethod + def get_id(self, as_url=0): + """Returns the element ID. If not set, generates a unique ID.""" + raise NotImplementedError + + +class BaseElementProtocol(Protocol): + """Abstraction for BaseElement, to be used as typehint in mixin classes""" + + def get_id(self, as_url=0) -> str: + """Returns the element ID. If not set, generates a unique ID.""" + + @property + def root(self) -> ISVGDocumentElement: + """Returns the element's root.""" + + +class ISVGDocumentElement(IBaseElement): + """Abstraction for SVGDocumentElement""" diff --git a/share/extensions/inkex/interfaces/__init__.py b/share/extensions/inkex/interfaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/inkex/inx.py b/share/extensions/inkex/inx.py new file mode 100644 index 0000000..2360bc6 --- /dev/null +++ b/share/extensions/inkex/inx.py @@ -0,0 +1,244 @@ +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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. +# +""" +Parsing inx files for checking and generating. +""" + +import os +from inspect import isclass +from importlib import util +from lxml import etree + +from .base import InkscapeExtension +from .utils import Boolean + +NSS = { + "inx": "http://www.inkscape.org/namespace/inkscape/extension", + "inkscape": "http://www.inkscape.org/namespaces/inkscape", +} +SSN = {b: a for (a, b) in NSS.items()} + + +class InxLookup(etree.CustomElementClassLookup): + """Custom inx xml file lookup""" + + def lookup( + self, node_type, document, namespace, name + ): # pylint: disable=unused-argument + if name == "param": + return ParamElement + return InxElement + + +INX_PARSER = etree.XMLParser() +INX_PARSER.set_element_class_lookup(InxLookup()) + + +class InxFile: + """Open an INX file and provide useful functions""" + + name = property(lambda self: self.xml.get_text("name")) + ident = property(lambda self: self.xml.get_text("id")) + slug = property(lambda self: self.ident.split(".")[-1].title().replace("_", "")) + kind = property(lambda self: self.metadata["type"]) + warnings = property(lambda self: sorted(list(set(self.xml.warnings)))) + + def __init__(self, filename): + if isinstance(filename, str) and "<" in filename: + filename = filename.encode("utf8") + if isinstance(filename, bytes) and b"<" in filename: + self.filename = None + self.doc = etree.ElementTree(etree.fromstring(filename, parser=INX_PARSER)) + else: + self.filename = os.path.basename(filename) + self.doc = etree.parse(filename, parser=INX_PARSER) + self.xml = self.doc.getroot() + self.xml.warnings = [] + + def __repr__(self): + return f"" + + @property + def script(self): + """Returns information about the called script""" + command = self.xml.find_one("script/command") + if command is None: + return {} + return { + "interpreter": command.get("interpreter", None), + "location": command.get("location", None), + "script": command.text, + } + + @property + def extension_class(self): + """Attempt to get the extension class""" + script = self.script.get("script", None) + if script is not None: + name = script[:-3].replace("/", ".") + spec = util.spec_from_file_location(name, script) + mod = util.module_from_spec(spec) + spec.loader.exec_module(mod) + for value in mod.__dict__.values(): + if ( + "Base" not in name + and isclass(value) + and value.__module__ == name + and issubclass(value, InkscapeExtension) + ): + return value + return None + + @property + def metadata(self): + """Returns information about what type of extension this is""" + effect = self.xml.find_one("effect") + output = self.xml.find_one("output") + inputs = self.xml.find_one("input") + data = {} + if effect is not None: + template = self.xml.find_one("inkscape:templateinfo") + if template is not None: + data["type"] = "template" + data["desc"] = self.xml.get_text( + "templateinfo/shortdesc", nss="inkscape" + ) + data["author"] = self.xml.get_text( + "templateinfo/author", nss="inkscape" + ) + else: + data["type"] = "effect" + data["preview"] = Boolean(effect.get("needs-live-preview", "true")) + data["objects"] = effect.get_text("object-type", "all") + elif inputs is not None: + data["type"] = "input" + data["extension"] = inputs.get_text("extension") + data["mimetype"] = inputs.get_text("mimetype") + data["tooltip"] = inputs.get_text("filetypetooltip") + data["name"] = inputs.get_text("filetypename") + elif output is not None: + data["type"] = "output" + data["dataloss"] = Boolean(output.get_text("dataloss", "false")) + data["extension"] = output.get_text("extension") + data["mimetype"] = output.get_text("mimetype") + data["tooltip"] = output.get_text("filetypetooltip") + data["name"] = output.get_text("filetypename") + return data + + @property + def menu(self): + """Return the menu this effect ends up in""" + + def _recurse_menu(parent): + for child in parent.xpath("submenu"): + yield child.get("name") + for subchild in _recurse_menu(child): + yield subchild + break # Not more than one menu chain? + + menu = self.xml.find_one("effect/effects-menu") + return list(_recurse_menu(menu)) + [self.name] + + @property + def params(self): + """Get all params at all levels""" + # Returns any params at any levels + return list(self.xml.xpath("//param")) + + +class InxElement(etree.ElementBase): + """Any element in an inx file + + .. versionadded:: 1.1""" + + def set_warning(self, msg): + """Set a warning for slightly incorrect inx contents""" + root = self.get_root() + if hasattr(root, "warnings"): + root.warnings.append(msg) + + def get_root(self): + """Get the root document element from any element descendent""" + if self.getparent() is not None: + return self.getparent().get_root() + return self + + def get_default_prefix(self): + """Set default xml namespace prefix. If none is defined, set warning""" + tag = self.get_root().tag + if "}" in tag: + (url, tag) = tag[1:].split("}", 1) + return SSN.get(url, "inx") + self.set_warning("No inx xml prefix.") + return None # no default prefix + + def apply_nss(self, xpath, nss=None): + """Add prefixes to any xpath string""" + if nss is None: + nss = self.get_default_prefix() + + def _process(seg): + if ":" in seg or not seg or not nss: + return seg + return f"{nss}:{seg}" + + return "/".join([_process(seg) for seg in xpath.split("/")]) + + def xpath(self, xpath, nss=None): + """Namespace specific xpath searches + + .. versionadded:: 1.1""" + return super().xpath(self.apply_nss(xpath, nss=nss), namespaces=NSS) + + def find_one(self, name, nss=None): + """Return the first element matching the given name + + .. versionadded:: 1.1""" + for elem in self.xpath(name, nss=nss): + return elem + return None + + def get_text(self, name, default=None, nss=None): + """Get text content agnostically""" + for pref in ("", "_"): + elem = self.find_one(pref + name, nss=nss) + if elem is not None and elem.text: + if pref == "_": + self.set_warning(f"Use of old translation scheme: <_{name}...>") + return elem.text + return default + + +class ParamElement(InxElement): + """ + A param in an inx file. + """ + + name = property(lambda self: self.get("name")) + param_type = property(lambda self: self.get("type", "string")) + + @property + def options(self): + """Return a list of option values""" + if self.param_type == "notebook": + return [option.get("name") for option in self.xpath("page")] + return [option.get("value") for option in self.xpath("option")] + + def __repr__(self): + return f"" diff --git a/share/extensions/inkex/localization.py b/share/extensions/inkex/localization.py new file mode 100644 index 0000000..7de6c57 --- /dev/null +++ b/share/extensions/inkex/localization.py @@ -0,0 +1,117 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Nick Drobchenko, nick@cnc-club.ru +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +""" +Allow extensions to translate messages. +""" + +import gettext +import os, sys + +# Get gettext domain and matching locale directory for translation of extensions strings +# (both environment variables are set by Inkscape) +GETTEXT_DOMAIN = os.environ.get("INKEX_GETTEXT_DOMAIN") +GETTEXT_DIRECTORY = os.environ.get("INKEX_GETTEXT_DIRECTORY") + +# INKSCAPE_LOCALEDIR can be used to override the default locale directory Inkscape uses +INKSCAPE_LOCALEDIR = os.environ.get("INKSCAPE_LOCALEDIR") + + +def localize(domain=GETTEXT_DOMAIN, localedir=GETTEXT_DIRECTORY): + """Configure gettext and install _() function into builtins namespace for easy + access""" + + # Do not enable translation if GETTEXT_DOMAIN is unset. + # This is the case when translationdomain="none", but also when no catalog was + # found. + # Install a NullTranslation just to be sure + # (so we do not get errors about undefined '_') + if domain is None: + gettext.NullTranslations().install() + return + + # Use the default system locale by default, + # but prefer LANGUAGE environment variable + # (which is set by Inkscape according to UI language) + languages = None + + trans = gettext.translation(domain, localedir, languages, fallback=True) + trans.install() + + +def inkex_localize(): + """ + Return internal Translations instance for translation of the inkex module itself + Those will always use the 'inkscape' domain and attempt to lookup the same catalog + Inkscape uses + """ + + domain = "inkscape" + localedir = INKSCAPE_LOCALEDIR + languages = None + + return gettext.translation(domain, localedir, languages, fallback=True) + + +inkex_gettext = inkex_localize().gettext # pylint: disable=invalid-name +""" +Shortcut for gettext. Import as:: + + from inkex.localize import inkex_gettext as _ + +""" + +inkex_ngettext = inkex_localize().ngettext +""" +Shortcut for ngettext + + .. versionadded:: 1.2 +""" + + +def inkex_fgettext(message, *args, **kwargs): + """ + Shortcut for gettext and subsequent formatting. Import as:: + + from inkex.localize import inkex_fgettext as _f + + The positionals and keyword arguments are passed to ``str.format()``. + + The call to xgettext must contain:: + + --keyword=_f + """ + return inkex_gettext(message).format(*args, **kwargs) + + +if sys.version_info >= (3, 8): + inkex_pgettext = inkex_localize().pgettext + """ + Gettext with context. Import as:: + + from inkex.localize import inkex_pgettext as pgettext + + Both parameters **must** be string literals. The call to xgettext must contain:: + + --keyword=pgettext:1c,2 + + .. versionadded:: 1.2 + """ +else: + inkex_pgettext = lambda context, message: message diff --git a/share/extensions/inkex/paths.py b/share/extensions/inkex/paths.py new file mode 100644 index 0000000..a0624d0 --- /dev/null +++ b/share/extensions/inkex/paths.py @@ -0,0 +1,2018 @@ +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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. +# +""" +functions for digesting paths +""" +from __future__ import annotations + +import re +import copy +import abc + +from math import atan2, cos, pi, sin, sqrt, acos, tan +from typing import ( + Any, + Type, + Dict, + Optional, + Union, + Tuple, + List, + Generator, + TypeVar, +) +from .transforms import ( + Transform, + BoundingBox, + Vector2d, + cubic_extrema, + quadratic_extrema, +) +from .utils import classproperty, strargs + + +Pathlike = TypeVar("Pathlike", bound="PathCommand") +AbsolutePathlike = TypeVar("AbsolutePathlike", bound="AbsolutePathCommand") + +# All the names that get added to the inkex API itself. +__all__ = ( + "Path", + "CubicSuperPath", + "PathCommand", + "AbsolutePathCommand", + "RelativePathCommand", + # Path commands: + "Line", + "line", + "Move", + "move", + "ZoneClose", + "zoneClose", + "Horz", + "horz", + "Vert", + "vert", + "Curve", + "curve", + "Smooth", + "smooth", + "Quadratic", + "quadratic", + "TepidQuadratic", + "tepidQuadratic", + "Arc", + "arc", + # errors + "InvalidPath", +) + +LEX_REX = re.compile(r"([MLHVCSQTAZmlhvcsqtaz])([^MLHVCSQTAZmlhvcsqtaz]*)") +NONE = lambda obj: obj is not None + + +class InvalidPath(ValueError): + """Raised when given an invalid path string""" + + +class PathCommand(abc.ABC): + """ + Base class of all path commands + """ + + # Number of arguments that follow this path commands letter + nargs = -1 + + @classproperty # From python 3.9 on, just combine @classmethod and @property + def name(cls): # pylint: disable=no-self-argument + """The full name of the segment (i.e. Line, Arc, etc)""" + return cls.__name__ # pylint: disable=no-member + + @classproperty + def letter(cls): # pylint: disable=no-self-argument + """The single letter representation of this command (i.e. L, A, etc)""" + return cls.name[0] + + @classproperty + def next_command(self): + """The implicit next command. This is for automatic chains where the next + command isn't given, just a bunch on numbers which we automatically parse.""" + return self + + @property + def is_relative(self): # type: () -> bool + """Whether the command is defined in relative coordinates, i.e. relative to + the previous endpoint (lower case path command letter)""" + raise NotImplementedError + + @property + def is_absolute(self): # type: () -> bool + """Whether the command is defined in absolute coordinates (upper case path + command letter)""" + raise NotImplementedError + + def to_relative(self, prev): # type: (Vector2d) -> RelativePathCommand + """Return absolute counterpart for absolute commands or copy for relative""" + raise NotImplementedError + + def to_absolute(self, prev): # type: (Vector2d) -> AbsolutePathCommand + """Return relative counterpart for relative commands or copy for absolute""" + raise NotImplementedError + + def reverse(self, first, prev): + """Reverse path command + + .. versionadded:: 1.1""" + + def to_non_shorthand(self, prev, prev_control): # pylint: disable=unused-argument + # type: (Vector2d, Vector2d) -> AbsolutePathCommand + """Return an absolute non-shorthand command + + .. versionadded:: 1.1""" + return self.to_absolute(prev) + + # The precision of the numbers when converting to string + number_template = "{:.6g}" + + # Maps single letter path command to corresponding class + # (filled at the bottom of file, when all classes already defined) + _letter_to_class = {} # type: Dict[str, Type[Any]] + + @staticmethod + def letter_to_class(letter): + """Returns class for given path command letter""" + return PathCommand._letter_to_class[letter] + + @property + def args(self): # type: () -> List[float] + """Returns path command arguments as tuple of floats""" + raise NotImplementedError() + + def control_points( + self, first: Vector2d, prev: Vector2d, prev_prev: Vector2d + ) -> Union[List[Vector2d], Generator[Vector2d, None, None]]: + """Returns list of path command control points""" + raise NotImplementedError + + @classmethod + def _argt(cls, sep): + return sep.join([cls.number_template] * cls.nargs) + + def __str__(self): + return f"{self.letter} {self._argt(' ').format(*self.args)}".strip() + + def __repr__(self): + # pylint: disable=consider-using-f-string + return "{{}}({})".format(self._argt(", ")).format(self.name, *self.args) + + def __eq__(self, other): + previous = Vector2d() + if type(self) == type(other): # pylint: disable=unidiomatic-typecheck + return self.args == other.args + if isinstance(other, tuple): + return self.args == other + if not isinstance(other, PathCommand): + raise ValueError("Can't compare types") + try: + if self.is_relative == other.is_relative: + return self.to_curve(previous) == other.to_curve(previous) + except ValueError: + pass + return False + + def end_point(self, first, prev): # type: (Vector2d, Vector2d) -> Vector2d + """Returns last control point of path command""" + raise NotImplementedError() + + def update_bounding_box( + self, first: Vector2d, last_two_points: List[Vector2d], bbox: BoundingBox + ): + # pylint: disable=unused-argument + """Enlarges given bbox to contain path element. + + Args: + first (Vector2d): first point of path. Required to calculate Z segment + last_two_points (List[Vector2d]): list with last two control points in abs + coords. + bbox (BoundingBox): bounding box to update + """ + + raise NotImplementedError(f"Bounding box is not implemented for {self.name}") + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> Curve + """Convert command to :py:class:`Curve` + + Curve().to_curve() returns a copy + """ + raise NotImplementedError(f"To curve not supported for {self.name}") + + def to_curves(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> List[Curve] + """Convert command to list of :py:class:`Curve` commands""" + return [self.to_curve(prev, prev_prev)] + + def to_line(self, prev): + # type: (Vector2d) -> Line + """Converts this segment to a line (copies if already a line)""" + return Line(*self.end_point(Vector2d(), prev)) + + +class RelativePathCommand(PathCommand): + """ + Abstract base class for relative path commands. + + Implements most of methods of :py:class:`PathCommand` through + conversion to :py:class:`AbsolutePathCommand` + """ + + @property + def is_relative(self): + return True + + @property + def is_absolute(self): + return False + + def control_points( + self, first: Vector2d, prev: Vector2d, prev_prev: Vector2d + ) -> Union[List[Vector2d], Generator[Vector2d, None, None]]: + return self.to_absolute(prev).control_points(first, prev, prev_prev) + + def to_relative(self, prev): + # type: (Pathlike, Vector2d) -> Pathlike + return self.__class__(*self.args) + + def update_bounding_box(self, first, last_two_points, bbox): + self.to_absolute(last_two_points[-1]).update_bounding_box( + first, last_two_points, bbox + ) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return self.to_absolute(prev).end_point(first, prev) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> Curve + return self.to_absolute(prev).to_curve(prev, prev_prev) + + def to_curves(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> List[Curve] + return self.to_absolute(prev).to_curves(prev, prev_prev) + + +class AbsolutePathCommand(PathCommand): + """Absolute path command. Unlike :py:class:`RelativePathCommand` can be transformed + directly.""" + + @property + def is_relative(self): + return False + + @property + def is_absolute(self): + return True + + def to_absolute( + self, prev + ): # type: (AbsolutePathlike, Vector2d) -> AbsolutePathlike + return self.__class__(*self.args) + + def transform( + self, transform + ): # type: (AbsolutePathlike, Transform) -> AbsolutePathlike + """Returns new transformed segment + + :param transform: a transformation to apply + """ + raise NotImplementedError() + + def rotate( + self, degrees, center + ): # type: (AbsolutePathlike, float, Vector2d) -> AbsolutePathlike + """ + Returns new transformed segment + + :param degrees: rotation angle in degrees + :param center: invariant point of rotation + """ + return self.transform(Transform(rotate=(degrees, center[0], center[1]))) + + def translate(self, dr): # type: (AbsolutePathlike, Vector2d) -> AbsolutePathlike + """Translate or scale this path command by dr""" + return self.transform(Transform(translate=dr)) + + def scale( + self, factor + ): # type: (AbsolutePathlike, Union[float, Tuple[float,float]]) -> AbsolutePathlike + """Returns new transformed segment + + :param factor: scale or (scale_x, scale_y) + """ + return self.transform(Transform(scale=factor)) + + +class Line(AbsolutePathCommand): + """Line segment""" + + nargs = 2 + + @property + def args(self): + return self.x, self.y + + def __init__(self, x, y): + self.x = x + self.y = y + + def update_bounding_box(self, first, last_two_points, bbox): + bbox += BoundingBox( + (last_two_points[-1].x, self.x), (last_two_points[-1].y, self.y) + ) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x, self.y) + + def to_relative(self, prev): + # type: (Vector2d) -> line + return line(self.x - prev.x, self.y - prev.y) + + def transform(self, transform): + # type: (Line, Transform) -> Line + return Line(*transform.apply_to_point((self.x, self.y))) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x, self.y) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Optional[Vector2d]) -> Curve + return Curve(prev.x, prev.y, self.x, self.y, self.x, self.y) + + def reverse(self, first, prev): + return Line(prev.x, prev.y) + + +class line(RelativePathCommand): # pylint: disable=invalid-name + """Relative line segment""" + + nargs = 2 + + @property + def args(self): + return self.dx, self.dy + + def __init__(self, dx, dy): + self.dx = dx + self.dy = dy + + def to_absolute(self, prev): # type: (Vector2d) -> Line + return Line(prev.x + self.dx, prev.y + self.dy) + + def reverse(self, first, prev): + return line(-self.dx, -self.dy) + + +class Move(AbsolutePathCommand): + """Move pen segment without a line""" + + nargs = 2 + next_command = Line + + @property + def args(self): + return self.x, self.y + + def __init__(self, x, y): + self.x = x + self.y = y + + def update_bounding_box(self, first, last_two_points, bbox): + bbox += BoundingBox(self.x, self.y) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x, self.y) + + def to_relative(self, prev): + # type: (Vector2d) -> move + return move(self.x - prev.x, self.y - prev.y) + + def transform(self, transform): + # type: (Transform) -> Move + return Move(*transform.apply_to_point((self.x, self.y))) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x, self.y) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Optional[Vector2d]) -> Curve + raise ValueError("Move segments can not be changed into curves.") + + def reverse(self, first, prev): + return Move(prev.x, prev.y) + + +class move(RelativePathCommand): # pylint: disable=invalid-name + """Relative move segment""" + + nargs = 2 + next_command = line + + @property + def args(self): + return self.dx, self.dy + + def __init__(self, dx, dy): + self.dx = dx + self.dy = dy + + def to_absolute(self, prev): # type: (Vector2d) -> Move + return Move(prev.x + self.dx, prev.y + self.dy) + + def reverse(self, first, prev): + return move(prev.x - first.x, prev.y - first.y) + + +class ZoneClose(AbsolutePathCommand): + """Close segment to finish a path""" + + nargs = 0 + next_command = Move + + @property + def args(self): + return () + + def update_bounding_box(self, first, last_two_points, bbox): + pass + + def transform(self, transform): + # type: (Transform) -> ZoneClose + return ZoneClose() + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield first + + def to_relative(self, prev): + # type: (Vector2d) -> zoneClose + return zoneClose() + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return first + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Optional[Vector2d]) -> Curve + raise ValueError("ZoneClose segments can not be changed into curves.") + + def reverse(self, first, prev): + return Line(prev.x, prev.y) + + +class zoneClose(RelativePathCommand): # pylint: disable=invalid-name + """Same as above (svg says no difference)""" + + nargs = 0 + next_command = Move + + @property + def args(self): + return () + + def to_absolute(self, prev): + return ZoneClose() + + def reverse(self, first, prev): + return line(prev.x - first.x, prev.y - first.y) + + +class Horz(AbsolutePathCommand): + """Horizontal Line segment""" + + nargs = 1 + + @property + def args(self): + return (self.x,) + + def __init__(self, x): + self.x = x + + def update_bounding_box(self, first, last_two_points, bbox): + bbox += BoundingBox((last_two_points[-1].x, self.x), last_two_points[-1].y) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x, prev.y) + + def to_relative(self, prev): + # type: (Vector2d) -> horz + return horz(self.x - prev.x) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Line + return self.to_line(prev) + + def transform(self, transform): + # type: (Pathlike, Transform) -> Pathlike + raise ValueError("Horizontal lines can't be transformed directly.") + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x, prev.y) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Optional[Vector2d]) -> Curve + """Convert a horizontal line into a curve""" + return self.to_line(prev).to_curve(prev) + + def to_line(self, prev): + # type: (Vector2d) -> Line + """Return this path command as a Line instead""" + return Line(self.x, prev.y) + + def reverse(self, first, prev): + return Horz(prev.x) + + +class horz(RelativePathCommand): # pylint: disable=invalid-name + """Relative horz line segment""" + + nargs = 1 + + @property + def args(self): + return (self.dx,) + + def __init__(self, dx): + self.dx = dx + + def to_absolute(self, prev): # type: (Vector2d) -> Horz + return Horz(prev.x + self.dx) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Line + return self.to_line(prev) + + def to_line(self, prev): # type: (Vector2d) -> Line + """Return this path command as a Line instead""" + return Line(prev.x + self.dx, prev.y) + + def reverse(self, first, prev): + return horz(-self.dx) + + +class Vert(AbsolutePathCommand): + """Vertical Line segment""" + + nargs = 1 + + @property + def args(self): + return (self.y,) + + def __init__(self, y): + self.y = y + + def update_bounding_box(self, first, last_two_points, bbox): + bbox += BoundingBox(last_two_points[-1].x, (last_two_points[-1].y, self.y)) + + def transform(self, transform): # type: (Pathlike, Transform) -> Pathlike + raise ValueError("Vertical lines can't be transformed directly.") + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(prev.x, self.y) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Line + return self.to_line(prev) + + def to_relative(self, prev): + # type: (Vector2d) -> vert + return vert(self.y - prev.y) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(prev.x, self.y) + + def to_line(self, prev): + # type: (Vector2d) -> Line + """Return this path command as a line instead""" + return Line(prev.x, self.y) + + def to_curve( + self, prev, prev_prev=Vector2d() + ): # type: (Vector2d, Optional[Vector2d]) -> Curve + """Convert a horizontal line into a curve""" + return self.to_line(prev).to_curve(prev) + + def reverse(self, first, prev): + return Vert(prev.y) + + +class vert(RelativePathCommand): # pylint: disable=invalid-name + """Relative vertical line segment""" + + nargs = 1 + + @property + def args(self): + return (self.dy,) + + def __init__(self, dy): + self.dy = dy + + def to_absolute(self, prev): # type: (Vector2d) -> Vert + return Vert(prev.y + self.dy) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Line + return self.to_line(prev) + + def to_line(self, prev): # type: (Vector2d) -> Line + """Return this path command as a line instead""" + return Line(prev.x, prev.y + self.dy) + + def reverse(self, first, prev): + return vert(-self.dy) + + +class Curve(AbsolutePathCommand): + """Absolute Curved Line segment""" + + nargs = 6 + + @property + def args(self): + return self.x2, self.y2, self.x3, self.y3, self.x4, self.y4 + + def __init__(self, x2, y2, x3, y3, x4, y4): # pylint: disable=too-many-arguments + self.x2 = x2 + self.y2 = y2 + + self.x3 = x3 + self.y3 = y3 + + self.x4 = x4 + self.y4 = y4 + + def update_bounding_box(self, first, last_two_points, bbox): + + x1, x2, x3, x4 = last_two_points[-1].x, self.x2, self.x3, self.x4 + y1, y2, y3, y4 = last_two_points[-1].y, self.y2, self.y3, self.y4 + + if not (x1 in bbox.x and x2 in bbox.x and x3 in bbox.x and x4 in bbox.x): + bbox.x += cubic_extrema(x1, x2, x3, x4) + + if not (y1 in bbox.y and y2 in bbox.y and y3 in bbox.y and y4 in bbox.y): + bbox.y += cubic_extrema(y1, y2, y3, y4) + + def transform(self, transform): + # type: (Transform) -> Curve + x2, y2 = transform.apply_to_point((self.x2, self.y2)) + x3, y3 = transform.apply_to_point((self.x3, self.y3)) + x4, y4 = transform.apply_to_point((self.x4, self.y4)) + return Curve(x2, y2, x3, y3, x4, y4) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x2, self.y2) + yield Vector2d(self.x3, self.y3) + yield Vector2d(self.x4, self.y4) + + def to_relative(self, prev): # type: (Vector2d) -> curve + return curve( + self.x2 - prev.x, + self.y2 - prev.y, + self.x3 - prev.x, + self.y3 - prev.y, + self.x4 - prev.x, + self.y4 - prev.y, + ) + + def end_point(self, first, prev): + return Vector2d(self.x4, self.y4) + + def to_curve( + self, prev, prev_prev=Vector2d() + ): # type: (Vector2d, Optional[Vector2d]) -> Curve + """No conversion needed, pass-through, returns self""" + return Curve(*self.args) + + def to_bez(self): + """Returns the list of coords for SuperPath""" + return [list(self.args[:2]), list(self.args[2:4]), list(self.args[4:6])] + + def reverse(self, first, prev): + return Curve(self.x3, self.y3, self.x2, self.y2, prev.x, prev.y) + + +class curve(RelativePathCommand): # pylint: disable=invalid-name + """Relative curved line segment""" + + nargs = 6 + + @property + def args(self): + return self.dx2, self.dy2, self.dx3, self.dy3, self.dx4, self.dy4 + + def __init__( + self, dx2, dy2, dx3, dy3, dx4, dy4 + ): # pylint: disable=too-many-arguments + self.dx2 = dx2 + self.dy2 = dy2 + + self.dx3 = dx3 + self.dy3 = dy3 + + self.dx4 = dx4 + self.dy4 = dy4 + + def to_absolute(self, prev): # type: (Vector2d) -> Curve + return Curve( + self.dx2 + prev.x, + self.dy2 + prev.y, + self.dx3 + prev.x, + self.dy3 + prev.y, + self.dx4 + prev.x, + self.dy4 + prev.y, + ) + + def reverse(self, first, prev): + return curve( + -self.dx4 + self.dx3, + -self.dy4 + self.dy3, + -self.dx4 + self.dx2, + -self.dy4 + self.dy2, + -self.dx4, + -self.dy4, + ) + + +class Smooth(AbsolutePathCommand): + """Absolute Smoothed Curved Line segment""" + + nargs = 4 + + @property + def args(self): + return self.x3, self.y3, self.x4, self.y4 + + def __init__(self, x3, y3, x4, y4): + + self.x3 = x3 + self.y3 = y3 + + self.x4 = x4 + self.y4 = y4 + + def update_bounding_box(self, first, last_two_points, bbox): + self.to_curve(last_two_points[-1], last_two_points[-2]).update_bounding_box( + first, last_two_points, bbox + ) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + + x1, x2, x3, x4 = prev_prev.x, prev.x, self.x3, self.x4 + y1, y2, y3, y4 = prev_prev.y, prev.y, self.y3, self.y4 + + # infer reflected point + x2 = 2 * x2 - x1 + y2 = 2 * y2 - y1 + + yield Vector2d(x2, y2) + yield Vector2d(x3, y3) + yield Vector2d(x4, y4) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Curve + return self.to_curve(prev, prev_control) + + def to_relative(self, prev): # type: (Vector2d) -> smooth + return smooth( + self.x3 - prev.x, self.y3 - prev.y, self.x4 - prev.x, self.y4 - prev.y + ) + + def transform(self, transform): + # type: (Transform) -> Smooth + x3, y3 = transform.apply_to_point((self.x3, self.y3)) + x4, y4 = transform.apply_to_point((self.x4, self.y4)) + return Smooth(x3, y3, x4, y4) + + def end_point(self, first, prev): + return Vector2d(self.x4, self.y4) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> Curve + """ + Convert this Smooth curve to a regular curve by creating a mirror + set of nodes based on the previous node. Previous should be a curve. + """ + (x2, y2), (x3, y3), (x4, y4) = self.control_points(prev, prev, prev_prev) + return Curve(x2, y2, x3, y3, x4, y4) + + def reverse(self, first, prev): + return Smooth(self.x3, self.y3, prev.x, prev.y) + + +class smooth(RelativePathCommand): # pylint: disable=invalid-name + """Relative smoothed curved line segment""" + + nargs = 4 + + @property + def args(self): + return self.dx3, self.dy3, self.dx4, self.dy4 + + def __init__(self, dx3, dy3, dx4, dy4): + self.dx3 = dx3 + self.dy3 = dy3 + + self.dx4 = dx4 + self.dy4 = dy4 + + def to_absolute(self, prev): # type: (Vector2d) -> Smooth + return Smooth( + self.dx3 + prev.x, self.dy3 + prev.y, self.dx4 + prev.x, self.dy4 + prev.y + ) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> Curve + return self.to_absolute(prev).to_non_shorthand(prev, prev_control) + + def reverse(self, first, prev): + return smooth(-self.dx4 + self.dx3, -self.dy4 + self.dy3, -self.dx4, -self.dy4) + + +class Quadratic(AbsolutePathCommand): + """Absolute Quadratic Curved Line segment""" + + nargs = 4 + + @property + def args(self): + return self.x2, self.y2, self.x3, self.y3 + + def __init__(self, x2, y2, x3, y3): + + self.x2 = x2 + self.y2 = y2 + + self.x3 = x3 + self.y3 = y3 + + def update_bounding_box(self, first, last_two_points, bbox): + + x1, x2, x3 = last_two_points[-1].x, self.x2, self.x3 + y1, y2, y3 = last_two_points[-1].y, self.y2, self.y3 + + if not (x1 in bbox.x and x2 in bbox.x and x3 in bbox.x): + bbox.x += quadratic_extrema(x1, x2, x3) + + if not (y1 in bbox.y and y2 in bbox.y and y3 in bbox.y): + bbox.y += quadratic_extrema(y1, y2, y3) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x2, self.y2) + yield Vector2d(self.x3, self.y3) + + def to_relative(self, prev): + # type: (Vector2d) -> quadratic + return quadratic( + self.x2 - prev.x, self.y2 - prev.y, self.x3 - prev.x, self.y3 - prev.y + ) + + def transform(self, transform): + # type: (Transform) -> Quadratic + x2, y2 = transform.apply_to_point((self.x2, self.y2)) + x3, y3 = transform.apply_to_point((self.x3, self.y3)) + return Quadratic(x2, y2, x3, y3) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x3, self.y3) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> Curve + """Attempt to convert a quadratic to a curve""" + prev = Vector2d(prev) + x1 = 1.0 / 3 * prev.x + 2.0 / 3 * self.x2 + x2 = 2.0 / 3 * self.x2 + 1.0 / 3 * self.x3 + y1 = 1.0 / 3 * prev.y + 2.0 / 3 * self.y2 + y2 = 2.0 / 3 * self.y2 + 1.0 / 3 * self.y3 + return Curve(x1, y1, x2, y2, self.x3, self.y3) + + def reverse(self, first, prev): + return Quadratic(self.x2, self.y2, prev.x, prev.y) + + +class quadratic(RelativePathCommand): # pylint: disable=invalid-name + """Relative quadratic line segment""" + + nargs = 4 + + @property + def args(self): + return self.dx2, self.dy2, self.dx3, self.dy3 + + def __init__(self, dx2, dy2, dx3, dy3): + self.dx2 = dx2 + self.dx3 = dx3 + self.dy2 = dy2 + self.dy3 = dy3 + + def to_absolute(self, prev): # type: (Vector2d) -> Quadratic + return Quadratic( + self.dx2 + prev.x, self.dy2 + prev.y, self.dx3 + prev.x, self.dy3 + prev.y + ) + + def reverse(self, first, prev): + return quadratic( + -self.dx3 + self.dx2, -self.dy3 + self.dy2, -self.dx3, -self.dy3 + ) + + +class TepidQuadratic(AbsolutePathCommand): + """Continued Quadratic Line segment""" + + nargs = 2 + + @property + def args(self): + return self.x3, self.y3 + + def __init__(self, x3, y3): + self.x3 = x3 + self.y3 = y3 + + def update_bounding_box(self, first, last_two_points, bbox): + self.to_quadratic(last_two_points[-1], last_two_points[-2]).update_bounding_box( + first, last_two_points, bbox + ) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + + x1, x2, x3 = prev_prev.x, prev.x, self.x3 + y1, y2, y3 = prev_prev.y, prev.y, self.y3 + + # infer reflected point + x2 = 2 * x2 - x1 + y2 = 2 * y2 - y1 + + yield Vector2d(x2, y2) + yield Vector2d(x3, y3) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> AbsolutePathCommand + return self.to_quadratic(prev, prev_control) + + def to_relative(self, prev): # type: (Vector2d) -> tepidQuadratic + return tepidQuadratic(self.x3 - prev.x, self.y3 - prev.y) + + def transform(self, transform): + # type: (Transform) -> TepidQuadratic + x3, y3 = transform.apply_to_point((self.x3, self.y3)) + return TepidQuadratic(x3, y3) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x3, self.y3) + + def to_curve(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> Curve + return self.to_quadratic(prev, prev_prev).to_curve(prev) + + def to_quadratic(self, prev, prev_prev): + # type: (Vector2d, Vector2d) -> Quadratic + """ + Convert this continued quadratic into a full quadratic + """ + (x2, y2), (x3, y3) = self.control_points(prev, prev, prev_prev) + return Quadratic(x2, y2, x3, y3) + + def reverse(self, first, prev): + return TepidQuadratic(prev.x, prev.y) + + +class tepidQuadratic(RelativePathCommand): # pylint: disable=invalid-name + """Relative continued quadratic line segment""" + + nargs = 2 + + @property + def args(self): + return self.dx3, self.dy3 + + def __init__(self, dx3, dy3): + self.dx3 = dx3 + self.dy3 = dy3 + + def to_absolute(self, prev): + # type: (Vector2d) -> TepidQuadratic + return TepidQuadratic(self.dx3 + prev.x, self.dy3 + prev.y) + + def to_non_shorthand(self, prev, prev_control): + # type: (Vector2d, Vector2d) -> AbsolutePathCommand + return self.to_absolute(prev).to_non_shorthand(prev, prev_control) + + def reverse(self, first, prev): + return tepidQuadratic(-self.dx3, -self.dy3) + + +class Arc(AbsolutePathCommand): + """Special Arc segment""" + + nargs = 7 + + @property + def args(self): + return ( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + self.sweep, + self.x, + self.y, + ) + + def __init__( + self, rx, ry, x_axis_rotation, large_arc, sweep, x, y + ): # pylint: disable=too-many-arguments + self.rx = rx + self.ry = ry + self.x_axis_rotation = x_axis_rotation + self.large_arc = large_arc + self.sweep = sweep + self.x = x + self.y = y + + def update_bounding_box(self, first, last_two_points, bbox): + prev = last_two_points[-1] + for seg in self.to_curves(prev=prev): + seg.update_bounding_box(first, [None, prev], bbox) + prev = seg.end_point(first, prev) + + def control_points(self, first, prev, prev_prev): + # type: (Vector2d, Vector2d, Vector2d) -> Generator[Vector2d, None, None] + yield Vector2d(self.x, self.y) + + def to_curves(self, prev, prev_prev=Vector2d()): + # type: (Vector2d, Vector2d) -> List[Curve] + """Convert this arc into bezier curves""" + path = CubicSuperPath([arc_to_path(list(prev), self.args)]).to_path( + curves_only=True + ) + # Ignore the first move command from to_path() + return list(path)[1:] + + def transform(self, transform): + # type: (Transform) -> Arc + # pylint: disable=invalid-name, too-many-locals + x_, y_ = transform.apply_to_point((self.x, self.y)) + + T = transform # type: Transform + if self.x_axis_rotation != 0: + T = T @ Transform(rotate=self.x_axis_rotation) + a, c, b, d, _, _ = list(T.to_hexad()) + # T = | a b | + # | c d | + + detT = a * d - b * c + detT2 = detT**2 + + rx = float(self.rx) + ry = float(self.ry) + + if rx == 0.0 or ry == 0.0 or detT2 == 0.0: + # invalid Arc parameters + # transform only last point + return Arc( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + self.sweep, + x_, + y_, + ) + + A = (d**2 / rx**2 + c**2 / ry**2) / detT2 + B = -(d * b / rx**2 + c * a / ry**2) / detT2 + D = (b**2 / rx**2 + a**2 / ry**2) / detT2 + + theta = atan2(-2 * B, D - A) / 2 + theta_deg = theta * 180.0 / pi + DA = D - A + l2 = 4 * B**2 + DA**2 + + if l2 == 0: + delta = 0.0 + else: + delta = 0.5 * (-(DA**2) - 4 * B**2) / sqrt(l2) + + half = (A + D) / 2 + + rx_ = 1.0 / sqrt(half + delta) + ry_ = 1.0 / sqrt(half - delta) + + x_, y_ = transform.apply_to_point((self.x, self.y)) + + if detT > 0: + sweep = self.sweep + else: + sweep = 0 if self.sweep > 0 else 1 + + return Arc(rx_, ry_, theta_deg, self.large_arc, sweep, x_, y_) + + def to_relative(self, prev): + # type: (Vector2d) -> arc + return arc( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + self.sweep, + self.x - prev.x, + self.y - prev.y, + ) + + def end_point(self, first, prev): + # type: (Vector2d, Vector2d) -> Vector2d + return Vector2d(self.x, self.y) + + def reverse(self, first, prev): + return Arc( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + 1 - self.sweep, + prev.x, + prev.y, + ) + + +class arc(RelativePathCommand): # pylint: disable=invalid-name + """Relative Arc line segment""" + + nargs = 7 + + @property + def args(self): + return ( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + self.sweep, + self.dx, + self.dy, + ) + + def __init__( + self, rx, ry, x_axis_rotation, large_arc, sweep, dx, dy + ): # pylint: disable=too-many-arguments + self.rx = rx + self.ry = ry + self.x_axis_rotation = x_axis_rotation + self.large_arc = large_arc + self.sweep = sweep + self.dx = dx + self.dy = dy + + def to_absolute(self, prev): # type: (Vector2d) -> "Arc" + x1, y1 = prev + return Arc( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + self.sweep, + self.dx + x1, + self.dy + y1, + ) + + def reverse(self, first, prev): + return arc( + self.rx, + self.ry, + self.x_axis_rotation, + self.large_arc, + 1 - self.sweep, + -self.dx, + -self.dy, + ) + + +PathCommand._letter_to_class = { # pylint: disable=protected-access + "M": Move, + "L": Line, + "V": Vert, + "H": Horz, + "A": Arc, + "C": Curve, + "S": Smooth, + "Z": ZoneClose, + "Q": Quadratic, + "T": TepidQuadratic, + "m": move, + "l": line, + "v": vert, + "h": horz, + "a": arc, + "c": curve, + "s": smooth, + "z": zoneClose, + "q": quadratic, + "t": tepidQuadratic, +} + + +class Path(list): + """A list of segment commands which combine to draw a shape""" + + class PathCommandProxy: + """ + A handy class for Path traverse and coordinate access + + Reduces number of arguments in user code compared to bare + :class:`PathCommand` methods + """ + + def __init__( + self, command, first_point, previous_end_point, prev2_control_point + ): + self.command = command # type: PathCommand + self.first_point = first_point # type: Vector2d + self.previous_end_point = previous_end_point # type: Vector2d + self.prev2_control_point = prev2_control_point # type: Vector2d + + @property + def name(self): + """The full name of the segment (i.e. Line, Arc, etc)""" + return self.command.name + + @property + def letter(self): + """The single letter representation of this command (i.e. L, A, etc)""" + return self.command.letter + + @property + def next_command(self): + """The implicit next command.""" + return self.command.next_command + + @property + def is_relative(self): + """Whether the command is defined in relative coordinates, i.e. relative to + the previous endpoint (lower case path command letter)""" + return self.command.is_relative + + @property + def is_absolute(self): + """Whether the command is defined in absolute coordinates (upper case path + command letter)""" + return self.command.is_absolute + + @property + def args(self): + """Returns path command arguments as tuple of floats""" + return self.command.args + + @property + def control_points(self): + """Returns list of path command control points""" + return self.command.control_points( + self.first_point, self.previous_end_point, self.prev2_control_point + ) + + @property + def end_point(self): + """Returns last control point of path command""" + return self.command.end_point(self.first_point, self.previous_end_point) + + def reverse(self): + """Reverse path command""" + return self.command.reverse(self.end_point, self.previous_end_point) + + def to_curve(self): + """Convert command to :py:class:`Curve` + Curve().to_curve() returns a copy + """ + return self.command.to_curve( + self.previous_end_point, self.prev2_control_point + ) + + def to_curves(self): + """Convert command to list of :py:class:`Curve` commands""" + return self.command.to_curves( + self.previous_end_point, self.prev2_control_point + ) + + def to_absolute(self): + """Return relative counterpart for relative commands or copy for absolute""" + return self.command.to_absolute(self.previous_end_point) + + def __str__(self): + return str(self.command) + + def __repr__(self): + return "<" + self.__class__.__name__ + ">" + repr(self.command) + + def __init__(self, path_d=None): + super().__init__() + if isinstance(path_d, str): + # Returns a generator returning PathCommand objects + path_d = self.parse_string(path_d) + elif isinstance(path_d, CubicSuperPath): + path_d = path_d.to_path() + + for item in path_d or (): + if isinstance(item, PathCommand): + self.append(item) + elif isinstance(item, (list, tuple)) and len(item) == 2: + if isinstance(item[1], (list, tuple)): + self.append(PathCommand.letter_to_class(item[0])(*item[1])) + else: + self.append(Line(*item)) + else: + raise TypeError( + f"Bad path type: {type(path_d).__name__}" + f"({type(item).__name__}, ...): {item}" + ) + + @classmethod + def parse_string(cls, path_d): + """Parse a path string and generate segment objects""" + for cmd, numbers in LEX_REX.findall(path_d): + args = list(strargs(numbers)) + cmd = PathCommand.letter_to_class(cmd) + i = 0 + while i < len(args) or cmd.nargs == 0: + if len(args[i : i + cmd.nargs]) != cmd.nargs: + return + seg = cmd(*args[i : i + cmd.nargs]) + i += cmd.nargs + cmd = seg.next_command + yield seg + + def bounding_box(self): + # type: () -> Optional[BoundingBox] + """Return bounding box of the Path""" + if not self: + return None + iterator = self.proxy_iterator() + proxy = next(iterator) + bbox = BoundingBox(proxy.first_point.x, proxy.first_point.y) + try: + while True: + proxy = next(iterator) + proxy.command.update_bounding_box( + proxy.first_point, + [ + proxy.prev2_control_point, + proxy.previous_end_point, + ], + bbox, + ) + except StopIteration: + return bbox + + def append(self, cmd): + """Append a command to this path including any chained commands""" + if isinstance(cmd, list): + self.extend(cmd) + elif isinstance(cmd, PathCommand): + super().append(cmd) + + def translate(self, x, y, inplace=False): # pylint: disable=invalid-name + """Move all coords in this path by the given amount""" + return self.transform(Transform(translate=(x, y)), inplace=inplace) + + def scale(self, x, y, inplace=False): # pylint: disable=invalid-name + """Scale all coords in this path by the given amounts""" + return self.transform(Transform(scale=(x, y)), inplace=inplace) + + def rotate(self, deg, center=None, inplace=False): + """Rotate the path around the given point""" + if center is None: + # Default center is center of bbox + bbox = self.bounding_box() + if bbox: + center = bbox.center + else: + center = Vector2d() + center = Vector2d(center) + return self.transform( + Transform(rotate=(deg, center.x, center.y)), inplace=inplace + ) + + @property + def control_points(self): + """Returns all control points of the Path""" + prev = Vector2d() + prev_prev = Vector2d() + first = Vector2d() + + for seg in self: # type: PathCommand + cpts = list(seg.control_points(first, prev, prev_prev)) + if isinstance(seg, (zoneClose, ZoneClose, move, Move)): + first = cpts[-1] + for cpt in cpts: + prev_prev = prev + prev = cpt + yield cpt + + @property + def end_points(self): + """Returns all endpoints of all path commands (i.e. the nodes)""" + prev = Vector2d() + first = Vector2d() + + for seg in self: # type: PathCommand + end_point = seg.end_point(first, prev) + if isinstance(seg, (zoneClose, ZoneClose, move, Move)): + first = end_point + prev = end_point + yield end_point + + def transform(self, transform, inplace=False): + """Convert to new path""" + result = Path() + previous = Vector2d() + previous_new = Vector2d() + start_zone = True + first = Vector2d() + first_new = Vector2d() + + for i, seg in enumerate(self): # type: PathCommand + if start_zone: + first = seg.end_point(first, previous) + + if isinstance(seg, (horz, Horz, Vert, vert)): + seg = seg.to_line(previous) + + if seg.is_relative: + new_seg = ( + seg.to_absolute(previous) + .transform(transform) + .to_relative(previous_new) + ) + else: + new_seg = seg.transform(transform) + + if start_zone: + first_new = new_seg.end_point(first_new, previous_new) + + if inplace: + self[i] = new_seg + else: + result.append(new_seg) + previous = seg.end_point(first, previous) + previous_new = new_seg.end_point(first_new, previous_new) + start_zone = isinstance(seg, (zoneClose, ZoneClose)) + if inplace: + return self + return result + + def reverse(self): + """Returns a reversed path""" + result = Path() + *_, first = self.end_points + closer = None + + # Go through the path in reverse order + for index, prcom in reversed(list(enumerate(self.proxy_iterator()))): + if isinstance(prcom.command, (Move, move, ZoneClose, zoneClose)): + if closer is not None: + if len(result) > 0 and isinstance( + result[-1], (Line, line, Vert, vert, Horz, horz) + ): + result.pop() # We can replace simple lines with Z + result.append(closer) # replace with same type (rel or abs) + if isinstance(prcom.command, (ZoneClose, zoneClose)): + closer = prcom.command + else: + closer = None + + if index == 0: + if prcom.letter == "M": + result.insert(0, Move(first.x, first.y)) + elif prcom.letter == "m": + result.insert(0, move(first.x, first.y)) + else: + result.append(prcom.reverse()) + + return result + + def close(self): + """Attempt to close the last path segment""" + if self and not isinstance(self[-1], (zoneClose, ZoneClose)): + self.append(ZoneClose()) + + def proxy_iterator(self): + """ + Yields :py:class:`AugmentedPathIterator` + + :rtype: Iterator[ Path.PathCommandProxy ] + """ + + previous = Vector2d() + prev_prev = Vector2d() + first = Vector2d() + + for seg in self: # type: PathCommand# + if isinstance(seg, (zoneClose, ZoneClose, move, Move)): + first = seg.end_point(first, previous) + yield Path.PathCommandProxy(seg, first, previous, prev_prev) + if isinstance( + seg, + ( + curve, + tepidQuadratic, + quadratic, + smooth, + Curve, + TepidQuadratic, + Quadratic, + Smooth, + ), + ): + prev_prev = list(seg.control_points(first, previous, prev_prev))[-2] + previous = seg.end_point(first, previous) + + def to_absolute(self): + """Convert this path to use only absolute coordinates""" + return self._to_absolute(True) + + def to_non_shorthand(self): + # type: () -> Path + """Convert this path to use only absolute non-shorthand coordinates + + .. versionadded:: 1.1""" + return self._to_absolute(False) + + def _to_absolute(self, shorthand: bool) -> Path: + """Make entire Path absolute. + + Args: + shorthand (bool): If false, then convert all shorthand commands to + non-shorthand. + + Returns: + Path: the input path, converted to absolute coordinates. + """ + + abspath = Path() + + previous = Vector2d() + first = Vector2d() + + for seg in self: # type: PathCommand + if isinstance(seg, (move, Move)): + first = seg.end_point(first, previous) + + if shorthand: + abspath.append(seg.to_absolute(previous)) + else: + if abspath and isinstance(abspath[-1], (Curve, Quadratic)): + prev_control = list( + abspath[-1].control_points(Vector2d(), Vector2d(), Vector2d()) + )[-2] + else: + prev_control = previous + + abspath.append(seg.to_non_shorthand(previous, prev_control)) + + previous = seg.end_point(first, previous) + + return abspath + + def to_relative(self): + """Convert this path to use only relative coordinates""" + abspath = Path() + + previous = Vector2d() + first = Vector2d() + + for seg in self: # type: PathCommand + if isinstance(seg, (move, Move)): + first = seg.end_point(first, previous) + + abspath.append(seg.to_relative(previous)) + previous = seg.end_point(first, previous) + + return abspath + + def __str__(self): + return " ".join([str(seg) for seg in self]) + + def __add__(self, other): + acopy = copy.deepcopy(self) + if isinstance(other, str): + other = Path(other) + if isinstance(other, list): + acopy.extend(other) + return acopy + + def to_arrays(self): + """Returns path in format of parsePath output, returning arrays of absolute + command data + + .. deprecated:: 1.0 + This is compatibility function for older API. Should not be used in new code + + """ + return [[seg.letter, list(seg.args)] for seg in self.to_non_shorthand()] + + def to_superpath(self): + """Convert this path into a cubic super path""" + return CubicSuperPath(self) + + def copy(self): + """Make a copy""" + return copy.deepcopy(self) + + +class CubicSuperPath(list): + """ + A conversion of a path into a predictable list of cubic curves which + can be operated on as a list of simplified instructions. + + When converting back into a path, all lines, arcs etc will be converted + to curve instructions. + + Structure is held as [SubPath[(point_a, bezier, point_b), ...]], ...] + """ + + def __init__(self, items): + super().__init__() + self._closed = True + self._prev = Vector2d() + self._prev_prev = Vector2d() + + if isinstance(items, str): + items = Path(items) + + if isinstance(items, Path): + items = items.to_absolute() + + for item in items: + self.append(item) + + def __str__(self): + return str(self.to_path()) + + def append(self, item, force_shift=False): + """Accept multiple different formats for the data + + .. versionchanged:: 1.2 + ``force_shift`` parameter has been added + """ + if isinstance(item, list) and len(item) == 2 and isinstance(item[0], str): + item = PathCommand.letter_to_class(item[0])(*item[1]) + coordinate_shift = True + if isinstance(item, list) and len(item) == 3 and not force_shift: + coordinate_shift = False + is_quadratic = False + if isinstance(item, PathCommand): + if isinstance(item, Move): + if self._closed is False: + super().append([]) + item = [list(item.args), list(item.args), list(item.args)] + elif isinstance(item, ZoneClose) and self and self[-1]: + # This duplicates the first segment to 'close' the path, it's appended + # directly because we don't want to last coord to change for the final + # segment. + self[-1].append( + [self[-1][0][0][:], self[-1][0][1][:], self[-1][0][2][:]] + ) + # Then adds a new subpath for the next shape (if any) + self._closed = True + self._prev.assign(self._first) + return + elif isinstance(item, Arc): + # Arcs are made up of three curves (approximated) + for arc_curve in item.to_curves(self._prev, self._prev_prev): + x2, y2, x3, y3, x4, y4 = arc_curve.args + self.append([[x2, y2], [x3, y3], [x4, y4]], force_shift=True) + self._prev_prev.assign(x3, y3) + return + else: + is_quadratic = isinstance( + item, (Quadratic, TepidQuadratic, quadratic, tepidQuadratic) + ) + if isinstance(item, (Horz, Vert)): + item = item.to_line(self._prev) + prp = self._prev_prev + if is_quadratic: + self._prev_prev = list( + item.control_points(self._first, self._prev, prp) + )[-2:-1][0] + item = item.to_curve(self._prev, prp) + + if isinstance(item, Curve): + # Curves are cut into three tuples for the super path. + item = item.to_bez() + + if not isinstance(item, list): + raise ValueError(f"Unknown super curve item type: {item}") + + if len(item) != 3 or not all(len(bit) == 2 for bit in item): + # The item is already a subpath (usually from some other process) + if len(item[0]) == 3 and all(len(bit) == 2 for bit in item[0]): + super().append(self._clean(item)) + self._prev_prev = Vector2d(self[-1][-1][0]) + self._prev = Vector2d(self[-1][-1][1]) + return + raise ValueError(f"Unknown super curve list format: {item}") + + if self._closed: + # Closed means that the previous segment is closed so we need a new one + # We always append to the last open segment. CSP starts out closed. + self._closed = False + super().append([]) + + if coordinate_shift: + if self[-1]: + # The last tuple is replaced, it's the coords of where the next segment + # will land. + self[-1][-1][-1] = item[0][:] + # The last coord is duplicated, but is expected to be replaced + self[-1].append(item[1:] + copy.deepcopy(item)[-1:]) + else: + # Item is already a csp segment and has already been shifted. + self[-1].append(copy.deepcopy(item)) + + self._prev = Vector2d(self[-1][-1][1]) + if not is_quadratic: + self._prev_prev = Vector2d(self[-1][-1][0]) + + def _clean(self, lst): + """Recursively clean lists so they have the same type""" + if isinstance(lst, (tuple, list)): + return [self._clean(child) for child in lst] + return lst + + @property + def _first(self): + try: + return Vector2d(self[-1][0][0]) + except IndexError: + return Vector2d() + + def to_path(self, curves_only=False, rtol=1e-5, atol=1e-8): + """Convert the super path back to an svg path + + Arguments: see :func:`to_segments` for parameters""" + return Path(list(self.to_segments(curves_only, rtol, atol))) + + def to_segments(self, curves_only=False, rtol=1e-5, atol=1e-8): + """Generate a set of segments for this cubic super path + + Arguments: + curves_only (bool, optional): If False, curves that can be represented + by Lineto / ZoneClose commands, will be. Defaults to False. + rtol (float, optional): relative tolerance, passed to :func:`is_line` and + :func:`inkex.transforms.ImmutableVector2d.is_close` for checking if a + line can be replaced by a ZoneClose command. Defaults to 1e-5. + + .. versionadded:: 1.2 + atol: absolute tolerance, passed to :func:`is_line` and + :func:`inkex.transforms.ImmutableVector2d.is_close`. Defaults to 1e-8. + + .. versionadded:: 1.2""" + for subpath in self: + previous = [] + for segment in subpath: + if not previous: + yield Move(*segment[1][:]) + elif self.is_line(previous, segment, rtol, atol) and not curves_only: + if segment is subpath[-1] and Vector2d(segment[1]).is_close( + subpath[0][1], rtol, atol + ): + yield ZoneClose() + else: + yield Line(*segment[1][:]) + else: + yield Curve(*(previous[2][:] + segment[0][:] + segment[1][:])) + previous = segment + + def transform(self, transform): + """Apply a transformation matrix to this super path""" + return self.to_path().transform(transform).to_superpath() + + @staticmethod + def is_on(pt_a, pt_b, pt_c, tol=1e-8): + """Checks if point pt_a is on the line between points pt_b and pt_c + + .. versionadded:: 1.2""" + return CubicSuperPath.collinear(pt_a, pt_b, pt_c, tol) and ( + CubicSuperPath.within(pt_a[0], pt_b[0], pt_c[0]) + if pt_a[0] != pt_b[0] + else CubicSuperPath.within(pt_a[1], pt_b[1], pt_c[1]) + ) + + @staticmethod + def collinear(pt_a, pt_b, pt_c, tol=1e-8): + """Checks if points pt_a, pt_b, pt_c lie on the same line, + i.e. that the cross product (b-a) x (c-a) < tol + + .. versionadded:: 1.2""" + return ( + abs( + (pt_b[0] - pt_a[0]) * (pt_c[1] - pt_a[1]) + - (pt_c[0] - pt_a[0]) * (pt_b[1] - pt_a[1]) + ) + < tol + ) + + @staticmethod + def within(val_b, val_a, val_c): + """Checks if float val_b is between val_a and val_c + + .. versionadded:: 1.2""" + return val_a <= val_b <= val_c or val_c <= val_b <= val_a + + @staticmethod + def is_line(previous, segment, rtol=1e-5, atol=1e-8): + """Check whether csp segment (two points) can be expressed as a line has retracted handles or the handles + can be retracted without loss of information (i.e. both handles lie on the + line) + + .. versionchanged:: 1.2 + Previously, it was only checked if both control points have retracted + handles. Now it is also checked if the handles can be retracted without + (visible) loss of information (i.e. both handles lie on the line connecting + the nodes). + + Arguments: + previous: first node in superpath notation + segment: second node in superpath notation + rtol (float, optional): relative tolerance, passed to + :func:`inkex.transforms.ImmutableVector2d.is_close` for checking handle + retraction. Defaults to 1e-5. + + .. versionadded:: 1.2 + atol (float, optional): absolute tolerance, passed to + :func:`inkex.transforms.ImmutableVector2d.is_close` for checking handle + retraction and + :func:`inkex.paths.CubicSuperPath.is_on` for checking if all points + (nodes + handles) lie on a line. Defaults to 1e-8. + + .. versionadded:: 1.2 + """ + + retracted = Vector2d(previous[1]).is_close( + previous[2], rtol, atol + ) and Vector2d(segment[0]).is_close(segment[1], rtol, atol) + + if retracted: + return True + + # Can both handles be retracted without loss of information? + # Definitely the case if the handles lie on the same line as the two nodes and + # in the correct order + # E.g. cspbezsplitatlength outputs non-retracted handles when splitting a + # straight line + return CubicSuperPath.is_on( + segment[0], segment[1], previous[2], atol + ) and CubicSuperPath.is_on(previous[2], previous[1], segment[0], atol) + + +def arc_to_path(point, params): + """Approximates an arc with cubic bezier segments. + + Arguments: + point: Starting point (absolute coords) + params: Arcs parameters as per + https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands + + Returns a list of triplets of points : + [control_point_before, node, control_point_after] + (first and last returned triplets are [p1, p1, *] and [*, p2, p2]) + """ + + # pylint: disable=invalid-name, too-many-locals + A = point[:] + rx, ry, teta, longflag, sweepflag, x2, y2 = params[:] + teta = teta * pi / 180.0 + B = [x2, y2] + # Degenerate ellipse + if rx == 0 or ry == 0 or A == B: + return [[A[:], A[:], A[:]], [B[:], B[:], B[:]]] + + # turn coordinates so that the ellipse morph into a *unit circle* (not 0-centered) + mat = matprod((rotmat(teta), [[1.0 / rx, 0.0], [0.0, 1.0 / ry]], rotmat(-teta))) + applymat(mat, A) + applymat(mat, B) + + k = [-(B[1] - A[1]), B[0] - A[0]] + d = k[0] * k[0] + k[1] * k[1] + k[0] /= sqrt(d) + k[1] /= sqrt(d) + d = sqrt(max(0, 1 - d / 4.0)) + # k is the unit normal to AB vector, pointing to center O + # d is distance from center to AB segment (distance from O to the midpoint of AB) + # for the last line, remember this is a unit circle, and kd vector is ortogonal to + # AB (Pythagorean thm) + + if longflag == sweepflag: + # top-right ellipse in SVG example + # https://www.w3.org/TR/SVG/images/paths/arcs02.svg + d *= -1 + + O = [(B[0] + A[0]) / 2.0 + d * k[0], (B[1] + A[1]) / 2.0 + d * k[1]] + OA = [A[0] - O[0], A[1] - O[1]] + OB = [B[0] - O[0], B[1] - O[1]] + start = acos(OA[0] / norm(OA)) + if OA[1] < 0: + start *= -1 + end = acos(OB[0] / norm(OB)) + if OB[1] < 0: + end *= -1 + # start and end are the angles from center of the circle to A and to B respectively + + if sweepflag and start > end: + end += 2 * pi + if (not sweepflag) and start < end: + end -= 2 * pi + + NbSectors = int(abs(start - end) * 2 / pi) + 1 + dTeta = (end - start) / NbSectors + v = 4 * tan(dTeta / 4.0) / 3.0 + # I would use v = tan(dTeta/2)*4*(sqrt(2)-1)/3 ? + p = [] + for i in range(0, NbSectors + 1, 1): + angle = start + i * dTeta + v1 = [ + O[0] + cos(angle) - (-v) * sin(angle), + O[1] + sin(angle) + (-v) * cos(angle), + ] + pt = [O[0] + cos(angle), O[1] + sin(angle)] + v2 = [O[0] + cos(angle) - v * sin(angle), O[1] + sin(angle) + v * cos(angle)] + p.append([v1, pt, v2]) + p[0][0] = p[0][1][:] + p[-1][2] = p[-1][1][:] + + # go back to the original coordinate system + mat = matprod((rotmat(teta), [[rx, 0], [0, ry]], rotmat(-teta))) + for pts in p: + applymat(mat, pts[0]) + applymat(mat, pts[1]) + applymat(mat, pts[2]) + return p + + +def matprod(mlist): + """Get the product of the mat""" + prod = mlist[0] + for mat in mlist[1:]: + a00 = prod[0][0] * mat[0][0] + prod[0][1] * mat[1][0] + a01 = prod[0][0] * mat[0][1] + prod[0][1] * mat[1][1] + a10 = prod[1][0] * mat[0][0] + prod[1][1] * mat[1][0] + a11 = prod[1][0] * mat[0][1] + prod[1][1] * mat[1][1] + prod = [[a00, a01], [a10, a11]] + return prod + + +def rotmat(teta): + """Rotate the mat""" + return [[cos(teta), -sin(teta)], [sin(teta), cos(teta)]] + + +def applymat(mat, point): + """Apply the given mat""" + x = mat[0][0] * point[0] + mat[0][1] * point[1] + y = mat[1][0] * point[0] + mat[1][1] * point[1] + point[0] = x + point[1] = y + + +def norm(point): + """Normalise""" + return sqrt(point[0] * point[0] + point[1] * point[1]) diff --git a/share/extensions/inkex/ports.py b/share/extensions/inkex/ports.py new file mode 100644 index 0000000..7595231 --- /dev/null +++ b/share/extensions/inkex/ports.py @@ -0,0 +1,105 @@ +# coding=utf-8 +# +# Copyright (C) 2019 Martin Owens +# +# 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. +# +""" +Common access to serial and other computer ports. +""" + +import os +import sys +import time +from .utils import DependencyError, AbortExtension + +try: + import serial + from serial.tools import list_ports +except ImportError: + serial = None + + +class Serial: + """ + Attempt to get access to the computer's serial port. + + with Serial(port_name, ...) as com: + com.write(...) + + Provides access to the debug/testing ports which are pretend ports + able to accept the same input but allow for debugging. + """ + + def __init__(self, port, baud=9600, timeout=0.1, **options): + self.test = port == "[test]" + if self.test: + import pty # This does not work on windows #pylint: disable=import-outside-toplevel + + self.controller, self.peripheral = pty.openpty() + port = os.ttyname(self.peripheral) + + self.has_serial() + self.com = serial.Serial() + self.com.port = port + self.com.baudrate = int(baud) + self.com.timeout = timeout + self.set_options(**options) + + def set_options(self, stop=1, size=8, flow=None, parity=None): + """Set further options on the serial port""" + size = {5: "five", 6: "six", 7: "seven", 8: "eight"}.get(size, size) + stop = {"onepointfive": 1.5}.get(stop.lower(), stop) + stop = {1: "one", 1.5: "one_point_five", 2: "two"}.get(stop, stop) + self.com.bytesize = getattr(serial, str(str(size).upper()) + "BITS") + self.com.stopbits = getattr(serial, "STOPBITS_" + str(stop).upper()) + self.com.parity = getattr(serial, "PARITY_" + str(parity).upper()) + # set flow control + self.com.xonxoff = flow == "xonxoff" + self.com.rtscts = flow in ("rtscts", "dsrdtrrtscts") + self.com.dsrdtr = flow == "dsrdtrrtscts" + + def __enter__(self): + try: + # try to establish connection + self.com.open() + except serial.SerialException as error: + raise AbortExtension( + "Could not open serial port. Please check your device" + " is running, connected and the settings are correct" + ) from error + return self.com + + def __exit__(self, exc, value, traceback): + if not traceback and self.test: + output = " " * 1024 + while len(output) == 1024: + time.sleep(0.01) + output = os.read(self.controller, 1024) + sys.stderr.write(output.decode("utf8")) + # self.com.read(2) + self.com.close() + + @staticmethod + def has_serial(): + """Late importing of pySerial module""" + if serial is None: + raise DependencyError("pySerial is required to open serial ports.") + + @staticmethod + def list_ports(): + """Return a list of available serial ports""" + Serial.has_serial() # Cause DependencyError error + return [hw.name for hw in list_ports.comports(True)] diff --git a/share/extensions/inkex/properties.py b/share/extensions/inkex/properties.py new file mode 100644 index 0000000..713e288 --- /dev/null +++ b/share/extensions/inkex/properties.py @@ -0,0 +1,800 @@ +# coding=utf-8 +# +# Copyright (C) 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +""" +Property management and parsing, CSS cascading, default value storage + +.. versionadded:: 1.2 + +.. data:: all_properties + + A list of all properties, their parser class, and additional information + such as whether they are inheritable or can be given as presentation attributes +""" + +from abc import ABC, abstractmethod + +import re +from typing import Tuple, Dict, Type, Union, List, Optional +from .interfaces.IElement import IBaseElement, ISVGDocumentElement + +from .units import parse_unit, convert_unit + +from .colors import Color, ColorError + + +class BaseStyleValue: + """A class encapsuling a single CSS declaration / presentation_attribute""" + + def __init__(self, declaration=None, attr_name=None, value=None, important=False): + self.attr_name: str + self.value: str + self.important: bool + if declaration is not None and ":" in declaration: + ( + self.attr_name, + self.value, + self.important, + ) = BaseStyleValue.parse_declaration(declaration) + elif attr_name is not None: + self.attr_name = attr_name.strip().lower() + if isinstance(value, str): + self.value = value.strip() + else: + # maybe its already parsed? then set it + self.value = self.unparse_value(value) + self.important = important + _ = self.parse_value() # check that we can parse this value + + @classmethod + def parse_declaration(cls, declaration: str) -> Tuple[str, str, bool]: + """Parse a single css declaration + + Args: + declaration (str): a css declaration such as: + ``fill: #000 !important;``. The trailing semicolon may be ommitted. + + Raises: + ValueError: Unable to parse the declaration + + Returns: + Tuple[str, str, bool]: a tuple with key, value and importance + """ + if declaration != "" and ":" in declaration: + declaration = declaration.replace(";", "") + (name, value) = declaration.split(":", 1) + # check whether this is an important declaration + important = False + if "!important" in value: + value = value.replace("!important", "") + important = True + return (name.strip().lower(), value.strip(), important) + raise ValueError("Invalid declaration") + + def parse_value(self, element=None): + """Get parsed property value with resolved urls, color, etc. + + Args: + element (BaseElement): the SVG element to which this style is applied to + currently used for resolving gradients / masks, could be used for + computing percentage attributes or calc() attributes [optional] + + Returns: + object: parsed property value + """ + if self.value == "inherit": + if self.attr_name in all_properties: + return self._parse_value(all_properties[self.attr_name][1], element) + return None + return self._parse_value(self.value, element) + + def _parse_value( # pylint: disable=unused-argument, no-self-use + self, value: str, element=None + ) -> object: + """internal parse method, to be overwritten by derived classes + + Args: + value (str): unparsed value + element (BaseElement): the SVG element to which this style is applied to + [optional] + + Returns: + object: the parsed value + """ + return value + + def unparse_value(self, value: object) -> str: + """ "Unparses" an object, i.e. converts an object back to an attribute. + If the result is invalid, i.e. can't be parsed, an exception is raised. + + Args: + value (object): the object to be unparsed + + Returns: + str: the attribute value + """ + result = self._unparse_value(value) + self._parse_value(result) # check if value can be parsed (value is valid) + return result + + def _unparse_value(self, value: object) -> str: # pylint: disable=no-self-use + return str(value) + + @property + def declaration(self) -> str: + """The css declaration corresponding to the StyleValue object + + Returns: + str: the css declaration, such as "fill: #000 !important;" + """ + return ( + self.attr_name + + ":" + + self.value + + (" !important" if self.important else "") + ) + + @classmethod + def factory( + cls, + declaration: Optional[str] = None, + attr_name: Optional[str] = None, + value: Optional[object] = None, + important: Optional[bool] = False, + ): + """Create an attribute + + Args: + declaration (str, optional): the CSS declaration to parse. Defaults to None. + attr_name (str, optional): the attribute name. Defaults to None. + value (object, optional): the attribute value. Defaults to None. + important (bool, optional): whether the attribute is marked !important. + Defaults to False. + + Raises: + Errors may also be raised on parsing, so make sure to handle them + + Returns: + BaseStyleValue: the parsed style + """ + if declaration is not None and ":" in declaration: + attr_name, value, important = BaseStyleValue.parse_declaration(declaration) + elif attr_name is not None and value is not None: + attr_name = attr_name.strip().lower() + if isinstance(value, str): + value = value.strip() + + if attr_name in all_properties: + valuetype = all_properties[attr_name][0] + return valuetype(declaration, attr_name, value, important) + return BaseStyleValue(declaration, attr_name, value, important) + + def __eq__(self, other): + if not (isinstance(other, BaseStyleValue)): + return False + if self.declaration != other.declaration: + return False + return True + + @staticmethod + def factory_errorhandled(element=None, declaration="", key="", value=""): + """Error handling for the factory method: if something goes wrong during + parsing, ignore the attribute + + Args: + element (BaseElement, optional): The element this declaration is affecting, + for finding gradients ect. Defaults to None. + declaration (str, optional): the CSS declaration to parse. Defaults to "". + key (str, optional): the attribute name. Defaults to "". + value (str, optional): the attribute value. Defaults to "". + + Returns: + BaseStyleValue: The parsed style + """ + try: + value = BaseStyleValue.factory( + declaration=declaration, attr_name=key, value=value + ) + key = value.attr_name + # Try to parse the attribute + _ = value.parse_value(element) + return (key, value) + except ValueError: + # something went wrong during parsing, e.g. a bad attribute format + # or an attribute referencing a missing gradient + # -> ignore this declaration + pass + except ColorError: + # The color parsing methods have their own error type + pass + + +class AlphaValue(BaseStyleValue): + """Stores an alpha value (such as opacity), which may be specified as + as percentage or absolute value. + + Reference: https://www.w3.org/TR/css-color/#typedef-alpha-value""" + + def _parse_value(self, value: str, element=None): + if value[-1] == "%": # percentage + parsed_value = float(value[:-1]) * 0.01 + else: + parsed_value = float(value) + if parsed_value < 0: + return 0 + if parsed_value > 1: + return 1 + return parsed_value + + def _unparse_value(self, value: object) -> str: + if isinstance(value, (float, int)): + if value < 0: + return "0" + if value > 1: + return "1" + return str(value) + raise ValueError("Value must be number") + + +class ColorValue(BaseStyleValue): + """Stores a color value + + Reference: https://drafts.csswg.org/css-color-3/#valuea-def-color""" + + def _parse_value(self, value: str, element=None): + if value == "currentColor": + if element is not None: + style = element.specified_style() + return style("color") + return None + return Color(value) + + +# https://www.w3.org/TR/css3-values/#url-value +# matches anything inside url() enclosed with single/double quotes +# (technically a fragment url) or no quotes at all +URLREGEX = r"url\(\s*('.*?'|\".*?\"|[^\"'].*?)\s*\)" + + +def match_url_and_return_element(string: str, svg): + """Parses a string containing an url, e.g. "url(#rect1234)", + looks up the element in the svg document and returns it. + + Args: + string (str): the string to parse + svg (SvgDocumentElement): document referenced in the URL + + Raises: + ValueError: if the string has invalid format + ValueError: if the referenced element is not found + + Returns: + BaseElement: the referenced element + """ + regex = re.compile(URLREGEX) + match = regex.match(string) + if match: + url = match.group(1) + paint_server = svg.getElementById(url) + return paint_server + raise ValueError("invalid URL format") + + +class URLNoneValue(BaseStyleValue): + """Stores a value that is either none or an url, such as markers or masks. + + Reference: https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties""" + + def _parse_value(self, value: str, element=None): + if value == "none": + return None + if value[0:4] == "url(": + if element is not None and self.element_has_root(element): + return match_url_and_return_element(value, element.root) + return None + raise ValueError("Invalid property value") + + def _unparse_value(self, value: object): + if isinstance(value, IBaseElement): + return f"url(#{value.get_id()})" + return super()._unparse_value(value) + + @staticmethod + def element_has_root(element) -> bool: + "Checks if an element has a root, i.e. if element.root will fail" + + return not ( + element.getparent() is None and not isinstance(element, ISVGDocumentElement) + ) + + +class PaintValue(ColorValue, URLNoneValue): + """Stores a paint value (such as fill and stroke), which may be specified + as color, or url. + + Reference: https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint""" + + def _parse_value(self, value: str, element=None): + if value == "none": + return None + if value in ["context-fill", "context-stroke"]: + return value + if value == "currentColor": + return super()._parse_value(value, element) + if value[0:4] == "url(": + # First part: fragment url + # second part: a fallback color if the url is not found. Colors start with + # a letter or a # + regex = re.compile(URLREGEX + r"\s*([#\w].*?)?$") + match = regex.match(value) + if match: + url = match.group(1) + if element is not None and self.element_has_root(element): + paint_server = element.root.getElementById(url) + else: + return None + if paint_server is not None: + return paint_server + if match.group(2) is None: + raise ValueError("Paint server not found") + return Color(match.group(2)) + return Color(value) + + def _unparse_value(self, value: object): + if value is None: + return "none" + return super()._unparse_value(value) + + +class EnumValue(BaseStyleValue): + """Stores a value that can only have a finite set of options""" + + def __init__(self, declaration=None, attr_name=None, value=None, important=False): + self.valueset = all_properties[attr_name][4] + super().__init__(declaration, attr_name, value, important) + + def _parse_value(self, value: str, element=None): + if value in self.valueset: + return value + raise ValueError( + f"Value '{value}' is invalid for the property {self.attr_name}. " + + f"Allowed values are: {self.valueset + ['inherit']}" + ) + + +class ShorthandValue(BaseStyleValue, ABC): + """Stores a value that sets other values (e.g. the font shorthand)""" + + def apply_shorthand(self, style): + """Applies a shorthand attribute to its style, respecting the + importance state of the individual attributes. + + Args: + style (Style): the style that the shorthand attribute is contained in, + and that the shorthand attribute will be applied on + """ + if self.attr_name not in style: + return + + dct = self.get_shorthand_changes() + importance = self.important + + # they are ordered in the order of adding the style elements. + current_keys = list(style.keys()) + for curkey in dct: + perform = False + if curkey not in current_keys: + # this is the easiest case, just set the element and the importance + perform = True + else: + if importance != style.get_importance(curkey): + # different importance, result independent of position + perform = importance + else: + # only apply if style overwrites previous with same importance + perform = current_keys.index(curkey) < current_keys.index( + self.attr_name + ) + + if perform: + style[curkey] = dct[curkey] + style.set_importance(curkey, importance) + style.pop(self.attr_name) + + @abstractmethod + def get_shorthand_changes(self) -> Dict[str, str]: + """calculates the value of affected attributes for this shorthand + + Returns: + Dict[str, str]: a dictionary containing the new values of the + affected attributes + """ + + +class FontValue(ShorthandValue): + """Logic for the shorthand font property""" + + def get_shorthand_changes(self): + keys = [ + "font-style", + "font-variant", + "font-weight", + "font-stretch", + "font-size", + "line-height", + "font-family", + ] + options = { + key: all_properties[key][4] + for key in keys + if isinstance(all_properties[key][4], list) + } + result = {key: all_properties[key][1] for key in keys} + + tokens = [i for i in self.value.split(" ") if i != ""] + + if len(tokens) == 0: + return {} # shorthand not set, nothing to do + + while not (len(tokens) == 0): + cur = tokens[0] + if cur in options["font-style"]: + result["font-style"] = cur + elif cur in options["font-variant"]: + result["font-variant"] = cur + elif cur in options["font-weight"]: + result["font-weight"] = cur + elif cur in options["font-stretch"]: + result["font-stretch"] = cur + else: + if "/" in cur: + result["font-size"], result["line-height"] = cur.split("/") + else: + result["font-size"] = cur + result["font-family"] = " ".join(tokens[1:]) + break + tokens = tokens[1:] # remove first element + return result + + +class MarkerShorthandValue(ShorthandValue, URLNoneValue): + """Logic for the marker shorthand property""" + + def get_shorthand_changes(self): + if self.value == "": + return {} # shorthand not set, nothing to do + return {k: self.value for k in ["marker-start", "marker-end", "marker-mid"]} + + def _parse_value(self, value: str, element=None): + # Make sure the parsing routine doesn't choke on an empty shorthand + if value == "": + return "" + return super()._parse_value(value, element) + + +class FontSizeValue(BaseStyleValue): + """Logic for the font-size property""" + + def _parse_value(self, value: str, element=None): + if element is None: + return value # no additional logic in this case + try: + return element.to_dimensionless(value) + except ValueError: # unable to parse font size, e.g. font-size:normal + return element.to_dimensionless("12pt") + + +class StrokeDasharrayValue(BaseStyleValue): + """Logic for the stroke-dasharray property""" + + def _parse_value(self, value: str, element=None): + dashes = re.findall(r"[^,\s]+", value) + if len(dashes) == 0 or value == "none": + return None # no dasharray applied + if not any(parse_unit(i) is None for i in dashes): + dashes = [convert_unit(i, "px") for i in dashes] + else: + return None + if any(i < 0 for i in dashes): + return None # one negative value makes the dasharray invalid + if len(dashes) % 2 == 1: + dashes = 2 * dashes + return dashes + + def _unparse_value(self, value: object) -> str: + if value is None: + return "none" + if isinstance(value, list): + return " ".join(map(str, value)) + return str(value) + + +# keys: attributes, right side: +# - Subclass of BaseStyleValue used for instantiating +# - default value +# - is presentation attribute +# - inherited +# - additional information, such as valid enum values +# For properties which have no special implementation yet: +# "(BaseStyleValue, , , None)" + +# Source for this list: https://www.w3.org/TR/SVG2/styling.html#PresentationAttributes + + +all_properties: Dict[ + str, Tuple[Type[BaseStyleValue], str, bool, bool, Union[List[str], None]] +] = { + "alignment-baseline": ( + EnumValue, + "baseline", + True, + False, + [ + "baseline", + "text-bottom", + "alphabetic", + "ideographic", + "middle", + "central", + "mathematical", + "text-top", + ], + ), + "baseline-shift": (BaseStyleValue, "0", True, False, None), + "clip": (BaseStyleValue, "auto", True, False, None), + "clip-path": (URLNoneValue, "none", True, False, None), + "clip-rule": (EnumValue, "nonzero", True, True, ["nonzero", "evenodd"]), + # only used for currentColor, which is not yet implemented + "color": (PaintValue, "black", True, True, None), + "color-interpolation": ( + EnumValue, + "sRGB", + True, + True, + ["sRGB", "auto", "linearRGB"], + ), + "color-interpolation-filters": ( + EnumValue, + "linearRGB", + True, + True, + ["auto", "sRGB", "linearRGB"], + ), + "color-rendering": ( + EnumValue, + "auto", + True, + True, + ["auto", "optimizeSpeed", "optimizeQuality"], + ), + "cursor": (BaseStyleValue, "auto", True, True, None), + "direction": (EnumValue, "ltr", True, True, ["ltr", "rtl"]), + "display": ( + EnumValue, + "inline", + True, + False, + [ + "inline", + "block", + "list-item", + "inline-block", + "table", + "inline-table", + "table-row-group", + "table-header-group", + "table-footer-group", + "table-row", + "table-column-group", + "table-column", + "table-cell", + "table-caption", + "none", + ], + ), # every value except none is rendered normally + "dominant-baseline": ( + EnumValue, + "auto", + True, + True, + [ + "auto", + "text-bottom", + "alphabetic", + "ideographic", + "middle", + "central", + "mathematical", + "hanging", + "text-top", + ], + ), + "fill": ( + PaintValue, + "black", + True, + True, + None, + ), # the normal fill, not the one + "fill-opacity": (AlphaValue, "1", True, True, None), + "fill-rule": (EnumValue, "nonzero", True, True, ["nonzero", "evenodd"]), + "filter": (BaseStyleValue, "none", True, False, None), + "flood-color": (PaintValue, "black", True, False, None), + "flood-opacity": (AlphaValue, "1", True, False, None), + "font": (FontValue, "", True, False, None), + "font-family": (BaseStyleValue, "sans-serif", True, True, None), + "font-size": (FontSizeValue, "medium", True, True, None), + "font-size-adjust": (BaseStyleValue, "none", True, True, None), + "font-stretch": ( + EnumValue, + "normal", + True, + True, + [ + "normal", + "ultra-condensed", + "extra-condensed", + "condensed", + "semi-condensed", + "semi-expanded", + "expanded", + "extra-expanded", + "ultra-expanded", + ], + ), + "font-style": (EnumValue, "normal", True, True, ["normal", "italic", "oblique"]), + # a lot more values and subproperties in SVG2 / CSS-Fonts3 + "font-variant": (EnumValue, "normal", True, True, ["normal", "small-caps"]), + "font-weight": ( + EnumValue, + "normal", + True, + True, + ["normal", "bold"] + [str(i) for i in range(100, 901, 100)], + ), + "glyph-orientation-horizontal": (BaseStyleValue, "0deg", True, True, None), + "glyph-orientation-vertical": (BaseStyleValue, "auto", True, True, None), + "image-rendering": ( + EnumValue, + "auto", + True, + True, + ["auto", "optimizeQuality", "optimizeSpeed"], + ), + "letter-spacing": (BaseStyleValue, "normal", True, True, None), + "lighting-color": (ColorValue, "normal", True, False, None), + "line-height": (BaseStyleValue, "normal", False, True, None), + "marker": (MarkerShorthandValue, "", True, True, None), + "marker-end": (URLNoneValue, "none", True, True, None), + "marker-mid": (URLNoneValue, "none", True, True, None), + "marker-start": (URLNoneValue, "none", True, True, None), + # is a shorthand for a lot of mask-related properties which Inkscape doesn't support + "mask": (URLNoneValue, "none", True, False, None), + "opacity": (AlphaValue, "1", True, False, None), + "overflow": ( + EnumValue, + "visible", + True, + False, + ["visible", "hidden", "scroll", "auto"], + ), + "paint-order": (BaseStyleValue, "normal", True, False, None), + "pointer-events": ( + EnumValue, + "visiblePainted", + True, + True, + [ + "bounding-box", + "visiblePainted", + "visibleFill", + "visibleStroke", + "visible", + "painted", + "fill", + "stroke", + "all", + "none", + ], + ), + "shape-rendering": ( + EnumValue, + "visiblePainted", + True, + True, + ["auto", "optimizeSpeed", "crispEdges", "geometricPrecision"], + ), + "stop-color": (ColorValue, "black", True, False, None), + "stop-opacity": (AlphaValue, "1", True, False, None), + "stroke": (PaintValue, "none", True, True, None), + "stroke-dasharray": (StrokeDasharrayValue, "none", True, True, None), + "stroke-dashoffset": (BaseStyleValue, "0", True, True, None), + "stroke-linecap": (EnumValue, "butt", True, True, ["butt", "round", "square"]), + "stroke-linejoin": ( + EnumValue, + "miter", + True, + True, + ["miter", "miter-clip", "round", "bevel", "arcs"], + ), + "stroke-miterlimit": (BaseStyleValue, "4", True, True, None), + "stroke-opacity": (AlphaValue, "1", True, True, None), + "stroke-width": (BaseStyleValue, "1", True, True, None), + "text-align": ( + BaseStyleValue, + "start", + True, + True, + None, + ), # only HTML property, but used by some unit tests + "text-anchor": (EnumValue, "start", True, True, ["start", "middle", "end"]), + # shorthand for text-decoration-line, *-style, *-color + "text-decoration": (BaseStyleValue, "none", True, True, None), + "text-overflow": (EnumValue, "clip", True, False, ["clip", "ellipsis"]), + "text-rendering": ( + EnumValue, + "auto", + True, + True, + ["auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision"], + ), + "unicode-bidi": ( + EnumValue, + "normal", + True, + False, + [ + "normal", + "embed", + "isolate", + "bidi-override", + "isolate-override", + "plaintext", + ], + ), + "vector-effect": (BaseStyleValue, "none", True, False, None), + "vertical-align": (BaseStyleValue, "baseline", False, False, None), + "visibility": (EnumValue, "visible", True, True, ["visible", "hidden", "collapse"]), + "white-space": ( + EnumValue, + "normal", + True, + True, + ["normal", "pre", "nowrap", "pre-wrap", "break-spaces", "pre-line"], + ), + "word-spacing": (BaseStyleValue, "normal", True, True, None), + # including obsolete SVG 1.1 values + "writing-mode": ( + EnumValue, + "horizontal-tb", + True, + True, + [ + "horizontal-tb", + "vertical-rl", + "vertical-lr", + "lr", + "lr-tb", + "rl", + "rl-tb", + "tb", + "tb-rl", + ], + ), + "-inkscape-font-specification": (BaseStyleValue, "sans-serif", False, True, None), +} diff --git a/share/extensions/inkex/styles.py b/share/extensions/inkex/styles.py new file mode 100644 index 0000000..ae0d334 --- /dev/null +++ b/share/extensions/inkex/styles.py @@ -0,0 +1,621 @@ +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# 2019-2020 Martin Owens +# 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +""" +Functions for handling styles and embedded css +""" + +import re +from collections import OrderedDict +from typing import MutableMapping, Union, Iterable, TYPE_CHECKING + +from .interfaces.IElement import IBaseElement + +from .colors import Color +from .properties import BaseStyleValue, all_properties, ShorthandValue +from .css import ConditionalRule + +if TYPE_CHECKING: + from .elements._svg import SvgDocumentElement + + +class Classes(list): + """A list of classes applied to an element (used in css and js)""" + + def __init__(self, classes=None, callback=None): + self.callback = None + if isinstance(classes, str): + classes = classes.split() + super().__init__(classes or ()) + self.callback = callback + + def __str__(self): + return " ".join(self) + + def _callback(self): + if self.callback is not None: + self.callback(self) + + def __setitem__(self, index, value): + super().__setitem__(index, value) + self._callback() + + def append(self, value): + value = str(value) + if value not in self: + super().append(value) + self._callback() + + def remove(self, value): + value = str(value) + if value in self: + super().remove(value) + self._callback() + + def toggle(self, value): + """If exists, remove it, if not, add it""" + value = str(value) + if value in self: + return self.remove(value) + return self.append(value) + + +class Style(OrderedDict, MutableMapping[str, Union[str, BaseStyleValue]]): + """A list of style directives + + .. versionchanged:: 1.2 + The Style API now allows for access to parsed / processed styles via the + :func:`call` method. + + .. automethod:: __call__ + .. automethod:: __getitem__ + .. automethod:: __setitem__ + """ + + color_props = ("stroke", "fill", "stop-color", "flood-color", "lighting-color") + opacity_props = ("stroke-opacity", "fill-opacity", "opacity", "stop-opacity") + unit_props = "stroke-width" + """Dictionary of attributes with units. + + ..versionadded:: 1.2 + """ + associated_props = { + "fill": "fill-opacity", + "stroke": "stroke-opacity", + "stop-color": "stop-opacity", + } + """Dictionary of association between color and opacity attributes. + + .. versionadded:: 1.2 + """ + + def __init__(self, style=None, callback=None, element=None, **kw): + self.element = element + # This callback is set twice because this is 'pre-initial' data (no callback) + self.callback = None + # Either a string style or kwargs (with dashes as underscores). + style = style or [(k.replace("_", "-"), v) for k, v in kw.items()] + if isinstance(style, str): + style = self._parse_str(style) + # Order raw dictionaries so tests can be made reliable + if isinstance(style, dict) and not isinstance(style, OrderedDict): + style = [(name, style[name]) for name in sorted(style)] + # Should accept dict, Style, parsed string, list etc. + super().__init__(style) + # Now after the initial data, the callback makes sense. + self.callback = callback + + @staticmethod + def _parse_str(style: str, element=None) -> Iterable[BaseStyleValue]: + """Create a dictionary from the value of a CSS rule (such as an inline style or + from an embedded style sheet), including its !important state, parsing the value + if possible. + + Args: + style: the content of a CSS rule to parse + element: the element this style is working on (can be the root SVG, is used + for parsing gradients etc.) + + Yields: + :class:`~inkex.properties.BaseStyleValue`: the parsed attribute + """ + for declaration in style.split(";"): + if ":" in declaration: + result = BaseStyleValue.factory_errorhandled( + element, declaration=declaration.strip() + ) + if result is not None: + yield result + + @staticmethod + def parse_str(style: str, element=None): + """Parse a style passed as string""" + return Style(style, element=element) + + def __str__(self): + """Format an inline style attribute from a dictionary""" + return self.to_str() + + def to_str(self, sep=";"): + """Convert to string using a custom delimiter""" + return sep.join([self.get_store(key).declaration for key in self]) + + def __add__(self, other): + """Add two styles together to get a third, composing them""" + ret = self.copy() + ret.update(Style(other)) + return ret + + def __iadd__(self, other): + """Add style to this style, the same as ``style.update(dict)``""" + self.update(other) + return self + + def __sub__(self, other): + """Remove keys and return copy""" + ret = self.copy() + ret.__isub__(other) + return ret + + def __isub__(self, other): + """Remove keys from this style, list of keys or other style dictionary""" + for key in other: + self.pop(key, None) + return self + + def __ne__(self, other): + return not self.__eq__(other) + + def copy(self): + """Create a copy of the style. + + .. versionadded:: 1.2""" + ret = Style({}, element=self.element) + for key, value in super().items(): + ret[key] = value + return ret + + def update(self, other): + """Update, while respecting ``!important`` declarations.""" + if not isinstance(other, Style): + other = Style(other) + # only update + if isinstance(other, Style): + for key in other.keys(): + if not (self.get_importance(key) and not other.get_importance(key)): + self[key] = other.get_store(key) + + if self.callback is not None: + self.callback(self) + + def add_inherited(self, parent): + """Creates a new Style containing all parent styles with importance "!important" + and current styles with importance "!important" + + .. versionadded:: 1.2 + + Args: + parent: the parent style that will be merged into this one (will not be + altered) + + Returns: + Style: the merged Style object + """ + ret = self.copy() + ret.apply_shorthands() # parent should already have its shortcuts applied + + if not (isinstance(parent, Style)): + return ret + + for key in parent.keys(): + apply = False + if key in all_properties and all_properties[key][3]: + # only set parent value if value is not set or parent importance is + # higher + if key not in ret: + apply = True + elif self.get_importance(key) != parent.get_importance(key): + apply = parent.get_importance(key) + if key in ret and ret[key] == "inherit": + apply = True + if apply: + ret[key] = parent[key] + return ret + + def apply_shorthands(self): + """Apply all shorthands in this style.""" + for element in list(self.values()): + if isinstance(element, ShorthandValue): + element.apply_shorthand(self) + + def __delitem__(self, key): + super().__delitem__(key) + if self.callback is not None: + self.callback(self) + + def __setitem__(self, key, value): + """Sets a style value. + + .. versionchanged:: 1.2 + ``value`` can now also be non-string objects such as a Gradient. + + Args: + key (str): the attribute name + value (Any): + + - a :class:`BaseStyleValue` + - a string with the value + - any other object. The :class:`~inkex.properties.BaseStyleValue` + subclass of the provided key will attempt to create a string out of + the passed value. + Raises: + ValueError: when ``value`` is a :class:`~inkex.properties.BaseStyleValue` + for a different attribute than `key` + Error: Other exceptions may be raised when converting non-string objects.""" + if not isinstance(value, BaseStyleValue) or value is None: + # try to convert the value using the factory + value = BaseStyleValue.factory(attr_name=key, value=value) + # check if the set attribute is valid + _ = value.parse_value(self.element) + elif key != value.attr_name: + raise ValueError( + """You're trying to save a value into a style attribute, but the + provided key is different from the attribute name given in the value""" + ) + super().__setitem__(key, value) + if self.callback is not None: + self.callback(self) + + def __getitem__(self, key): + """Returns the unparsed value of the element (minus a possible ``!important``) + + .. versionchanged:: 1.2 + ``!important`` is removed from the value. + """ + return self.get_store(key).value + + def get(self, key, default=None): + if key in self: + return self.__getitem__(key) + return default + + def get_store(self, key): + """Gets the :class:`~inkex.properties.BaseStyleValue` of this key, since the + other interfaces - :func:`__getitem__` and :func:`__call__` - return the + original and parsed value, respectively. + + .. versionadded:: 1.2 + + Args: + key (str): the attribute name + + Returns: + BaseStyleValue: the BaseStyleValue struct of this attribute + """ + return super().__getitem__(key) + + def __call__(self, key, element=None): + """Return the parsed value of a style. Optionally, an element can be passed + that will be used to find gradient definitions ect. + + .. versionadded:: 1.2""" + # check if there are shorthand properties defined. If so, apply them to a copy + copy = self + for value in super().values(): + if isinstance(value, ShorthandValue): + copy = self.copy() + copy.apply_shorthands() + if key in copy: + return copy.get_store(key).parse_value(element or self.element) + # style is not set, return the default value + if key in all_properties: + defvalue = BaseStyleValue.factory( + attr_name=key, value=all_properties[key][1] + ) + return ( + defvalue.parse_value() + ) # default values are independent of the element + raise KeyError("Unknown attribute") + + def __eq__(self, other): + if not isinstance(other, Style): + other = Style(other) + if self.keys() != other.keys(): + return False + for arg in set(self) | set(other): + if self.get_store(arg) != other.get_store(arg): + return False + return True + + def items(self): + """The styles's parsed items + + .. versionadded:: 1.2""" + for key, value in super().items(): + yield key, value.value + + def get_importance(self, key, default=False): + """Returns whether the declaration with ``key`` is marked as ``!important`` + + .. versionadded:: 1.2""" + if key in self: + return super().__getitem__(key).important + return default + + def set_importance(self, key, importance): + """Sets the ``!important`` state of a declaration with key ``key`` + + .. versionadded:: 1.2""" + if key in self: + super().__getitem__(key).important = importance + else: + raise KeyError() + if self.callback is not None: + self.callback(self) + + def get_color(self, name="fill"): + """Get the color AND opacity as one Color object""" + color = Color(self.get(name, "none")) + return color.to_rgba(self.get(name + "-opacity", 1.0)) + + def set_color(self, color, name="fill"): + """Sets the given color AND opacity as rgba to the fill or stroke style + properties.""" + color = Color(color) + if color.space == "rgba" and name in Style.associated_props: + self[Style.associated_props[name]] = color.alpha + self[name] = color.to_rgb() + else: + self[name] = color + + def update_urls(self, old_id, new_id): + """Find urls in this style and replace them with the new id""" + for (name, value) in self.items(): + if value == f"url(#{old_id})": + self[name] = f"url(#{new_id})" + + def interpolate(self, other, fraction): + # type: (Style, Style, float) -> Style + """Interpolate all properties. + + .. versionadded:: 1.1""" + from .tween import StyleInterpolator + from inkex.elements import PathElement + + if self.element is None: + self.element = PathElement(style=str(self)) + if other.element is None: + other.element = PathElement(style=str(other)) + return StyleInterpolator(self.element, other.element).interpolate(fraction) + + @classmethod + def cascaded_style(cls, element): + """Returns the cascaded style of an element (all rules that apply the element + itself), based on the stylesheets, the presentation attributes and the inline + style using the respective specificity of the style + + see https://www.w3.org/TR/CSS22/cascade.html#cascading-order + + .. versionadded:: 1.2 + + Args: + element (BaseElement): the element that the cascaded style will be + computed for + + Returns: + Style: the cascaded style + """ + styles = list(element.root.stylesheets.lookup_specificity(element.get_id())) + + # presentation attributes have specificity 0, + # see https://www.w3.org/TR/SVG/styling.html#PresentationAttributes + styles.append([element.presentation_style(), (0, 0, 0)]) + + # would be (1, 0, 0, 0), but then we'd have to extend every entry + styles.append([element.style, (float("inf"), 0, 0)]) + + # sort styles by specificity (ascending, so when overwriting it's correct) + styles = sorted(styles, key=lambda item: item[1]) + + result = styles[0][0].copy() + for style, _ in styles[1:]: + result.update(style) + result.element = element + return result + + @classmethod + def specified_style(cls, element): + """Returns the specified style of an element, i.e. the cascaded style + + inheritance, see https://www.w3.org/TR/CSS22/cascade.html#specified-value + + .. versionadded:: 1.2 + + Args: + element (BaseElement): the element that the specified style will be computed + for + + Returns: + Style: the specified style + """ + + # We currently dont treat the case where parent=absolute value and + # element=relative value, i.e. specified = relative * absolute. + cascaded = Style.cascaded_style(element) + + parent = element.getparent() + + if parent is not None and isinstance(parent, IBaseElement): + cascaded = Style.add_inherited(cascaded, parent.specified_style()) + cascaded.element = element + return cascaded # doesn't have a parent + + +class StyleSheets(list): + """ + Special mechanism which contains all the stylesheets for an svg document + while also caching lookups for specific elements. + + This caching is needed because data can't be attached to elements as they are + re-created on the fly by lxml so lookups have to be centralised. + """ + + def __init__(self, svg=None): + super().__init__() + self.svg = svg + + def lookup(self, element_id, svg=None): + """ + Find all styles for this element. + """ + # This is aweful, but required because we can't know for sure + # what might have changed in the xml tree. + if svg is None: + svg = self.svg + for sheet in self: + for style in sheet.lookup(element_id, svg=svg): + yield style + + def lookup_specificity(self, element_id, svg=None): + """ + Find all styles for this element and return the specificity of the match. + + .. versionadded:: 1.2 + """ + # This is aweful, but required because we can't know for sure + # what might have changed in the xml tree. + if svg is None: + svg = self.svg + for sheet in self: + for style in sheet.lookup_specificity(element_id, svg=svg): + yield style + + +class StyleSheet(list): + """ + A style sheet, usually the CDATA contents of a style tag, but also + a css file used with a css. Will yield multiple Style() classes. + """ + + comment_strip = re.compile(r"(\/\/.*?\n)|(\/\*.*?\*\/)|@.*;") + + def __init__(self, content=None, callback=None): + super().__init__() + self.callback = None + # Remove comments + content = self.comment_strip.sub("", (content or "")) + # Parse rules + for block in content.split("}"): + if block: + self.append(block) + self.callback = callback + + def __str__(self): + return "\n" + "\n".join([str(style) for style in self]) + "\n" + + def _callback(self, style=None): # pylint: disable=unused-argument + if self.callback is not None: + self.callback(self) + + def add(self, rule, style): + """Append a rule and style combo to this stylesheet""" + self.append( + ConditionalStyle(rules=rule, style=str(style), callback=self._callback) + ) + + def append(self, other): + """Make sure callback is called when updating""" + if isinstance(other, str): + if "{" not in other: + return # Warning? + rules, style = other.strip("}").split("{", 1) + if rules.strip().startswith("@"): # ignore @font-face and @import + return + other = ConditionalStyle( + rules=rules, style=style.strip(), callback=self._callback + ) + super().append(other) + self._callback() + + def lookup(self, element_id, svg): + """Lookup the element_id against all the styles in this sheet""" + for style in self: + for elem in svg.xpath(style.to_xpath()): + if elem.get("id", None) == element_id: + yield style + + def lookup_specificity(self, element_id, svg): + """Lookup the element_id against all the styles in this sheet + and return the specificity of the match + + Args: + element_id (str): the id of the element that styles are being queried for + svg (SvgDocumentElement): The document that contains both element and the + styles + + Yields: + Tuple[ConditionalStyle, Tuple[int, int, int]]: all matched styles and the + specificity of the match + """ + for style in self: + for rule, spec in zip(style.to_xpaths(), style.get_specificities()): + for elem in svg.xpath(rule): + if elem.get("id", None) == element_id: + yield (style, spec) + + +class ConditionalStyle(Style): + """ + Just like a Style object, but includes one or more + conditional rules which places this style in a stylesheet + rather than being an attribute style. + """ + + def __init__(self, rules="*", style=None, callback=None, **kwargs): + super().__init__(style=style, callback=callback, **kwargs) + self.rules = [ConditionalRule(rule) for rule in rules.split(",")] + + def __str__(self): + """Return this style as a css entry with class""" + content = self.to_str(";\n ") + rules = ",\n".join(str(rule) for rule in self.rules) + if content: + return f"{rules} {{\n {content};\n}}" + return f"{rules} {{}}" + + def to_xpath(self): + """Convert all rules to an xpath""" + # This can be converted to cssselect.CSSSelector (lxml.cssselect) later if we + # have coverage problems. The main reason we're not is that cssselect is doing + # exactly this xpath transform and provides no extra functionality for reverse + # lookups. + return "|".join(self.to_xpaths()) + + def to_xpaths(self): + """Gets a list of xpaths for all rules of this ConditionalStyle + + .. versionadded:: 1.2""" + return [rule.to_xpath() for rule in self.rules] + + def get_specificities(self): + """Gets an iterator of the specificity of all rules in this ConditionalStyle + + .. versionadded:: 1.2""" + for rule in self.rules: + yield rule.get_specificity() diff --git a/share/extensions/inkex/tester/__init__.py b/share/extensions/inkex/tester/__init__.py new file mode 100644 index 0000000..f7e1d4b --- /dev/null +++ b/share/extensions/inkex/tester/__init__.py @@ -0,0 +1,437 @@ +# coding=utf-8 +# +# Copyright (C) 2018-2019 Martin Owens +# 2019 Thomas Holder +# +# 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, USA. +# +""" +Testing module. See :ref:`unittests` for details. +""" + +import os +import re +import sys +import shutil +import tempfile +import hashlib +import random +import uuid +from typing import List, Union, Tuple, Type, TYPE_CHECKING + +from io import BytesIO, StringIO +import xml.etree.ElementTree as xml + +from unittest import TestCase as BaseCase +from inkex.base import InkscapeExtension + +from .. import Transform +from ..utils import to_bytes +from .xmldiff import xmldiff +from .mock import MockCommandMixin, Capture + +if TYPE_CHECKING: + from .filters import Compare + +COMPARE_DELETE, COMPARE_CHECK, COMPARE_WRITE, COMPARE_OVERWRITE = range(4) + + +class NoExtension(InkscapeExtension): # pylint: disable=too-few-public-methods + """Test case must specify 'self.effect_class' to assertEffect.""" + + def __init__(self, *args, **kwargs): # pylint: disable=super-init-not-called + raise NotImplementedError(self.__doc__) + + def run(self, args=None, output=None): + """Fake run""" + + +class TestCase(MockCommandMixin, BaseCase): + """ + Base class for all effects tests, provides access to data_files and + test_without_parameters + """ + + effect_class = NoExtension # type: Type[InkscapeExtension] + effect_name = property(lambda self: self.effect_class.__module__) + + # If set to true, the output is not expected to be the stdout SVG document, but + # rather text or a message sent to the stderr, this is highly weird. But sometimes + # happens. + stderr_output = False + stdout_protect = True + stderr_protect = True + + def __init__(self, *args, **kw): + super().__init__(*args, **kw) + self._temp_dir = None + self._effect = None + + def setUp(self): # pylint: disable=invalid-name + """Make sure every test is seeded the same way""" + self._effect = None + super().setUp() + random.seed(0x35F) + + def tearDown(self): + super().tearDown() + if self._temp_dir and os.path.isdir(self._temp_dir): + shutil.rmtree(self._temp_dir) + + @classmethod + def __file__(cls): + """Create a __file__ property which acts much like the module version""" + return os.path.abspath(sys.modules[cls.__module__].__file__) + + @classmethod + def _testdir(cls): + """Get's the folder where the test exists (so data can be found)""" + return os.path.dirname(cls.__file__()) + + @classmethod + def rootdir(cls): + """Return the full path to the extensions directory""" + return os.path.dirname(cls._testdir()) + + @classmethod + def datadir(cls): + """Get the data directory (can be over-ridden if needed)""" + return os.path.join(cls._testdir(), "data") + + @property + def tempdir(self): + """Generate a temporary location to store files""" + if self._temp_dir is None: + self._temp_dir = os.path.realpath(tempfile.mkdtemp(prefix="inkex-tests-")) + if not os.path.isdir(self._temp_dir): + raise IOError("The temporary directory has disappeared!") + return self._temp_dir + + def temp_file( + self, prefix="file-", template="{prefix}{name}{suffix}", suffix=".tmp" + ): + """Generate the filename of a temporary file""" + filename = template.format(prefix=prefix, suffix=suffix, name=uuid.uuid4().hex) + return os.path.join(self.tempdir, filename) + + @classmethod + def data_file(cls, filename, *parts, check_exists=True): + """Provide a data file from a filename, can accept directories as arguments. + + .. versionchanged:: 1.2 + ``check_exists`` parameter added""" + if os.path.isabs(filename): + # Absolute root was passed in, so we trust that (it might be a tempdir) + full_path = os.path.join(filename, *parts) + else: + # Otherwise we assume it's relative to the test data dir. + full_path = os.path.join(cls.datadir(), filename, *parts) + + if not os.path.isfile(full_path) and check_exists: + raise IOError(f"Can't find test data file: {full_path}") + return full_path + + @property + def empty_svg(self): + """Returns a common minimal svg file""" + return self.data_file("svg", "default-inkscape-SVG.svg") + + def assertAlmostTuple( + self, found, expected, precision=8, msg="" + ): # pylint: disable=invalid-name + """ + Floating point results may vary with computer architecture; use + assertAlmostEqual to allow a tolerance in the result. + """ + self.assertEqual(len(found), len(expected), msg) + for fon, exp in zip(found, expected): + self.assertAlmostEqual(fon, exp, precision, msg) + + def assertEffectEmpty(self, effect, **kwargs): # pylint: disable=invalid-name + """Assert calling effect without any arguments""" + self.assertEffect(effect=effect, **kwargs) + + def assertEffect(self, *filename, **kwargs): # pylint: disable=invalid-name + """Assert an effect, capturing the output to stdout. + + filename should point to a starting svg document, default is empty_svg + """ + if filename: + data_file = self.data_file(*filename) + else: + data_file = self.empty_svg + + os.environ["DOCUMENT_PATH"] = data_file + args = [data_file] + list(kwargs.pop("args", [])) + args += [f"--{kw[0]}={kw[1]}" for kw in kwargs.items()] + + effect = kwargs.pop("effect", self.effect_class)() + + # Output is redirected to this string io buffer + if self.stderr_output: + with Capture("stderr") as stderr: + effect.run(args, output=BytesIO()) + effect.test_output = stderr + else: + output = BytesIO() + with Capture( + "stdout", kwargs.get("stdout_protect", self.stdout_protect) + ) as stdout: + with Capture( + "stderr", kwargs.get("stderr_protect", self.stderr_protect) + ) as stderr: + effect.run(args, output=output) + self.assertEqual( + "", stdout.getvalue(), "Extra print statements detected" + ) + self.assertEqual( + "", stderr.getvalue(), "Extra error or warnings detected" + ) + effect.test_output = output + + if os.environ.get("FAIL_ON_DEPRECATION", False): + warnings = getattr(effect, "warned_about", set()) + effect.warned_about = set() # reset for next test + self.assertFalse(warnings, "Deprecated API is still being used!") + + return effect + + # pylint: disable=invalid-name + def assertDeepAlmostEqual(self, first, second, places=None, msg=None, delta=None): + """Asserts that two objects, possible nested lists, are almost equal.""" + if delta is None and places is None: + places = 7 + if isinstance(first, (list, tuple)): + assert len(first) == len(second) + for (f, s) in zip(first, second): + self.assertDeepAlmostEqual(f, s, places, msg, delta) + else: + self.assertAlmostEqual(first, second, places, msg, delta) + + def assertTransformEqual(self, lhs, rhs, places=7): + """Assert that two transform expressions evaluate to the same + transformation matrix. + + .. versionadded:: 1.1 + """ + self.assertAlmostTuple( + tuple(Transform(lhs).to_hexad()), tuple(Transform(rhs).to_hexad()), places + ) + + # pylint: enable=invalid-name + + @property + def effect(self): + """Generate an effect object""" + if self._effect is None: + self._effect = self.effect_class() + return self._effect + + +class InkscapeExtensionTestMixin: + """Automatically setup self.effect for each test and test with an empty svg""" + + def setUp(self): # pylint: disable=invalid-name + """Check if there is an effect_class set and create self.effect if it is""" + super().setUp() + if self.effect_class is None: + self.skipTest("self.effect_class is not defined for this this test") + + def test_default_settings(self): + """Extension works with empty svg file""" + self.effect.run([self.empty_svg]) + + +class ComparisonMixin: + """ + Add comparison tests to any existing test suite. + """ + + compare_file: Union[List[str], Tuple[str], str] = "svg/shapes.svg" + """This input svg file sent to the extension (if any)""" + + compare_filters = [] # type: List[Compare] + """The ways in which the output is filtered for comparision (see filters.py)""" + + compare_filter_save = False + """If true, the filtered output will be saved and only applied to the + extension output (and not to the reference file)""" + + comparisons = [ + (), + ("--id=p1", "--id=r3"), + ] + """A list of comparison runs, each entry will cause the extension to be run.""" + + compare_file_extension = "svg" + + @property + def _compare_file_extension(self): + """The default extension to use when outputting check files in COMPARE_CHECK + mode.""" + if self.stderr_output: + return "txt" + return self.compare_file_extension + + def test_all_comparisons(self): + """Testing all comparisons""" + if not isinstance(self.compare_file, (list, tuple)): + self._test_comparisons(self.compare_file) + else: + for compare_file in self.compare_file: + self._test_comparisons( + compare_file, addout=os.path.basename(compare_file) + ) + + def _test_comparisons(self, compare_file, addout=None): + for args in self.comparisons: + self.assertCompare( + compare_file, + self.get_compare_cmpfile(args, addout), + args, + ) + + def assertCompare( + self, infile, cmpfile, args, outfile=None + ): # pylint: disable=invalid-name + """ + Compare the output of a previous run against this one. + + Args: + infile: The filename of the pre-processed svg (or other type of file) + cmpfile: The filename of the data we expect to get, if not set + the filename will be generated from the effect name and kwargs. + args: All the arguments to be passed to the effect run + outfile: Optional, instead of returning a regular output, this extension + dumps it's output to this filename instead. + + """ + compare_mode = int(os.environ.get("EXPORT_COMPARE", COMPARE_DELETE)) + + effect = self.assertEffect(infile, args=args) + + if cmpfile is None: + cmpfile = self.get_compare_cmpfile(args) + + if not os.path.isfile(cmpfile) and compare_mode == COMPARE_DELETE: + raise IOError( + f"Comparison file {cmpfile} not found, set EXPORT_COMPARE=1 to create " + "it." + ) + + if outfile: + if not os.path.isabs(outfile): + outfile = os.path.join(self.tempdir, outfile) + self.assertTrue( + os.path.isfile(outfile), f"No output file created! {outfile}" + ) + with open(outfile, "rb") as fhl: + data_a = fhl.read() + else: + data_a = effect.test_output.getvalue() + + write_output = None + if compare_mode == COMPARE_CHECK: + _file = cmpfile[:-4] if cmpfile.endswith(".out") else cmpfile + write_output = f"{_file}.{self._compare_file_extension}" + elif ( + compare_mode == COMPARE_WRITE and not os.path.isfile(cmpfile) + ) or compare_mode == COMPARE_OVERWRITE: + write_output = cmpfile + + try: + if write_output and not os.path.isfile(cmpfile): + raise AssertionError(f"Check the output: {write_output}") + with open(cmpfile, "rb") as fhl: + data_b = self._apply_compare_filters(fhl.read(), False) + self._base_compare(data_a, data_b, compare_mode) + except AssertionError: + if write_output: + if isinstance(data_a, str): + data_a = data_a.encode("utf-8") + with open(write_output, "wb") as fhl: + fhl.write(self._apply_compare_filters(data_a, True)) + print(f"Written output: {write_output}") + # This only reruns if the original test failed. + # The idea here is to make sure the new output file is "stable" + # Because some tests can produce random changes and we don't + # want test authors to be too reassured by a simple write. + if write_output == cmpfile: + effect = self.assertEffect(infile, args=args) + self._base_compare(data_a, cmpfile, COMPARE_CHECK) + if not write_output == cmpfile: + raise + + def _base_compare(self, data_a, data_b, compare_mode): + data_a = self._apply_compare_filters(data_a) + + if ( + isinstance(data_a, bytes) + and isinstance(data_b, bytes) + and data_a.startswith(b"<") + and data_b.startswith(b"<") + ): + # Late importing + diff_xml, delta = xmldiff(data_a, data_b) + if not delta and compare_mode == COMPARE_DELETE: + print( + "The XML is different, you can save the output using the " + "EXPORT_COMPARE envionment variable. Set it to 1 to save a file " + "you can check, set it to 3 to overwrite this comparison, setting " + "the new data as the correct one.\n" + ) + diff = "SVG Differences\n\n" + if os.environ.get("XML_DIFF", False): + diff = "<- " + diff_xml + else: + for x, (value_a, value_b) in enumerate(delta): + try: + # Take advantage of better text diff in testcase's own asserts. + self.assertEqual(value_a, value_b) + except AssertionError as err: + diff += f" {x}. {str(err)}\n" + self.assertTrue(delta, diff) + else: + # compare any content (non svg) + self.assertEqual(data_a, data_b) + + def _apply_compare_filters(self, data, is_saving=None): + data = to_bytes(data) + # Applying filters flips depending if we are saving the filtered content + # to disk, or filtering during the test run. This is because some filters + # are destructive others are useful for diagnostics. + if is_saving is self.compare_filter_save or is_saving is None: + for cfilter in self.compare_filters: + data = cfilter(data) + return data + + def get_compare_cmpfile(self, args, addout=None): + """Generate an output file for the arguments given""" + if addout is not None: + args = list(args) + [str(addout)] + opstr = ( + "__".join(args) + .replace(self.tempdir, "TMP_DIR") + .replace(self.datadir(), "DAT_DIR") + ) + opstr = re.sub(r"[^\w-]", "__", opstr) + if opstr: + if len(opstr) > 127: + # avoid filename-too-long error + opstr = hashlib.md5(opstr.encode("latin1")).hexdigest() + opstr = "__" + opstr + return self.data_file( + "refs", f"{self.effect_name}{opstr}.out", check_exists=False + ) diff --git a/share/extensions/inkex/tester/decorators.py b/share/extensions/inkex/tester/decorators.py new file mode 100644 index 0000000..f27e638 --- /dev/null +++ b/share/extensions/inkex/tester/decorators.py @@ -0,0 +1,9 @@ +""" +Useful decorators for tests. +""" +import pytest +from inkex.command import is_inkscape_available + +requires_inkscape = pytest.mark.skipif( # pylint: disable=invalid-name + not is_inkscape_available(), reason="Test requires inkscape, but it's not available" +) diff --git a/share/extensions/inkex/tester/filters.py b/share/extensions/inkex/tester/filters.py new file mode 100644 index 0000000..281adfc --- /dev/null +++ b/share/extensions/inkex/tester/filters.py @@ -0,0 +1,180 @@ +# +# Copyright (C) 2019 Thomas Holder +# +# 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. +# +# pylint: disable=too-few-public-methods +# +""" +Comparison filters for use with the ComparisonMixin. + +Each filter should be initialised in the list of +filters that are being used. + +.. code-block:: python + + compare_filters = [ + CompareNumericFuzzy(), + CompareOrderIndependentLines(option=yes), + ] + +""" + +import re +from ..utils import to_bytes + + +class Compare: + """ + Comparison base class, this acts as a passthrough unless + the filter staticmethod is overwritten. + """ + + def __init__(self, **options): + self.options = options + + def __call__(self, content): + return self.filter(content) + + @staticmethod + def filter(contents): + """Replace this filter method with your own filtering""" + return contents + + +class CompareNumericFuzzy(Compare): + """ + Turn all numbers into shorter standard formats + + 1.2345678 -> 1.2346 + 1.2300 -> 1.23, 50.0000 -> 50.0 + 50.0 -> 50 + """ + + @staticmethod + def filter(contents): + func = lambda m: b"%.3f" % (float(m.group(0))) + contents = re.sub(rb"\d+\.\d+(e[+-]\d+)?", func, contents) + contents = re.sub(rb"(\d\.\d+?)0+\b", rb"\1", contents) + contents = re.sub(rb"(\d)\.0+(?=\D|\b)", rb"\1", contents) + return contents + + +class CompareWithoutIds(Compare): + """Remove all ids from the svg""" + + @staticmethod + def filter(contents): + return re.sub(rb' id="([^"]*)"', b"", contents) + + +class CompareWithPathSpace(Compare): + """Make sure that path segment commands have spaces around them""" + + @staticmethod + def filter(contents): + def func(match): + """We've found a path command, process it""" + new = re.sub(rb"\s*([LZMHVCSQTAatqscvhmzl])\s*", rb" \1 ", match.group(1)) + return b' d="' + new.replace(b",", b" ") + b'"' + + return re.sub(rb' d="([^"]*)"', func, contents) + + +class CompareSize(Compare): + """Compare the length of the contents instead of the contents""" + + @staticmethod + def filter(contents): + return len(contents) + + +class CompareOrderIndependentBytes(Compare): + """Take all the bytes and sort them""" + + @staticmethod + def filter(contents): + return b"".join([bytes(i) for i in sorted(contents)]) + + +class CompareOrderIndependentLines(Compare): + """Take all the lines and sort them""" + + @staticmethod + def filter(contents): + return b"\n".join(sorted(contents.splitlines())) + + +class CompareOrderIndependentStyle(Compare): + """Take all styles and sort the results""" + + @staticmethod + def filter(contents): + contents = CompareNumericFuzzy.filter(contents) + + def func(match): + """Search and replace function for sorting""" + sty = b";".join(sorted(match.group(1).split(b";"))) + return b'style="%s"' % (sty,) + + return re.sub(rb'style="([^"]*)"', func, contents) + + +class CompareOrderIndependentStyleAndPath(Compare): + """Take all styles and paths and sort them both""" + + @staticmethod + def filter(contents): + contents = CompareOrderIndependentStyle.filter(contents) + + def func(match): + """Search and replace function for sorting""" + path = b"X".join(sorted(re.split(rb"[A-Z]", match.group(1)))) + return b'd="%s"' % (path,) + + return re.sub(rb'\bd="([^"]*)"', func, contents) + + +class CompareOrderIndependentTags(Compare): + """Sorts all the XML tags""" + + @staticmethod + def filter(contents): + return b"\n".join(sorted(re.split(rb">\s*<", contents))) + + +class CompareReplacement(Compare): + """Replace pieces to make output more comparable + + .. versionadded:: 1.1""" + + def __init__(self, *replacements): + self.deltas = replacements + super().__init__() + + def filter(self, contents): + contents = to_bytes(contents) + for _from, _to in self.deltas: + contents = contents.replace(to_bytes(_from), to_bytes(_to)) + return contents + + +class WindowsTextCompat(CompareReplacement): + """Normalize newlines so tests comparing plain text work + + .. versionadded:: 1.2""" + + def __init__(self): + super().__init__(("\r\n", "\n")) diff --git a/share/extensions/inkex/tester/inx.py b/share/extensions/inkex/tester/inx.py new file mode 100644 index 0000000..bad6d81 --- /dev/null +++ b/share/extensions/inkex/tester/inx.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test elements extra logic from svg xml lxml custom classes. +""" + +from ..utils import PY3 +from ..inx import InxFile + +INTERNAL_ARGS = ("help", "output", "id", "selected-nodes") +ARG_TYPES = { + "Boolean": "bool", + "Color": "color", + "str": "string", + "int": "int", + "float": "float", +} + + +class InxMixin: + """Tools for Testing INX files, use as a mixin class: + + class MyTests(InxMixin, TestCase): + def test_inx_file(self): + self.assertInxIsGood("some_inx_file.inx") + """ + + def assertInxIsGood(self, inx_file): # pylint: disable=invalid-name + """Test the inx file for consistancy and correctness""" + self.assertTrue(PY3, "INX files can only be tested in python3") + + inx = InxFile(inx_file) + if "help" in inx.ident or inx.script.get("interpreter", None) != "python": + return + cls = inx.extension_class + # Check class can be matched in python file + self.assertTrue(cls, f"Can not find class for {inx.filename}") + # Check name is reasonable for the class + if not cls.multi_inx: + self.assertEqual( + cls.__name__, + inx.slug, + f"Name of extension class {cls.__module__}.{cls.__name__} " + f"is different from ident {inx.slug}", + ) + self.assertParams(inx, cls) + + def assertParams(self, inx, cls): # pylint: disable=invalid-name + """Confirm the params in the inx match the python script + + .. versionchanged:: 1.2 + Also checks that the default values are identical""" + params = {param.name: self.parse_param(param) for param in inx.params} + args = dict(self.introspect_arg_parser(cls().arg_parser)) + mismatch_a = list(set(params) ^ set(args) & set(params)) + mismatch_b = list(set(args) ^ set(params) & set(args)) + self.assertFalse( + mismatch_a, f"{inx.filename}: Inx params missing from arg parser" + ) + self.assertFalse( + mismatch_b, f"{inx.filename}: Script args missing from inx xml" + ) + + for param in args: + if params[param]["type"] and args[param]["type"]: + self.assertEqual( + params[param]["type"], + args[param]["type"], + f"Type is not the same for {inx.filename}:param:{param}", + ) + inxdefault = params[param]["default"] + argsdefault = args[param]["default"] + if inxdefault and argsdefault: + # for booleans, the inx is lowercase and the param is uppercase + if params[param]["type"] == "bool": + argsdefault = str(argsdefault).lower() + elif params[param]["type"] not in ["string", None, "color"] or args[ + param + ]["type"] in ["int", "float"]: + # try to parse the inx value to compare numbers to numbers + inxdefault = float(inxdefault) + if args[param]["type"] == "color" or callable(args[param]["default"]): + # skip color, method types + continue + self.assertEqual( + argsdefault, + inxdefault, + f"Default value is not the same for {inx.filename}:param:{param}", + ) + + def introspect_arg_parser(self, arg_parser): + """Pull apart the arg parser to find out what we have in it""" + for ( + action + ) in arg_parser._optionals._actions: # pylint: disable=protected-access + for opt in action.option_strings: + # Ignore params internal to inkscape (thus not in the inx) + if opt.startswith("--") and opt[2:] not in INTERNAL_ARGS: + yield (opt[2:], self.introspect_action(action)) + + @staticmethod + def introspect_action(action): + """Pull apart a single action to get at the juicy insides""" + return { + "type": ARG_TYPES.get((action.type or str).__name__, "string"), + "default": action.default, + "choices": action.choices, + "help": action.help, + } + + @staticmethod + def parse_param(param): + """Pull apart the param element in the inx file""" + if param.param_type in ("optiongroup", "notebook"): + options = param.options + return { + "type": None, + "choices": options, + "default": options and options[0] or None, + } + param_type = param.param_type + if param.param_type in ("path",): + param_type = "string" + return { + "type": param_type, + "default": param.text, + "choices": None, + } diff --git a/share/extensions/inkex/tester/mock.py b/share/extensions/inkex/tester/mock.py new file mode 100644 index 0000000..3b75dcd --- /dev/null +++ b/share/extensions/inkex/tester/mock.py @@ -0,0 +1,455 @@ +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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, USA. +# +# pylint: disable=protected-access,too-few-public-methods +""" +Any mocking utilities required by testing. Mocking is when you need the test +to exercise a piece of code, but that code may or does call on something +outside of the target code that either takes too long to run, isn't available +during the test running process or simply shouldn't be running at all. +""" + +import io +import os +import sys +import logging +import hashlib +import tempfile +from typing import List, Tuple, Any + +from email.mime.application import MIMEApplication +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.parser import Parser as EmailParser + +import inkex.command + + +FIXED_BOUNDARY = "--CALLDATA--//--CALLDATA--" + + +class Capture: + """Capture stdout or stderr. Used as `with Capture('stdout') as stream:`""" + + def __init__(self, io_name="stdout", swap=True): + self.io_name = io_name + self.original = getattr(sys, io_name) + self.stream = io.StringIO() + self.swap = swap + + def __enter__(self): + if self.swap: + setattr(sys, self.io_name, self.stream) + return self.stream + + def __exit__(self, exc, value, traceback): + if exc is not None and self.swap: + # Dump content back to original if there was an error. + self.original.write(self.stream.getvalue()) + setattr(sys, self.io_name, self.original) + + +class ManualVerbosity: + """Change the verbosity of the test suite manually""" + + result = property(lambda self: self.test._current_result) + + def __init__(self, test, okay=True, dots=False): + self.test = test + self.okay = okay + self.dots = dots + + def flip( + self, exc_type=None, exc_val=None, exc_tb=None + ): # pylint: disable=unused-argument + """Swap the stored verbosity with the original""" + self.okay, self.result.showAll = self.result.showAll, self.okay + self.dots, self.result.dots = self.result.dots, self.okay + + __enter__ = flip + __exit__ = flip + + +class MockMixin: + """ + Add mocking ability to any test base class, will set up mock on setUp + and remove it on tearDown. + + Mocks are stored in an array attached to the test class (not instance!) which + ensures that mocks can only ever be setUp once and can never be reset over + themselves. (just in case this looks weird at first glance) + + class SomeTest(MockingMixin, TestBase): + mocks = [(sys, 'exit', NoSystemExit("Nope!")] + """ + + mocks = [] # type: List[Tuple[Any, str, Any]] + + def setUpMock(self, owner, name, new): # pylint: disable=invalid-name + """Setup the mock here, taking name and function and returning (name, old)""" + old = getattr(owner, name) + if isinstance(new, str): + if hasattr(self, new): + new = getattr(self, new) + if isinstance(new, Exception): + + def _error_function(*args2, **kw2): # pylint: disable=unused-argument + raise type(new)(str(new)) + + setattr(owner, name, _error_function) + elif new is None or isinstance(new, (str, int, float, list, tuple)): + + def _value_function(*args, **kw): # pylint: disable=unused-argument + return new + + setattr(owner, name, _value_function) + else: + setattr(owner, name, new) + # When we start, mocks contains length 3 tuples, when we're finished, it + # contains length 4, this stops remocking and reunmocking from taking place. + return (owner, name, old, False) + + def setUp(self): # pylint: disable=invalid-name + """For each mock instruction, set it up and store the return""" + super().setUp() + for x, mock in enumerate(self.mocks): + if len(mock) == 4: + logging.error( + "Mock was already set up, so it wasn't cleared previously!" + ) + continue + self.mocks[x] = self.setUpMock(*mock) + + def tearDown(self): # pylint: disable=invalid-name + """For each returned stored, tear it down and restore mock instruction""" + super().tearDown() + try: + for x, (owner, name, old, _) in enumerate(self.mocks): + self.mocks[x] = (owner, name, getattr(owner, name)) + setattr(owner, name, old) + except ValueError: + logging.warning("Was never mocked, did something go wrong?") + + def old_call(self, name): + """Get the original caller""" + for arg in self.mocks: + if arg[1] == name: + return arg[2] + return lambda: None + + +class MockCommandMixin(MockMixin): + """ + Replace all the command functions with testable replacements. + + This stops the pipeline and people without the programs, running into problems. + """ + + mocks = [ + (inkex.command, "_call", "mock_call"), + (tempfile, "mkdtemp", "record_tempdir"), + ] + recorded_tempdirs = [] # type:List[str] + + def setUp(self): # pylint: disable=invalid-name + super().setUp() + # This is a the daftest thing I've ever seen, when in the middle + # of a mock, the 'self' variable magically turns from a FooTest + # into a TestCase, this makes it impossible to find the datadir. + from . import TestCase + + TestCase._mockdatadir = self.datadir() + + @classmethod + def cmddir(cls): + """Returns the location of all the mocked command results""" + from . import TestCase + + return os.path.join(TestCase._mockdatadir, "cmd") + + def record_tempdir(self, *args, **kwargs): + """Record any attempts to make tempdirs""" + newdir = self.old_call("mkdtemp")(*args, **kwargs) + self.recorded_tempdirs.append(os.path.realpath(newdir)) + return newdir + + def clean_paths(self, data, files): + """Clean a string of any files or tempdirs""" + + def replace(indata, replaced, replacement): + if isinstance(indata, str): + indata = indata.replace(replaced, replacement) + else: + indata = [i.replace(replaced, replacement) for i in indata] + return indata + + try: + for fdir in self.recorded_tempdirs: + data = replace(data, fdir, ".") + files = replace(files, fdir, ".") + for fname in files: + data = replace(data, fname, os.path.basename(fname)) + except (UnicodeDecodeError, TypeError): + pass + return data + + def get_all_tempfiles(self): + """Returns a set() of all files currently in any of the tempdirs""" + ret = set([]) + for fdir in self.recorded_tempdirs: + if not os.path.isdir(fdir): + continue + for fname in os.listdir(fdir): + if fname in (".", ".."): + continue + path = os.path.join(fdir, fname) + # We store the modified time so if a program modifies + # the input file in-place, it will look different. + ret.add(path + f";{os.path.getmtime(path)}") + + return ret + + def ignore_command_mock(self, program, arglst): + """Return true if the mock is ignored""" + if self and program and arglst: + return os.environ.get("NO_MOCK_COMMANDS") + return False + + def mock_call(self, program, *args, **kwargs): + """ + Replacement for the inkex.command.call() function, instead of calling + an external program, will compile all arguments into a hash and use the + hash to find a command result. + """ + # Remove stdin first because it needs to NOT be in the Arguments list. + stdin = kwargs.pop("stdin", None) + args = list(args) + + # We use email + msg = MIMEMultipart(boundary=FIXED_BOUNDARY) + msg["Program"] = MockCommandMixin.get_program_name(program) + + # Gather any output files and add any input files to msg, args and kwargs + # may be modified to strip out filename directories (which change) + inputs, outputs = self.add_call_files(msg, args, kwargs) + + arglst = inkex.command.to_args_sorted(program, *args, **kwargs)[1:] + arglst = self.clean_paths(arglst, inputs + outputs) + argstr = " ".join(arglst) + msg["Arguments"] = argstr.strip() + + if stdin is not None: + # The stdin is counted as the msg body + cleanin = ( + self.clean_paths(stdin, inputs + outputs) + .replace("\r\n", "\n") + .replace(".\\", "./") + ) + msg.attach(MIMEText(cleanin, "plain", "utf-8")) + + keystr = msg.as_string() + # On Windows, output is separated by CRLF + keystr = keystr.replace("\r\n", "\n") + # There is a difference between python2 and python3 output + keystr = keystr.replace("\n\n", "\n") + keystr = keystr.replace("\n ", " ") + if "verb" in keystr: + # Verbs seperated by colons cause diff in py2/3 + keystr = keystr.replace("; ", ";") + # Generate a unique key for this call based on _all_ it's inputs + key = hashlib.md5(keystr.encode("utf-8")).hexdigest() + + if self.ignore_command_mock(program, arglst): + # Call original code. This is so programmers can run the test suite + # against the external programs too, to see how their fair. + if stdin is not None: + kwargs["stdin"] = stdin + + before = self.get_all_tempfiles() + stdout = self.old_call("_call")(program, *args, **kwargs) + outputs += list(self.get_all_tempfiles() - before) + # Remove the modified time from the call + outputs = [out.rsplit(";", 1)[0] for out in outputs] + + # After the program has run, we collect any file outputs and store + # them, then store any stdout or stderr created during the run. + # A developer can then use this to build new test cases. + reply = MIMEMultipart(boundary=FIXED_BOUNDARY) + reply["Program"] = MockCommandMixin.get_program_name(program) + reply["Arguments"] = argstr + self.save_call(program, key, stdout, outputs, reply) + self.save_key(program, key, keystr, "key") + return stdout + + try: + return self.load_call(program, key, outputs) + except IOError as err: + self.save_key(program, key, keystr, "bad-key") + raise IOError( + f"Problem loading call: {program}/{key} use the environment variable " + "NO_MOCK_COMMANDS=1 to call out to the external program and generate " + f"the mock call file for call {program} {argstr}." + ) from err + + def add_call_files(self, msg, args, kwargs): + """ + Gather all files, adding input files to the msg (for hashing) and + output files to the returned files list (for outputting in debug) + """ + # Gather all possible string arguments together. + loargs = sorted(kwargs.items(), key=lambda i: i[0]) + values = [] + for arg in args: + if isinstance(arg, (tuple, list)): + loargs.append(arg) + else: + values.append(str(arg)) + + for (_, value) in loargs: + if isinstance(value, (tuple, list)): + for val in value: + if val is not True: + values.append(str(val)) + elif value is not True: + values.append(str(value)) + + # See if any of the strings could be filenames, either going to be + # or are existing files on the disk. + files = [[], []] + for value in values: + if os.path.isfile(value): # Input file + files[0].append(value) + self.add_call_file(msg, value) + elif os.path.isdir(os.path.dirname(value)): # Output file + files[1].append(value) + return files + + def add_call_file(self, msg, filename): + """Add a single file to the given mime message""" + fname = os.path.basename(filename) + with open(filename, "rb") as fhl: + if filename.endswith(".svg"): + value = self.clean_paths(fhl.read().decode("utf8"), []) + else: + value = fhl.read() + try: + value = value.decode() + except UnicodeDecodeError: + pass # do not attempt to process binary files further + if isinstance(value, str): + value = value.replace("\r\n", "\n").replace(".\\", "./") + part = MIMEApplication(value, Name=fname) + # After the file is closed + part["Content-Disposition"] = "attachment" + part["Filename"] = fname + msg.attach(part) + + def get_call_filename(self, program, key, create=False): + """ + Get the filename for the call testing information. + """ + path = self.get_call_path(program, create=create) + fname = os.path.join(path, key + ".msg") + if not create and not os.path.isfile(fname): + raise IOError(f"Attempted to find call test data {key}") + return fname + + @staticmethod + def get_program_name(program): + """Takes a program and returns a program name""" + if program == inkex.command.INKSCAPE_EXECUTABLE_NAME: + return "inkscape" + return program + + def get_call_path(self, program, create=True): + """Get where this program would store it's test data""" + command_dir = os.path.join( + self.cmddir(), MockCommandMixin.get_program_name(program) + ) + if not os.path.isdir(command_dir): + if create: + os.makedirs(command_dir) + else: + raise IOError( + "A test is attempting to use an external program in a test:" + f" {program}; but there is not a command data directory which " + f"should contain the results of the command here: {command_dir}" + ) + return command_dir + + def load_call(self, program, key, files): + """ + Load the given call + """ + fname = self.get_call_filename(program, key, create=False) + with open(fname, "rb") as fhl: + msg = EmailParser().parsestr(fhl.read().decode("utf-8")) + + stdout = None + for part in msg.walk(): + if "attachment" in part.get("Content-Disposition", ""): + base_name = part["Filename"] + for out_file in files: + if out_file.endswith(base_name): + with open(out_file, "wb") as fhl: + fhl.write(part.get_payload(decode=True)) + part = None + if part is not None: + # Was not caught by any normal outputs, so we will + # save the file to EVERY tempdir in the hopes of + # hitting on of them. + for fdir in self.recorded_tempdirs: + if os.path.isdir(fdir): + with open(os.path.join(fdir, base_name), "wb") as fhl: + fhl.write(part.get_payload(decode=True)) + elif part.get_content_type() == "text/plain": + stdout = part.get_payload(decode=True) + + return stdout + + def save_call( + self, program, key, stdout, files, msg, ext="output" + ): # pylint: disable=too-many-arguments + """ + Saves the results from the call into a debug output file, the resulting files + should be a Mime msg file format with each attachment being one of the input + files as well as any stdin and arguments used in the call. + """ + if stdout is not None and stdout.strip(): + # The stdout is counted as the msg body here + msg.attach(MIMEText(stdout.decode("utf-8"), "plain", "utf-8")) + + for fname in set(files): + if os.path.isfile(fname): + # print("SAVING FILE INTO MSG: {}".format(fname)) + self.add_call_file(msg, fname) + else: + part = MIMEText("Missing File", "plain", "utf-8") + part.add_header("Filename", os.path.basename(fname)) + msg.attach(part) + + fname = self.get_call_filename(program, key, create=True) + "." + ext + with open(fname, "wb") as fhl: + fhl.write(msg.as_string().encode("utf-8")) + + def save_key(self, program, key, keystr, ext="key"): + """Save the key file if we are debugging the key data""" + if os.environ.get("DEBUG_KEY"): + fname = self.get_call_filename(program, key, create=True) + "." + ext + with open(fname, "wb") as fhl: + fhl.write(keystr.encode("utf-8")) diff --git a/share/extensions/inkex/tester/svg.py b/share/extensions/inkex/tester/svg.py new file mode 100644 index 0000000..c601c81 --- /dev/null +++ b/share/extensions/inkex/tester/svg.py @@ -0,0 +1,55 @@ +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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, USA. +# +""" +SVG specific utilities for tests. +""" + +from lxml import etree + +from inkex import SVG_PARSER + + +def svg(svg_attrs=""): + """Returns xml etree based on a simple SVG element. + + svg_attrs: A string containing attributes to add to the + root element of a minimal SVG document. + """ + return etree.fromstring( + str.encode( + '' + f"" + ), + parser=SVG_PARSER, + ) + + +def svg_unit_scaled(width_unit): + """Same as svg, but takes a width unit (top-level transform) for the new document. + + The transform is the ratio between the SVG width and the viewBox width. + """ + return svg(f'width="1{width_unit}" viewBox="0 0 1 1"') + + +def svg_file(filename): + """Parse an svg file and return it's document root""" + with open(filename, "r", encoding="utf-8") as fhl: + doc = etree.parse(fhl, parser=SVG_PARSER) + return doc.getroot() diff --git a/share/extensions/inkex/tester/word.py b/share/extensions/inkex/tester/word.py new file mode 100644 index 0000000..bf395d7 --- /dev/null +++ b/share/extensions/inkex/tester/word.py @@ -0,0 +1,42 @@ +# coding=utf-8 +# +# Unknown author +# +""" +Generate words for testing. +""" + +import string +import random + + +def word_generator(text_length): + """ + Generate a word of text_length size + """ + word = "" + + for _ in range(0, text_length): + word += random.choice( + string.ascii_lowercase + + string.ascii_uppercase + + string.digits + + string.punctuation + ) + + return word + + +def sentencecase(word): + """Make a word standace case""" + word_new = "" + lower_letters = list(string.ascii_lowercase) + first = True + for letter in word: + if letter in lower_letters and first is True: + word_new += letter.upper() + first = False + else: + word_new += letter + + return word_new diff --git a/share/extensions/inkex/tester/xmldiff.py b/share/extensions/inkex/tester/xmldiff.py new file mode 100644 index 0000000..1864530 --- /dev/null +++ b/share/extensions/inkex/tester/xmldiff.py @@ -0,0 +1,124 @@ +# +# Copyright 2011 (c) Ian Bicking +# 2019 (c) Martin Owens +# +# Taken from http://formencode.org under the GPL compatible PSF License. +# Modified to produce more output as a diff. +# +""" +Allow two xml files/lxml etrees to be compared, returning their differences. +""" +import xml.etree.ElementTree as xml +from io import BytesIO + +from inkex.paths import Path + + +def text_compare(test1, test2): + """ + Compare two text strings while allowing for '*' to match + anything on either lhs or rhs. + """ + if not test1 and not test2: + return True + if test1 == "*" or test2 == "*": + return True + return (test1 or "").strip() == (test2 or "").strip() + + +class DeltaLogger(list): + """A record keeper of the delta between two svg files""" + + def append_tag(self, tag_a, tag_b): + """Record a tag difference""" + if tag_a: + tag_a = f"<{tag_a}.../>" + if tag_b: + tag_b = f"<{tag_b}.../>" + self.append((tag_a, tag_b)) + + def append_attr(self, attr, value_a, value_b): + """Record an attribute difference""" + + def _prep(val): + if val: + if attr == "d": + return [attr] + Path(val).to_arrays() + return (attr, val) + return val + + # Only append a difference if the preprocessed values are different. + # This solves the issue that -0 != 0 in path data. + prep_a = _prep(value_a) + prep_b = _prep(value_b) + if prep_a != prep_b: + self.append((prep_a, prep_b)) + + def append_text(self, text_a, text_b): + """Record a text difference""" + self.append((text_a, text_b)) + + def __bool__(self): + """Returns True if there's no log, i.e. the delta is clean""" + return not self.__len__() + + __nonzero__ = __bool__ + + def __repr__(self): + if self: + return "No differences detected" + return f"{len(self)} xml differences" + + +def to_xml(data): + """Convert string or bytes to xml parsed root node""" + if isinstance(data, str): + data = data.encode("utf8") + if isinstance(data, bytes): + return xml.parse(BytesIO(data)).getroot() + return data + + +def xmldiff(data1, data2): + """Create an xml difference, will modify the first xml structure with a diff""" + xml1, xml2 = to_xml(data1), to_xml(data2) + delta = DeltaLogger() + _xmldiff(xml1, xml2, delta) + return xml.tostring(xml1).decode("utf-8"), delta + + +def _xmldiff(xml1, xml2, delta): + if xml1.tag != xml2.tag: + xml1.tag = f"{xml1.tag}XXX{xml2.tag}" + delta.append_tag(xml1.tag, xml2.tag) + for name, value in xml1.attrib.items(): + if name not in xml2.attrib: + delta.append_attr(name, xml1.attrib[name], None) + xml1.attrib[name] += "XXX" + elif xml2.attrib.get(name) != value: + delta.append_attr(name, xml1.attrib.get(name), xml2.attrib.get(name)) + xml1.attrib[name] = f"{xml1.attrib.get(name)}XXX{xml2.attrib.get(name)}" + for name, value in xml2.attrib.items(): + if name not in xml1.attrib: + delta.append_attr(name, None, value) + xml1.attrib[name] = "XXX" + value + if not text_compare(xml1.text, xml2.text): + delta.append_text(xml1.text, xml2.text) + xml1.text = f"{xml1.text}XXX{xml2.text}" + if not text_compare(xml1.tail, xml2.tail): + delta.append_text(xml1.tail, xml2.tail) + xml1.tail = f"{xml1.tail}XXX{xml2.tail}" + + # Get children and pad with nulls + children_a = list(xml1) + children_b = list(xml2) + children_a += [None] * (len(children_b) - len(children_a)) + children_b += [None] * (len(children_a) - len(children_b)) + + for child_a, child_b in zip(children_a, children_b): + if child_a is None: # child_b exists + delta.append_tag(child_b.tag, None) + elif child_b is None: # child_a exists + delta.append_tag(None, child_a.tag) + else: + _xmldiff(child_a, child_b, delta) diff --git a/share/extensions/inkex/transforms.py b/share/extensions/inkex/transforms.py new file mode 100644 index 0000000..3a37a38 --- /dev/null +++ b/share/extensions/inkex/transforms.py @@ -0,0 +1,1250 @@ +# coding=utf-8 +# +# Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +# Copyright (C) 2010 Alvin Penner, penner@vaxxine.com +# +# 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. +# barraud@math.univ-lille1.fr +# +# This code defines several functions to make handling of transform +# attribute easier. +# +""" +Provide transformation parsing to extensions +""" +from __future__ import annotations +import re +from decimal import Decimal +from math import cos, radians, sin, sqrt, tan, fabs, atan2, hypot, pi, isfinite +from typing import ( + overload, + cast, + Callable, + Generator, + Iterator, + Tuple, + Union, + Optional, + List, +) + + +from .utils import strargs, KeyDict + + +VectorLike = Union[ + "ImmutableVector2d", Tuple[float, float] +] # pylint: disable=invalid-name +MatrixLike = Union[ + str, + Tuple[Tuple[float, float, float], Tuple[float, float, float]], + Tuple[float, float, float, float, float, float], + "Transform", +] +BoundingIntervalArgs = Union[ + "BoundingInterval", Tuple[float, float], float +] # pylint: disable=invalid-name + +# All the names that get added to the inkex API itself. +__all__ = ( + "BoundingBox", + "DirectedLineSegment", + "ImmutableVector2d", + "Transform", + "Vector2d", +) + + +# Old settings, supported because users click 'ok' without looking. +XAN = KeyDict({"l": "left", "r": "right", "m": "center_x"}) +YAN = KeyDict({"t": "top", "b": "bottom", "m": "center_y"}) +# Anchoring objects with given directions (see inx options) +CUSTOM_DIRECTION = {270: "tb", 90: "bt", 0: "lr", 360: "lr", 180: "rl"} +DIRECTION = ["tb", "bt", "lr", "rl", "ro", "ri"] + + +class ImmutableVector2d: + """Represents an immutable element of 2-dimensional Euclidean space""" + + _x = 0.0 + _y = 0.0 + + x = property(lambda self: self._x) + y = property(lambda self: self._y) + + @overload + def __init__(self): + # type: () -> None + pass + + @overload + def __init__(self, v, fallback=None): + # type: (Union[VectorLike, str], Optional[Union[VectorLike, str]]) -> None + pass + + @overload + def __init__(self, x, y): + # type: (float, float) -> None + pass + + def __init__(self, *args, fallback=None): + try: + if len(args) == 0: + x, y = 0.0, 0.0 + elif len(args) == 1: + x, y = self._parse(args[0]) + elif len(args) == 2: + x, y = map(float, args) + else: + raise ValueError("too many arguments") + except (ValueError, TypeError) as error: + if fallback is None: + raise ValueError("Cannot parse vector and no fallback given") from error + x, y = ImmutableVector2d(fallback) + self._x, self._y = float(x), float(y) + + @staticmethod + def _parse(point): + # type: (Union[VectorLike, str]) -> Tuple[float, float] + if isinstance(point, ImmutableVector2d): + x, y = point.x, point.y + elif isinstance(point, (tuple, list)) and len(point) == 2: + x, y = map(float, point) + elif isinstance(point, str) and point.count(",") == 1: + x, y = map(float, point.split(",")) + else: + raise ValueError(f"Can't parse {repr(point)}") + return x, y + + def __add__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + return Vector2d(self.x + other.x, self.y + other.y) + + def __radd__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + return Vector2d(self.x + other.x, self.y + other.y) + + def __sub__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + return Vector2d(self.x - other.x, self.y - other.y) + + def __rsub__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + return Vector2d(-self.x + other.x, -self.y + other.y) + + def __neg__(self): + # type: () -> Vector2d + return Vector2d(-self.x, -self.y) + + def __pos__(self): + # type: () -> Vector2d + return Vector2d(self.x, self.y) + + def __floordiv__(self, factor): + # type: (float) -> Vector2d + return Vector2d(self.x / float(factor), self.y / float(factor)) + + def __truediv__(self, factor): + # type: (float) -> Vector2d + return Vector2d(self.x / float(factor), self.y / float(factor)) + + def __div__(self, factor): + # type: (float) -> Vector2d + return Vector2d(self.x / float(factor), self.y / float(factor)) + + def __mul__(self, factor): + # type: (float) -> Vector2d + return Vector2d(self.x * factor, self.y * factor) + + def __abs__(self): + # type: () -> float + return self.length + + def __rmul__(self, factor): + # type: (float) -> VectorLike + return Vector2d(self.x * factor, self.y * factor) + + def __repr__(self): + # type: () -> str + return f"Vector2d({self.x:.6g}, {self.y:.6g})" + + def __str__(self): + # type: () -> str + return f"{self.x:.6g}, {self.y:.6g}" + + def __iter__(self) -> Generator[float, None, None]: + yield self.x + yield self.y + + def __len__(self): + # type: () -> int + return 2 + + def __getitem__(self, item): + # type: (int) -> float + return (self.x, self.y)[item] + + def to_tuple(self) -> Tuple[float, float]: + """A tuple of the vector's components""" + return cast(Tuple[float, float], tuple(self)) + + def to_polar_tuple(self): + # type: () -> Tuple[float, Optional[float]] + """A tuple of the vector's magnitude and direction + + .. versionadded:: 1.1""" + return self.length, self.angle + + def dot(self, other: VectorLike) -> float: + """Multiply Vectors component-wise""" + other = Vector2d(other) + return self.x * other.x + self.y * other.y + + def cross(self, other): + # type: (VectorLike) -> float + """Z component of the cross product of the vectors extended into 3D + + .. versionadded:: 1.1""" + other = Vector2d(other) + return self.x * other.y - self.y * other.x + + def is_close( + self, + other: Union[VectorLike, str, Tuple[float, float]], + rtol: float = 1e-5, + atol: float = 1e-8, + ) -> float: + """Checks if two vectors are (almost) identical, up to both absolute and + relative tolerance.""" + other = Vector2d(other) + delta = (self - other).length + return delta < (atol + rtol * other.length) + + @property + def length(self) -> float: + """Returns the length of the vector""" + return sqrt(self.dot(self)) + + @property + def angle(self): + # type: () -> Optional[float] + """The angle of the vector when represented in polar coordinates + + .. versionadded:: 1.1""" + if self.x == 0 and self.y == 0: + return None + return atan2(self.y, self.x) + + +class Vector2d(ImmutableVector2d): + """Represents an element of 2-dimensional Euclidean space""" + + @staticmethod + def from_polar(radius, theta): + # type: (float, Optional[float]) -> Optional[Vector2d] + """Creates a Vector2d from polar coordinates + + None is returned when theta is None and radius is not zero. + + .. versionadded:: 1.1 + """ + if radius == 0.0: + return Vector2d(0.0, 0.0) + if theta is not None: + return Vector2d(radius * cos(theta), radius * sin(theta)) + # A vector with a radius but no direction is invalid + return None + + @ImmutableVector2d.x.setter + def x(self, value): + # type: (Union[float, int, str]) -> None + self._x = float(value) + + @ImmutableVector2d.y.setter + def y(self, value): + # type: (Union[float, int, str]) -> None + self._y = float(value) + + def __iadd__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + self.x += other.x + self.y += other.y + return self + + def __isub__(self, other): + # type: (VectorLike) -> Vector2d + other = Vector2d(other) + self.x -= other.x + self.y -= other.y + return self + + def __imul__(self, factor): + # type: (float) -> Vector2d + self.x *= factor + self.y *= factor + return self + + def __idiv__(self, factor): + # type: (float) -> Vector2d + self.x /= factor + self.y /= factor + return self + + def __itruediv__(self, factor): + # type: (float) -> Vector2d + self.x /= factor + self.y /= factor + return self + + def __ifloordiv__(self, factor): + # type: (float) -> Vector2d + self.x /= factor + self.y /= factor + return self + + @overload + def assign(self, x, y): + # type: (float, float) -> VectorLike + pass + + @overload + def assign(self, other): + # type: (VectorLike, str) -> VectorLike + pass + + def assign(self, *args): + """Assigns a different vector in place""" + self.x, self.y = Vector2d(*args) + return self + + +class Transform: + """A transformation object which will always reduce to a matrix and can + then be used in combination with other transformations for reducing + finding a point and printing svg ready output. + + Use with svg transform attribute input: + + tr = Transform("scale(45, 32)") + + Use with triad matrix input (internal representation): + + tr = Transform(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0))) + + Use with hexad matrix input (i.e. svg matrix(...)): + + tr = Transform((1.0, 0.0, 0.0, 1.0, 0.0, 0.0)) + + Once you have a transformation you can operate tr * tr to compose, + any of the above inputs are also valid operators for composing. + """ + + TRM = re.compile(r"(translate|scale|rotate|skewX|skewY|matrix)\s*\(([^)]*)\)\s*,?") + absolute_tolerance = 1e-5 # type: float + + def __init__( + self, + matrix=None, # type: Optional[MatrixLike] + callback=None, # type: Optional[Callable[[Transform], Transform]] + **extra, + ): + # type: (...) -> None + self.callback = None + self.matrix = ((1.0, 0.0, 0.0), (0.0, 1.0, 0.0)) + if matrix is not None: + self._set_matrix(matrix) + + self.add_kwargs(**extra) + # Set callback last, so it doesn't kick off just setting up the internal value + self.callback = callback + + def _set_matrix(self, matrix): + # type: (MatrixLike) -> None + """Parse a given string as an svg transformation instruction. + + .. versionadded:: 1.1""" + if isinstance(matrix, str): + for func, values in self.TRM.findall(matrix.strip()): + getattr(self, "add_" + func.lower())(*strargs(values)) + elif isinstance(matrix, Transform): + self.matrix = matrix.matrix + elif isinstance(matrix, (tuple, list)) and len(matrix) == 2: + row1 = matrix[0] + row2 = matrix[1] + if isinstance(row1, (tuple, list)) and isinstance(row2, (tuple, list)): + if len(row1) == 3 and len(row2) == 3: + row1 = cast(Tuple[float, float, float], tuple(map(float, row1))) + row2 = cast(Tuple[float, float, float], tuple(map(float, row2))) + self.matrix = row1, row2 + else: + raise ValueError( + f"Matrix '{matrix}' is not a valid transformation matrix" + ) + else: + raise ValueError( + f"Matrix '{matrix}' is not a valid transformation matrix" + ) + elif isinstance(matrix, (list, tuple)) and len(matrix) == 6: + tmatrix = cast( + Union[List[float], Tuple[float, float, float, float, float, float]], + matrix, + ) + row1 = (float(tmatrix[0]), float(tmatrix[2]), float(tmatrix[4])) + row2 = (float(tmatrix[1]), float(tmatrix[3]), float(tmatrix[5])) + self.matrix = row1, row2 + elif not isinstance(matrix, (list, tuple)): + raise ValueError(f"Invalid transform type: {type(matrix).__name__}") + else: + raise ValueError(f"Matrix '{matrix}' is not a valid transformation matrix") + + # These provide quick access to the svg matrix: + # + # [ a, c, e ] + # [ b, d, f ] + # + a = property(lambda self: self.matrix[0][0]) # pylint: disable=invalid-name + b = property(lambda self: self.matrix[1][0]) # pylint: disable=invalid-name + c = property(lambda self: self.matrix[0][1]) # pylint: disable=invalid-name + d = property(lambda self: self.matrix[1][1]) # pylint: disable=invalid-name + e = property(lambda self: self.matrix[0][2]) # pylint: disable=invalid-name + f = property(lambda self: self.matrix[1][2]) # pylint: disable=invalid-name + + def __bool__(self): + # type: () -> bool + return not self.__eq__(Transform()) + + __nonzero__ = __bool__ + + @overload + def add_matrix(self, a): + # type: (MatrixLike) -> Transform + pass + + @overload + def add_matrix( # pylint: disable=too-many-arguments + self, a: float, b: float, c: float, d: float, e: float, f: float + ) -> Transform: + pass + + @overload + def add_matrix(self, a, b): + # type: (Tuple[float, float, float], Tuple[float, float, float]) -> Transform + pass + + def add_matrix(self, *args): + """Add matrix in order they appear in the svg hexad""" + if len(args) == 1: + self.__imatmul__(Transform(args[0])) + elif len(args) == 2 or len(args) == 6: + self.__imatmul__(Transform(args)) + else: + raise ValueError(f"Invalid number of arguments {args}") + return self + + def add_kwargs(self, **kwargs): + """Add translations, scales, rotations etc using key word arguments""" + for key, value in reversed(list(kwargs.items())): + func = getattr(self, "add_" + key) + if isinstance(value, tuple): + func(*value) + elif value is not None: + func(value) + return self + + @overload + def add_translate(self, dr): + # type: (VectorLike) -> Transform + pass + + @overload + def add_translate(self, tr_x, tr_y=0.0): + # type: (float, Optional[float]) -> Transform + pass + + def add_translate(self, *args): + """Add translate to this transformation""" + if len(args) == 1 and isinstance(args[0], (int, float)): + tr_x, tr_y = args[0], 0.0 + else: + tr_x, tr_y = Vector2d(*args) + self.__imatmul__(((1.0, 0.0, tr_x), (0.0, 1.0, tr_y))) + return self + + def add_scale(self, sc_x, sc_y=None): + """Add scale to this transformation""" + sc_y = sc_x if sc_y is None else sc_y + self.__imatmul__(((sc_x, 0.0, 0.0), (0.0, sc_y, 0.0))) + return self + + @overload + def add_rotate(self, deg, center): + # type: (float, VectorLike) -> Transform + pass + + @overload + def add_rotate(self, deg, center_x, center_y): + # type: (float, float, float) -> Transform + pass + + @overload + def add_rotate(self, deg): + # type: (float) -> Transform + pass + + @overload + def add_rotate(self, deg, a): + # type: (float, Union[VectorLike, str]) -> Transform + pass + + @overload + def add_rotate(self, deg, a, b): + # type: (float, float, float) -> Transform + pass + + def add_rotate(self, deg, *args): + """Add rotation to this transformation""" + center_x, center_y = Vector2d(*args) + _cos, _sin = cos(radians(deg)), sin(radians(deg)) + self.__imatmul__(((_cos, -_sin, center_x), (_sin, _cos, center_y))) + self.__imatmul__(((1.0, 0.0, -center_x), (0.0, 1.0, -center_y))) + return self + + def add_skewx(self, deg): + # type: (float) -> Transform + """Add skew x to this transformation""" + self.__imatmul__(((1.0, tan(radians(deg)), 0.0), (0.0, 1.0, 0.0))) + return self + + def add_skewy(self, deg): + # type: (float) -> Transform + """Add skew y to this transformation""" + self.__imatmul__(((1.0, 0.0, 0.0), (tan(radians(deg)), 1.0, 0.0))) + return self + + def to_hexad(self): + # type: () -> Iterator[float] + """Returns the transform as a hexad matrix (used in svg)""" + return (val for lst in zip(*self.matrix) for val in lst) + + def is_translate(self, exactly=False): + # type: (bool) -> bool + """Returns True if this transformation is ONLY translate""" + tol = self.absolute_tolerance if not exactly else 0.0 + return ( + fabs(self.a - 1) <= tol + and abs(self.d - 1) <= tol + and fabs(self.b) <= tol + and fabs(self.c) <= tol + ) + + def is_scale(self, exactly=False): + # type: (bool) -> bool + """Returns True if this transformation is ONLY scale""" + tol = self.absolute_tolerance if not exactly else 0.0 + return ( + fabs(self.e) <= tol + and fabs(self.f) <= tol + and fabs(self.b) <= tol + and fabs(self.c) <= tol + ) + + def is_rotate(self, exactly=False): + # type: (bool) -> bool + """Returns True if this transformation is ONLY rotate""" + tol = self.absolute_tolerance if not exactly else 0.0 + return ( + self._is_URT(exactly=exactly) + and fabs(self.e) <= tol + and fabs(self.f) <= tol + and fabs(self.a**2 + self.b**2 - 1) <= tol + ) + + def rotation_degrees(self): + # type: () -> float + """Return the amount of rotation in this transform""" + if not self._is_URT(exactly=False): + raise ValueError( + "Rotation angle is undefined for non-uniformly scaled or skewed " + "matrices" + ) + return atan2(self.b, self.a) * 180 / pi + + def __str__(self): + # type: () -> str + """Format the given matrix into a string representation for svg""" + hexad = tuple(self.to_hexad()) + if self.is_translate(): + if not self: + return "" + return f"translate({self.e:.6g}, {self.f:.6g})" + if self.is_scale(): + return f"scale({self.a:.6g}, {self.d:.6g})" + if self.is_rotate(): + return f"rotate({self.rotation_degrees():.6g})" + return f"matrix({' '.join(f'{var:.6g}' for var in hexad)})" + + def __repr__(self) -> str: + """String representation of this object""" + return ( + f"{type(self).__name__}((" + f"({', '.join(f'{var:.6g}' for var in self.matrix[0])}), " + f"({', '.join(f'{var:.6g}' for var in self.matrix[1])})))" + ) + + def __eq__(self, matrix): + # typing this requires writing a proof for mypy that matrix is really + # MatrixLike + """Test if this transformation is equal to the given matrix""" + if isinstance(matrix, (str, tuple, list, Transform)): + val = all( + fabs(l - r) <= self.absolute_tolerance + for l, r in zip(self.to_hexad(), Transform(matrix).to_hexad()) + ) + else: + val = False + return val + + def __matmul__(self, matrix): + # type: (MatrixLike) -> Transform + """Combine this transform's internal matrix with the given matrix""" + # Conform the input to a known quantity (and convert if needed) + other = Transform(matrix) + # Return a transformation as the combined result + return Transform( + ( + self.a * other.a + self.c * other.b, + self.b * other.a + self.d * other.b, + self.a * other.c + self.c * other.d, + self.b * other.c + self.d * other.d, + self.a * other.e + self.c * other.f + self.e, + self.b * other.e + self.d * other.f + self.f, + ) + ) + + def __imatmul__(self, matrix): + # type: (MatrixLike) -> Transform + """In place multiplication of transform matrices""" + self.matrix = (self @ matrix).matrix + if self.callback is not None: + self.callback(self) + return self + + def __neg__(self): + # type: () -> Transform + """Returns an inverted transformation""" + det = (self.a * self.d) - (self.c * self.b) + # invert the rotation/scaling part + new_a = self.d / det + new_d = self.a / det + new_c = -self.c / det + new_b = -self.b / det + # invert the translational part + new_e = -(new_a * self.e + new_c * self.f) + new_f = -(new_b * self.e + new_d * self.f) + return Transform((new_a, new_b, new_c, new_d, new_e, new_f)) + + def apply_to_point(self, point): + # type: (VectorLike) -> Vector2d + """Transform a tuple (X, Y)""" + if isinstance(point, str): + raise ValueError(f"Will not transform string '{point}'") + point = Vector2d(point) + return Vector2d( + self.a * point.x + self.c * point.y + self.e, + self.b * point.x + self.d * point.y + self.f, + ) + + def _is_URT(self, exactly=False): + # type: (bool) -> bool + """ + Checks that transformation can be decomposed into product of + Uniform scale (U), Rotation around origin (R) and translation (T) + + :return: decomposition as U*R*T is possible + """ + tol = self.absolute_tolerance if not exactly else 0.0 + return (fabs(self.a - self.d) <= tol) and (fabs(self.b + self.c) <= tol) + + def interpolate(self, other, fraction): + # type: (Transform, float) -> Transform + """Interpolate with another Transform. + + .. versionadded:: 1.1 + """ + from .tween import TransformInterpolator + + return TransformInterpolator(self, other).interpolate(fraction) + + +class BoundingInterval: # pylint: disable=too-few-public-methods + """A pair of numbers that represent the minimum and maximum values.""" + + @overload + def __init__(self, other=None): + # type: (Optional[BoundingInterval]) -> None + pass + + @overload + def __init__(self, pair): + # type: (Tuple[float, float]) -> None + pass + + @overload + def __init__(self, value): + # type: (float) -> None + pass + + @overload + def __init__(self, x, y): + # type: (float, float) -> None + pass + + def __init__(self, x=None, y=None): + self.x: Union[int, float, Decimal] + self.y: Union[int, float, Decimal] + self.minimum: float + self.maximum: float + if y is not None: + if isinstance(x, (int, float, Decimal)) and isinstance( + y, (int, float, Decimal) + ): + self.minimum = float(x) + self.maximum = float(y) + else: + raise ValueError( + f"Not a number for scaling: {str((x, y))} " + f"({type(x).__name__},{type(y).__name__})" + ) + + else: + value = x + if value is None: + # identity for addition, zero for intersection + self.minimum, self.maximum = float("+inf"), float("-inf") + elif isinstance(value, BoundingInterval): + self.minimum = value.minimum + self.maximum = value.maximum + elif isinstance(value, (tuple, list)) and len(value) == 2: + self.minimum, self.maximum = min(value), max(value) + elif isinstance(value, (int, float, Decimal)): + self.minimum = self.maximum = float(value) + else: + raise ValueError( + f"Not a number for scaling: {str(value)} ({type(value).__name__})" + ) + + def __bool__(self): + # type: () -> bool + return isfinite(self.minimum) and isfinite(self.maximum) + + __nonzero__ = __bool__ + + def __neg__(self): + # type: () -> BoundingInterval + return BoundingInterval((-1 * self.maximum, -1 * self.minimum)) + + def __add__(self, other): + # type: (BoundingInterval) -> BoundingInterval + """Calculate the bounding interval that covers both given bounding intervals""" + new = BoundingInterval(self) + if other is not None: + new += other + return new + + def __iadd__(self, other): + # type: (BoundingInterval) -> BoundingInterval + other = BoundingInterval(other) + self.minimum = min((self.minimum, other.minimum)) + self.maximum = max((self.maximum, other.maximum)) + return self + + def __radd__(self, other): + # type: (BoundingInterval) -> BoundingInterval + if other is None: + return BoundingInterval(self) + return self + other + + def __and__(self, other: BoundingInterval) -> BoundingInterval: + """Calculate the bounding interval where both given bounding intervals + overlap""" + new = BoundingInterval(self) + if other is not None: + new &= other + return new + + def __iand__(self, other): + # type: (BoundingInterval) -> BoundingInterval + other = BoundingInterval(other) + self.minimum = max((self.minimum, other.minimum)) + self.maximum = min((self.maximum, other.maximum)) + if self.minimum > self.maximum: + self.minimum, self.maximum = float("+inf"), float("-inf") + return self + + def __rand__(self, other): + # type: (BoundingInterval) -> BoundingInterval + if other is None: + return BoundingInterval(self) + return self & other + + def __mul__(self, other: float) -> BoundingInterval: + new = BoundingInterval(self) + if other is not None: + new *= other + return new + + def __imul__(self, other: float) -> BoundingInterval: + self.minimum *= other + self.maximum *= other + return self + + def __iter__(self) -> Generator[float, None, None]: + yield self.minimum + yield self.maximum + + def __eq__(self, other) -> bool: + return tuple(self) == tuple(BoundingInterval(other)) + + def __contains__(self, value: float) -> bool: + return self.minimum <= value <= self.maximum + + def __repr__(self) -> str: + return f"BoundingInterval({self.minimum}, {self.maximum})" + + @property + def center(self): + # type: () -> float + """Pick the middle of the line""" + return self.minimum + ((self.maximum - self.minimum) / 2) + + @property + def size(self): + # type: () -> float + """Return the size difference minimum and maximum""" + return self.maximum - self.minimum + + +class BoundingBox: # pylint: disable=too-few-public-methods + """ + Some functions to compute a rough bbox of a given list of objects. + + BoundingBox(other) + BoundingBox(x, y) + BoundingBox((x1, x2), (y1, y2)) + """ + + width = property(lambda self: self.x.size) + height = property(lambda self: self.y.size) + top = property(lambda self: self.y.minimum) + left = property(lambda self: self.x.minimum) + bottom = property(lambda self: self.y.maximum) + right = property(lambda self: self.x.maximum) + center_x = property(lambda self: self.x.center) + center_y = property(lambda self: self.y.center) + + @overload + def __init__(self, other=None): + # type: (Optional[BoundingBox]) -> None + pass + + @overload + def __init__(self, x, y): + # type: (BoundingIntervalArgs, BoundingIntervalArgs) -> None + pass + + def __init__(self, x=None, y=None): + if y is None: + if x is None: + # identity for addition, zero for intersection + pass + elif isinstance(x, BoundingBox): + x, y = x.x, x.y + else: + raise ValueError( + f"Not a number for scaling: {str(x)} ({type(x).__name__})" + ) + self.x = BoundingInterval(x) + self.y = BoundingInterval(y) + + @staticmethod + def new_xywh(x: float, y: float, width: float, height: float) -> BoundingBox: + """Create a bounding box using x, y, width and height + + .. versionadded:: 1.2""" + return BoundingBox((x, x + width), (y, y + height)) + + def __bool__(self): + # type: () -> bool + return bool(self.x) and bool(self.y) + + __nonzero__ = __bool__ + + def __neg__(self): + # type: () -> BoundingBox + return BoundingBox(-self.x, -self.y) + + def __add__(self, other): + # type: (Optional[BoundingBox]) -> BoundingBox + """Calculate the bounding box that covers both given bounding boxes""" + new = BoundingBox(self) + new += BoundingBox(other) + return new + + def __iadd__(self, other): + # type: (Optional[BoundingBox]) -> BoundingBox + other = BoundingBox(other) + self.x += other.x + self.y += other.y + return self + + def __radd__(self, other): + # type: (Optional[BoundingBox]) -> BoundingBox + return self + other + + def __and__(self, other): + # type: (Optional[BoundingBox]) -> BoundingBox + """Calculate the bounding box where both given bounding boxes overlap""" + new = BoundingBox(self) + new &= BoundingBox(other) + return new + + def __iand__(self, other: Optional[BoundingBox]) -> BoundingBox: + other = BoundingBox(other) + self.x = self.x & other.x + self.y = self.y & other.y + if not self.x or not self.y: + self.x, self.y = BoundingInterval(), BoundingInterval() + return self + + def __rand__(self, other): + # type: (Optional[BoundingBox]) -> BoundingBox + return self & other + + def __mul__(self, factor): + # type: (float) -> BoundingBox + new = BoundingBox(self) + new *= factor + return new + + def __imul__(self, factor): + # type: (float) -> BoundingBox + self.x *= factor + self.y *= factor + return self + + def __eq__(self, other): + # type (object) -> bool + if isinstance(other, BoundingBox): + return tuple(self) == tuple(other) + return False + + def __iter__(self) -> Generator[BoundingBox, None, None]: + yield self.x + yield self.y + + @property + def area(self): + """Return area of the bounding box + + .. versionadded:: 1.2""" + return self.width * self.height + + @property + def minimum(self): + # type: () -> Vector2d + """Return the minimum x,y coords""" + return Vector2d(self.x.minimum, self.y.minimum) + + @property + def maximum(self): + # type: () -> Vector2d + """Return the maximum x,y coords""" + return Vector2d(self.x.maximum, self.y.maximum) + + def __repr__(self): + # type: () -> str + return f"BoundingBox({tuple(self.x)},{tuple(self.y)})" + + @property + def center(self): + # type: () -> Vector2d + """Returns the middle of the bounding box""" + return Vector2d(self.x.center, self.y.center) + + @property + def size(self): + """Returns a vector containing width and height of the bounding box + + .. versionadded:: 1.2""" + return Vector2d(self.x.size, self.y.size) + + def get_anchor(self, xanchor, yanchor, direction=0, selbox=None): + # type: (str, str, Union[int, str], Optional[BoundingBox]) -> float + """Calls get_distance with the given anchor options""" + return self.anchor_distance( + getattr(self, XAN[xanchor]), + getattr(self, YAN[yanchor]), + direction=direction, + selbox=selbox, + ) + + @staticmethod + def anchor_distance( + x: float, + y: float, + direction: Union[int, str] = 0, + selbox: Optional[BoundingBox] = None, + ) -> float: + """Using the x,y returns a single sortable value based on direction and angle + + Args: + x (float): input x coordinate + y (float): input y coordinate + direction (Union[int, str], optional): int/float (custom angle), + tb/bt (top/bottom), lr/rl (left/right), ri/ro (radial). Defaults to 0. + selbox (Optional[BoundingBox], optional): The bounding box of the whole + selection for radial anchors. Defaults to None. + + Raises: + ValueError: if radial distance is requested without the optional selbox + parameter. + + Returns: + float: the anchor distance with respect to the direction. + """ + + rot = 0.0 + if isinstance(direction, (int, float)): # Angle + if direction not in CUSTOM_DIRECTION: + return hypot(x, y) * (cos(radians(-direction) - atan2(y, x))) + direction = CUSTOM_DIRECTION[direction] + + if direction in ("ro", "ri"): + if selbox is None: + raise ValueError( + "Radial distance not available without selection bounding box" + ) + rot = hypot(selbox.x.center - x, selbox.y.center - y) + + return [y, -y, x, -x, rot, -rot][DIRECTION.index(direction)] + + def resize(self, delta_x: float, delta_y: Optional[float] = None) -> BoundingBox: + """Enlarges / shrinks a bounding box by a constant value. If only delta_x + is given, each side is moved by the same amount; if delta_y is given, + different deltas are applied to horizontal and vertical intervals. + + .. versionadded:: 1.2""" + delta_y = delta_y or delta_x + return BoundingBox( + (self.x.minimum - delta_x, self.x.maximum + delta_x), + (self.y.minimum - delta_y, self.y.maximum + delta_y), + ) + + +class DirectedLineSegment: + """ + A directed line segment + + DirectedLineSegment(((x0, y0), (x1, y1))) + """ + + start = Vector2d() # start point of segment + end = Vector2d() # end point of segment + + x0 = property(lambda self: self.start.x) # pylint: disable=invalid-name + y0 = property(lambda self: self.start.y) # pylint: disable=invalid-name + x1 = property(lambda self: self.end.x) + y1 = property(lambda self: self.end.y) + dx = property(lambda self: self.vector.x) # pylint: disable=invalid-name + dy = property(lambda self: self.vector.y) # pylint: disable=invalid-name + + @overload + def __init__(self): + # type: () -> None + pass + + @overload + def __init__(self, other): + # type: (DirectedLineSegment) -> None + pass + + @overload + def __init__(self, start, end): + # type: (VectorLike, VectorLike) -> None + pass + + def __init__(self, *args): + if not args: # overload 0 + start, end = Vector2d(), Vector2d() + elif len(args) == 1: # overload 1 + (other,) = args + start, end = other.start, other.end + elif len(args) == 2: # overload 2 + start, end = args + else: + raise ValueError(f"DirectedLineSegment() can't be constructed from {args}") + + self.start = Vector2d(start) + self.end = Vector2d(end) + + def __eq__(self, other): + # type: (object) -> bool + if isinstance(other, (tuple, DirectedLineSegment)): + return tuple(self) == tuple(other) + return False + + def __iter__(self): + # type: () -> Generator[DirectedLineSegment, None, None] + yield self.x0 + yield self.x1 + yield self.y0 + yield self.y1 + + @property + def vector(self): + # type: () -> Vector2d + """The vector of the directed line segment. + + The vector of the directed line segment represents the length + and direction of segment, but not the starting point. + + .. versionadded:: 1.1 + """ + return self.end - self.start + + @property + def length(self): + # type: () -> float + """Get the length of the line segment""" + return self.vector.length + + @property + def angle(self): + # type: () -> float + """Get the angle of the line created by this segment""" + return atan2(self.dy, self.dx) + + def distance_to_point(self, x, y): + # type: (float, float) -> Union[DirectedLineSegment, Optional[float]] + """Get the distance to the given point (x, y)""" + segment2 = DirectedLineSegment(self.start, (x, y)) + dot2 = segment2.dot(self) + if dot2 <= 0: + return DirectedLineSegment((x, y), self.start).length + if self.dot(self) <= dot2: + return DirectedLineSegment((x, y), self.end).length + return self.perp_distance(x, y) + + def perp_distance(self, x, y): + # type: (float, float) -> Optional[float] + """Perpendicular distance to the given point""" + if self.length == 0: + return None + return fabs((self.dx * (self.y0 - y)) - ((self.x0 - x) * self.dy)) / self.length + + def dot(self, other): + # type: (DirectedLineSegment) -> float + """Get the dot product with the segment with another""" + return self.vector.dot(other.vector) + + def point_at_ratio(self, ratio): + # type: (float) -> Tuple[float, float] + """Get the point at the given ratio along the line""" + return self.x0 + ratio * self.dx, self.y0 + ratio * self.dy + + def point_at_length(self, length): + # type: (float) -> Tuple[float, float] + """Get the point as the length along the line""" + return self.point_at_ratio(length / self.length) + + def parallel(self, x, y): + # type: (float, float) -> DirectedLineSegment + """Create parallel Segment""" + return DirectedLineSegment((x + self.dx, y + self.dy), (x, y)) + + def intersect(self, other): + # type: (DirectedLineSegment) -> Optional[Vector2d] + """Get the intersection between two segments""" + other = DirectedLineSegment(other) + denom = self.vector.cross(other.vector) + num = other.vector.cross(self.start - other.start) + + if denom != 0: + return Vector2d(self.point_at_ratio(num / denom)) + return None + + def __repr__(self): + # type: () -> str + return f"DirectedLineSegment(({self.start}), ({self.end}))" + + +def cubic_extrema(py0, py1, py2, py3): + # type: (float, float, float, float) -> Tuple[float, float] + """Returns the extreme value, given a set of bezier coordinates""" + + atol = 1e-9 + cmin, cmax = min(py0, py3), max(py0, py3) + pd1 = py1 - py0 + pd2 = py2 - py1 + pd3 = py3 - py2 + + def _is_bigger(point): + if 0 < point < 1: + pyx = ( + py0 * (1 - point) * (1 - point) * (1 - point) + + 3 * py1 * point * (1 - point) * (1 - point) + + 3 * py2 * point * point * (1 - point) + + py3 * point * point * point + ) + return min(cmin, pyx), max(cmax, pyx) + return cmin, cmax + + if fabs(pd1 - 2 * pd2 + pd3) > atol: + if pd2 * pd2 > pd1 * pd3: + pds = sqrt(pd2 * pd2 - pd1 * pd3) + cmin, cmax = _is_bigger((pd1 - pd2 + pds) / (pd1 - 2 * pd2 + pd3)) + cmin, cmax = _is_bigger((pd1 - pd2 - pds) / (pd1 - 2 * pd2 + pd3)) + + elif fabs(pd2 - pd1) > atol: + cmin, cmax = _is_bigger(-pd1 / (2 * (pd2 - pd1))) + + return cmin, cmax + + +def quadratic_extrema(py0, py1, py2): + # type: (float, float, float) -> Tuple[float, float] + """Returns the extreme value, given a set of quadratic bezier coordinates""" + atol = 1e-9 + cmin, cmax = min(py0, py2), max(py0, py2) + + def _is_bigger(point): + if 0 < point < 1: + pyx = ( + py0 * (1 - point) * (1 - point) + + 2 * py1 * point * (1 - point) + + py2 * point * point + ) + return min(cmin, pyx), max(cmax, pyx) + return cmin, cmax + + if fabs(py0 + py2 - 2 * py1) > atol: + cmin, cmax = _is_bigger((py0 - py1) / (py0 + py2 - 2 * py1)) + + return cmin, cmax diff --git a/share/extensions/inkex/turtle.py b/share/extensions/inkex/turtle.py new file mode 100644 index 0000000..40c9b60 --- /dev/null +++ b/share/extensions/inkex/turtle.py @@ -0,0 +1,255 @@ +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +"""A Python path turtle for Inkscape extensions""" + +import math +import random +from typing import List, Union + +from .paths import Line, Move, Path, PathCommand +from .elements import PathElement, Group, BaseElement +from .styles import Style + + +class PathTurtle: + """A Python path turtle + + .. versionchanged:: 1.2 + pTurtle has been renamed to PathTurtle.""" + + def __init__(self, home=(0, 0)): + self.__home = [home[0], home[1]] + self.__pos = self.__home[:] + self.__heading = -90 + self.__path = "" + self.__draw = True + self.__new = True + + def forward(self, mag: float): + """Move turtle forward by mag in the current direction.""" + self.setpos( + ( + self.__pos[0] + math.cos(math.radians(self.__heading)) * mag, + self.__pos[1] + math.sin(math.radians(self.__heading)) * mag, + ) + ) + + def backward(self, mag): + """Move turtle backward by mag in the current direction.""" + self.setpos( + ( + self.__pos[0] - math.cos(math.radians(self.__heading)) * mag, + self.__pos[1] - math.sin(math.radians(self.__heading)) * mag, + ) + ) + + def right(self, deg): + """Rotate turtle right by deg degrees. + + Changed in inkex 1.2: The turtle now rotates right (previously left) when + calling this method.""" + self.__heading += deg + + def left(self, deg): + """Rotate turtle left by deg degrees. + + Changed in inkex 1.2: The turtle now rotates left (previously right) when + calling this method.""" + self.__heading -= deg + + def penup(self): + """Enable non-drawing / moving mode""" + self.__draw = False + self.__new = False + + def pendown(self): + """Enable drawing mode""" + if not self.__draw: + self.__new = True + self.__draw = True + + def pentoggle(self): + """Switch between drawing and moving mode""" + if self.__draw: + self.penup() + else: + self.pendown() + + def home(self): + """Move to home position""" + self.setpos(self.__home) + + def clean(self): + """Delete current path""" + self.__path = "" + + def clear(self): + """Delete current path and move to home""" + self.clean() + self.home() + + def setpos(self, arg): + """Move/draw to position, depending on the current state""" + if self.__new: + self.__path += "M" + ",".join([str(i) for i in self.__pos]) + self.__new = False + self.__pos = arg + if self.__draw: + self.__path += "L" + ",".join([str(i) for i in self.__pos]) + + def getpos(self): + """Returns the current position""" + return self.__pos[:] + + def setheading(self, deg): + """Set the heading to deg degrees""" + self.__heading = deg + + def getheading(self): + """Returns the heading in degrees""" + return self.__heading + + def sethome(self, arg): + """Set home position""" + self.__home = list(arg) + + def getPath(self): + """Returns the current path""" + return self.__path + + def rtree(self, size, minimum, pt=False): + """Generates a random tree""" + if size < minimum: + return + self.fd(size) + turn = random.uniform(20, 40) + self.rt(turn) + self.rtree(size * random.uniform(0.5, 0.9), minimum, pt) + self.lt(turn) + turn = random.uniform(20, 40) + self.lt(turn) + self.rtree(size * random.uniform(0.5, 0.9), minimum, pt) + self.rt(turn) + if pt: + self.pu() + self.bk(size) + if pt: + self.pd() + + # pylint: disable=invalid-name + fd = forward + bk = backward + rt = right + lt = left + pu = penup + pd = pendown + + +pTurtle = PathTurtle # should be deprecated + + +class PathBuilder: + """This helper class can be used to construct a path and insert it into a + document. + + .. versionadded:: 1.2""" + + def __init__(self, style: Style): + """Initializes a PathDrawHelper object + + Args: + style (Style): Style of the path. + """ + self.current = Path() + self.style = style + + def add(self, command: Union[PathCommand, List[PathCommand]]): + """Add a Path command to the Helper + + Args: + command (Union[PathCommand, List[PathCommand]]): A (list of) PathCommand(s) + to be appended. + """ + self.current.append(command) + + def terminate(self): + """Terminates current subpath. This method does nothing by default and is + supposed to be overridden in subclasses.""" + + def append_next(self, sibling_before: BaseElement): + """Insert the resulting Path as :class:`inkex.elements._polygons.PathElement` + into the document tree. + + Args: + sibling_before (BaseElement): The element the resulting path will be + appended after. + """ + pth = PathElement() + pth.path = self.current + pth.style = self.style + sibling_before.addnext(pth) + + def Move_to(self, x, y): # pylint: disable=invalid-name + """Shorthand to insert an absolute move command: `M x y`. + + Args: + x (Float): x coordinate to move to + y (Float): y coordinate to move to + """ + self.add(Move(x, y)) + + def Line_to(self, x, y): # pylint: disable=invalid-name + """Shorthand to insert an absolute lineto command: `L x y`. + + Args: + x (Float): x coordinate to draw a line to + y (Float): y coordinate to draw a line to + """ + self.add(Line(x, y)) + + +class PathGroupBuilder(PathBuilder): + """This helper class can be used to construct a group of paths that all have the + same style. + + .. versionadded:: 1.2""" + + def __init__(self, style): + super().__init__(style) + self.result = Group() + + def terminate(self): + """Terminates the current Path, and appends it to the group if it is not + empty.""" + if len(self.current) > 1: + pth = PathElement() + pth.path = self.current.to_absolute() + pth.style = self.style + self.result.append(pth) + self.current = Path() + + def append_next(self, sibling_before: BaseElement): + """Insert the resulting Path as :class:`inkex.elements._groups.Group` into the + document tree. + + Args: + sibling_before (BaseElement): The element the resulting group will be + appended after. + """ + sibling_before.addnext(self.result) diff --git a/share/extensions/inkex/tween.py b/share/extensions/inkex/tween.py new file mode 100644 index 0000000..75bd90c --- /dev/null +++ b/share/extensions/inkex/tween.py @@ -0,0 +1,847 @@ +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# 2020 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +"""Module for interpolating attributes and styles + +.. versionchanged:: 1.2 + Rewritten in inkex 1.2 in an object-oriented structure to support more attributes. +""" +from bisect import bisect_left +import abc +import copy + +from .styles import Style +from .elements._filters import LinearGradient, RadialGradient, Stop +from .transforms import Transform +from .colors import Color +from .units import convert_unit, parse_unit, render_unit +from .bezier import bezlenapprx, cspbezsplit, cspbezsplitatlength, csplength +from .paths import Path, CubicSuperPath +from .elements import SvgDocumentElement +from .utils import FragmentError + + +try: + from typing import Tuple, TypeVar + + Value = TypeVar("Value") + Number = TypeVar("Number", int, float) +except ImportError: + pass + + +def interpcoord(coord_a: Number, coord_b: Number, time: float): + """Interpolate single coordinate by the amount of time""" + return ValueInterpolator(coord_a, coord_b).interpolate(time) + + +def interppoints(point1, point2, time): + # type: (Tuple[float, float], Tuple[float, float], float) -> Tuple[float, float] + """Interpolate coordinate points by amount of time""" + return ArrayInterpolator(point1, point2).interpolate(time) + + +class AttributeInterpolator(abc.ABC): + """Interpolate between attributes""" + + def __init__(self, start_value, end_value): + self.start_value = start_value + self.end_value = end_value + + @staticmethod + def best_style(node): + """Gets the best possible approximation to a node's style. For nodes inside the + element tree of an SVG file, stylesheets defined in the defs of that file can be + taken into account. This should be the case for input elements, but is not + required - in that case, only the local inline style is used. + + During the interpolation process, some nodes are created temporarily, such as + plain gradients of a single color to allow solid<->gradient interpolation. These + are not attached to the document tree and therefore have no root. Since the only + style relevant for them is the inline style, it is acceptable to fallback to it. + + Args: + node (BaseElement): The node to get the best approximated style of + + Returns: + Style: If the node is rooted, the CSS specified style. Else, the inline + style.""" + try: + return node.specified_style() + except FragmentError: + return node.style + + @staticmethod + def create_from_attribute(snode, enode, attribute, method=None): + """Creates an interpolator for an attribute. Currently, only path, transform and + style attributes are supported + + Args: + snode (BaseElement): start element + enode (BaseElement): end element + attribute (str): attribute name (for styles, starting with "style/") + method (AttributeInterpolator, optional): (currently only used for paths). + Specifies a method used to interpolate the attribute. Defaults to None. + + Raises: + ValueError: if an attribute is passed that is not a style, path or transform + attribute + + Returns: + AttributeInterpolator: an interpolator whose type depends on attribute. + """ + if attribute in Style.color_props: + return StyleInterpolator.create_from_fill_stroke(snode, enode, attribute) + if attribute == "d": + if method is None: + method = FirstNodesInterpolator + return method(snode.path, enode.path) + if attribute == "style": + return StyleInterpolator(snode, enode) + if attribute.startswith("style/"): + return StyleInterpolator.create(snode, enode, attribute[6:]) + if attribute == "transform": + return TransformInterpolator(snode.transform, enode.transform) + if method is not None: + return method(snode.get(attribute), enode.get(attribute)) + raise ValueError("only path and style attributes are supported") + + @abc.abstractmethod + def interpolate(self, time=0): + """Interpolation method, needs to be implemented by subclasses""" + return + + +class StyleInterpolator(AttributeInterpolator): + """Class to interpolate styles""" + + def __init__(self, start_value, end_value): + super().__init__(start_value, end_value) + self.interpolators = {} + # some keys are always processed in a certain order, these provide alternative + # interpolation routes if e.g. Color<->none is interpolated + all_keys = list( + dict.fromkeys( + ["fill", "stroke", "fill-opacity", "stroke-opacity", "stroke-width"] + + list(self.best_style(start_value).keys()) + + list(self.best_style(end_value).keys()) + ) + ) + for attr in all_keys: + sstyle = self.best_style(start_value) + estyle = self.best_style(end_value) + if attr not in sstyle and attr not in estyle: + continue + try: + interp = StyleInterpolator.create( + self.start_value, self.end_value, attr + ) + self.interpolators[attr] = interp + except ValueError: + # no interpolation method known for this attribute + pass + + @staticmethod + def create(snode, enode, attribute): + """Creates an Interpolator for a given style attribute, depending on its type: + + - Color properties (such as fill, stroke) -> :class:`ColorInterpolator`, + :class:`GradientInterpolator` ect. + - Unit properties -> :class:`UnitValueInterpolator` + - other properties -> :class:`ValueInterpolator` + + Args: + snode (BaseElement): start element + enode (BaseElement): end element + attribute (str): attribute to interpolate + + Raises: + ValueError: if the attribute is not in any of the lists + + Returns: + AttributeInterpolator: an interpolator object whose type depends on the + attribute. + """ + if attribute in Style.color_props: + return StyleInterpolator.create_from_fill_stroke(snode, enode, attribute) + + if attribute in Style.unit_props: + return UnitValueInterpolator( + AttributeInterpolator.best_style(snode)(attribute), + AttributeInterpolator.best_style(enode)(attribute), + ) + + if attribute in Style.opacity_props: + return ValueInterpolator( + AttributeInterpolator.best_style(snode)(attribute), + AttributeInterpolator.best_style(enode)(attribute), + ) + + raise ValueError("Unknown attribute") + + @staticmethod + def create_from_fill_stroke(snode, enode, attribute): + """Creates an Interpolator for a given color-like attribute + + Args: + snode (BaseElement): start element + enode (BaseElement): end element + attribute (str): attribute to interpolate + + Raises: + ValueError: if the attribute is not color-like + ValueError: if the attribute is unset on both start and end style + + Returns: + AttributeInterpolator: an interpolator object whose type depends on the + attribute. + """ + if attribute not in Style.color_props: + raise ValueError("attribute must be a color property") + + sstyle = AttributeInterpolator.best_style(snode) + estyle = AttributeInterpolator.best_style(enode) + + styles = [[snode, sstyle], [enode, estyle]] + for (cur, curstyle) in styles: + if curstyle(attribute) is None: + cur.style[attribute + "-opacity"] = 0.0 + if attribute == "stroke": + cur.style["stroke-width"] = 0.0 + + # check if style is none, unset or a color + if isinstance( + sstyle(attribute), (LinearGradient, RadialGradient) + ) or isinstance(estyle(attribute), (LinearGradient, RadialGradient)): + # if one of the two styles is a gradient, use gradient interpolation. + try: + return GradientInterpolator.create(snode, enode, attribute) + except ValueError: + # different gradient types, just duplicate the first + return TrivialInterpolator(sstyle(attribute)) + if sstyle(attribute) is None and estyle(attribute) is None: + return TrivialInterpolator("none") + return ColorInterpolator.create(sstyle, estyle, attribute) + + def interpolate(self, time=0): + """Interpolates a style using the interpolators set in self.interpolators + + Args: + time (int, optional): Interpolation position. If 0, start_value is returned, + if 1, end_value is returned. Defaults to 0. + + Returns: + inkex.Style: interpolated style + """ + style = Style() + for prop, interp in self.interpolators.items(): + style[prop] = interp.interpolate(time) + return style + + +class TrivialInterpolator(AttributeInterpolator): + """Trivial interpolator, returns value for every time""" + + def __init__(self, value): + super().__init__(value, value) + + def interpolate(self, time=0): + return self.start_value + + +class ValueInterpolator(AttributeInterpolator): + """Class for interpolation of a single value""" + + def __init__(self, start_value=0, end_value=0): + super().__init__(float(start_value), float(end_value)) + + def interpolate(self, time=0): + """(Linearly) interpolates a value + + Args: + time (int, optional): Interpolation position. If 0, start_value is returned, + if 1, end_value is returned. Defaults to 0. + + Returns: + int: interpolated value + """ + return self.start_value + ((self.end_value - self.start_value) * time) + + +class UnitValueInterpolator(ValueInterpolator): + """Class for interpolation of a value with unit""" + + def __init__(self, start_value=0, end_value=0): + start_val, start_unit = parse_unit(start_value) + end_val = convert_unit(end_value, start_unit) + super().__init__(start_val, end_val) + self.unit = start_unit + + def interpolate(self, time=0): + return render_unit(super().interpolate(time), self.unit) + + +class ArrayInterpolator(AttributeInterpolator): + """Interpolates array-like objects element-wise, e.g. color, transform, + coordinate""" + + def __init__(self, start_value, end_value): + super().__init__(start_value, end_value) + self.interpolators = [ + ValueInterpolator(cur, other) + for (cur, other) in zip(start_value, end_value) + ] + + def interpolate(self, time=0): + """Interpolates an array element-wise + + Args: + time (int, optional): [description]. Defaults to 0. + + Returns: + List: interpolated array + """ + return [interp.interpolate(time) for interp in self.interpolators] + + +class TransformInterpolator(ArrayInterpolator): + """Class for interpolation of transforms""" + + def __init__(self, start_value=Transform(), end_value=Transform()): + """Creates a transform interpolator. + + Args: + start_value (inkex.Transform, optional): start transform. Defaults to + inkex.Transform(). + end_value (inkex.Transform, optional): end transform. Defaults to + inkex.Transform(). + """ + super().__init__(start_value.to_hexad(), end_value.to_hexad()) + + def interpolate(self, time=0): + """Interpolates a transform by interpolating each item in the transform hexad + separately. + + Args: + time (int, optional): Interpolation position. If 0, start_value is returned, + if 1, end_value is returned. Defaults to 0. + + Returns: + Transform: interpolated transform + """ + return Transform(super().interpolate(time)) + + +class ColorInterpolator(ArrayInterpolator): + """Class for color interpolation""" + + @staticmethod + def create(sst, est, attribute): + """Creates a ColorInterpolator for either Fill or stroke, depending on the + attribute. + + Args: + sst (Style): Start style + est (Style): End style + attribute (string): either fill or stroke + + Raises: + ValueError: if none of the start or end style is a color. + + Returns: + ColorInterpolator: A ColorInterpolator object + """ + styles = [sst, est] + for cur, other in zip(styles, reversed(styles)): + if not isinstance(cur(attribute), Color) or cur(attribute) is None: + cur[attribute] = other(attribute) + this = ColorInterpolator( + Color(styles[0](attribute)), Color(styles[1](attribute)) + ) + if this is None: + raise ValueError("One of the two attribute needs to be a plain color") + return this + + def __init__(self, start_value=Color("#000000"), end_value=Color("#000000")): + super().__init__(start_value, end_value) + + def interpolate(self, time=0): + """Interpolates a color by interpolating its r, g, b, a channels separately. + + Args: + time (int, optional): Interpolation position. If 0, start_value is returned, + if 1, end_value is returned. Defaults to 0. + + Returns: + Color: interpolated color + """ + return Color(list(map(int, super().interpolate(time)))) + + +class GradientInterpolator(AttributeInterpolator): + """Base class for Gradient Interpolation""" + + def __init__(self, start_value, end_value, svg=None): + super().__init__(start_value, end_value) + self.svg = svg + # If one of the styles is empty, set it to the gradient of the other + if start_value is None: + self.start_value = end_value + if end_value is None: + self.end_value = start_value + self.transform_interpolator = TransformInterpolator( + self.start_value.gradientTransform, self.end_value.gradientTransform + ) + self.orientation_interpolator = { + attr: UnitValueInterpolator( + self.start_value.get(attr), self.end_value.get(attr) + ) + for attr in self.start_value.orientation_attributes + if self.start_value.get(attr) is not None + and self.end_value.get(attr) is not None + } + if not ( + self.start_value.href is not None + and self.start_value.href is self.end_value.href + ): + # the gradient link to different stops, interpolate between them + # add both start and end offsets, then take distict + newoffsets = sorted( + list(set(self.start_value.stop_offsets + self.end_value.stop_offsets)) + ) + + def func(start, end, time): + return StopInterpolator(start, end).interpolate(time) + + sstops = GradientInterpolator.interpolate_linear_list( + self.start_value.stop_offsets, + list(self.start_value.stops), + newoffsets, + func, + ) + ostops = GradientInterpolator.interpolate_linear_list( + self.end_value.stop_offsets, + list(self.end_value.stops), + newoffsets, + func, + ) + self.newstop_interpolator = [ + StopInterpolator(s1, s2) for s1, s2 in zip(sstops, ostops) + ] + else: + self.newstop_interpolator = None + + @staticmethod + def create(snode, enode, attribute): + """Creates a `GradientInterpolator` for either fill or stroke, depending on + attribute. + + Cases: (A, B) -> Interpolator + + - Linear Gradient, Linear Gradient -> LinearGradientInterpolator + - Color or None, Linear Gradient -> LinearGradientInterpolator + - Radial Gradient, Radial Gradient -> RadialGradientInterpolator + - Color or None, Radial Gradient -> RadialGradientInterpolator + - Radial Gradient, Linear Gradient -> ValueError + - Color or None, Color or None -> ValueError + + Args: + snode (BaseElement): start element + enode (BaseElement): end element + attribute (string): either fill or stroke + + Raises: + ValueError: if none of the styles are a gradient or if they are gradients + of different types + + Returns: + GradientInterpolator: an Interpolator object + """ + interpolator = None + gradienttype = None + # first find out which type of interpolator we need + sstyle = AttributeInterpolator.best_style(snode) + estyle = AttributeInterpolator.best_style(enode) + for cur in [sstyle, estyle]: + curgrad = None + if isinstance(cur(attribute), (LinearGradient, RadialGradient)): + curgrad = cur(attribute) + for gradtype, interp in [ + [LinearGradient, LinearGradientInterpolator], + [RadialGradient, RadialGradientInterpolator], + ]: + if curgrad is not None and isinstance(curgrad, gradtype): + if interpolator is None: + interpolator = interp + gradienttype = gradtype + if not (interp == interpolator): + raise ValueError("Gradient types don't match") + # If one of the styles is empty, set it to the gradient of the other, but with + # zero opacity (and stroke-width for strokes) + # If one of the styles is a plain color, replace it by a gradient with a single + # stop + iterator = [[snode, gradienttype(), enode], [enode, gradienttype(), snode]] + for index in [0, 1]: + curstyle = AttributeInterpolator.best_style(iterator[index][0]) + value = curstyle(attribute) + if value is None: + # if the attribute of one of the two ends is unset, set the opacity to + # zero. + iterator[index][0].style[attribute + "-opacity"] = 0.0 + if attribute == "stroke": + iterator[index][0].style["stroke-width"] = 0.0 + if isinstance(value, Color): + # if the attribute of one of the two ends is a color, convert it to a + # one-stop gradient. Type depends on the type of the other gradient. + interpolator.initialize_position( + iterator[index][1], iterator[index][0].bounding_box() + ) + stop = Stop() + stop.style = Style() + stop.style["stop-color"] = value + stop.offset = 0 + iterator[index][1].add(stop) + stop = Stop() + stop.style = Style() + stop.style["stop-color"] = value + stop.offset = 1 + iterator[index][1].add(stop) + else: + iterator[index][1] = value # is a gradient + if interpolator is None: + raise ValueError("None of the two styles is a gradient") + if interpolator in [LinearGradientInterpolator, RadialGradientInterpolator]: + return interpolator(iterator[0][1], iterator[1][1], snode) + return interpolator(iterator[0][1], iterator[1][1]) + + @staticmethod + def interpolate_linear_list(positions, values, newpositions, func): + """Interpolates a list of values given at n positions to the best approximation + at m newpositions. + + >>> + | + | x + | x + _________________ + pq q p q + (x denotes function values, p: positions, q: newpositions) + A function may be given to interpolate between given values. + + Args: + positions (list[number-like]): position of current function values + values (list[Type]): list of arbitrary type, + ``len(values) == len(positions)`` + newpositions (list[number-like]): position of interpolated values + func (Callable[[Type, Type, float], Type]): Function to interpolate between + values + + Returns: + list[Type]: interpolated function values at positions + """ + newvalues = [] + positions = list(map(float, positions)) + newpositions = list(map(float, newpositions)) + for pos in newpositions: + if len(positions) == 1: + newvalues.append(values[0]) + else: + # current run: + # idxl pos idxr + # p p | p + # q q + idxl = max(0, bisect_left(positions, pos) - 1) + idxr = min(len(positions) - 1, idxl + 1) + fraction = (pos - positions[idxl]) / (positions[idxr] - positions[idxl]) + vall = values[idxl] + valr = values[idxr] + newval = func(vall, valr, fraction) + newvalues.append(newval) + return newvalues + + @staticmethod + def append_to_doc(element, gradient): + """Splits a gradient into stops and orientation, appends it to the document's + defs and returns the href to the orientation gradient. + + Args: + element (BaseElement): an element inside the SVG that the gradient should be + added to + gradient (Gradient): the gradient to append to the document + + Returns: + Gradient: the orientation gradient, or the gradient object if + element has no root or is None + """ + stops, orientation = gradient.stops_and_orientation() + if element is None or ( + element.getparent() is None and not isinstance(element, SvgDocumentElement) + ): + return gradient + element.root.defs.add(orientation) + if len(stops) > 0: + element.root.defs.add(stops, orientation) + orientation.set("xlink:href", f"#{stops.get_id()}") + return orientation + + def interpolate(self, time=0): + """Interpolate with another gradient.""" + newgrad = self.start_value.copy() + # interpolate transforms + newgrad.gradientTransform = self.transform_interpolator.interpolate(time) + + # interpolate orientation + for attr in self.orientation_interpolator.keys(): + newgrad.set(attr, self.orientation_interpolator[attr].interpolate(time)) + + # interpolate stops + if self.newstop_interpolator is not None: + newgrad.remove_all(Stop) + newgrad.add( + *[interp.interpolate(time) for interp in self.newstop_interpolator] + ) + if self.svg is None: + return newgrad + return GradientInterpolator.append_to_doc(self.svg, newgrad) + + +class LinearGradientInterpolator(GradientInterpolator): + """Class for interpolation of linear gradients""" + + def __init__( + self, start_value=LinearGradient(), end_value=LinearGradient(), svg=None + ): + super().__init__(start_value, end_value, svg) + + @staticmethod + def initialize_position(grad, bbox): + """Initializes a linear gradient's position""" + grad.set("x1", bbox.left) + grad.set("x2", bbox.right) + grad.set("y1", bbox.center.y) + grad.set("y2", bbox.center.y) + + +class RadialGradientInterpolator(GradientInterpolator): + """Class to interpolate radial gradients""" + + def __init__( + self, start_value=RadialGradient(), end_value=RadialGradient(), svg=None + ): + super().__init__(start_value, end_value, svg) + + @staticmethod + def initialize_position(grad, bbox): + """Initializes a radial gradient's position""" + x, y = bbox.center + grad.set("cx", x) + grad.set("cy", y) + grad.set("fx", x) + grad.set("fy", y) + grad.set("r", bbox.right - bbox.center.x) + + +class StopInterpolator(AttributeInterpolator): + """Class to interpolate gradient stops""" + + def __init__(self, start_value, end_value): + super().__init__(start_value, end_value) + self.style_interpolator = StyleInterpolator(start_value, end_value) + self.position_interpolator = ValueInterpolator( + float(start_value.offset), float(end_value.offset) + ) + + def interpolate(self, time=0): + """Interpolates a gradient stop by interpolating style and offset separately + + Args: + time (int, optional): Interpolation position. If 0, start_value is returned, + if 1, end_value is returned. Defaults to 0. + + Returns: + Stop: interpolated gradient stop + """ + newstop = Stop() + newstop.style = self.style_interpolator.interpolate(time) + newstop.offset = self.position_interpolator.interpolate(time) + return newstop + + +class PathInterpolator(AttributeInterpolator): + """Base class for Path interpolation""" + + def __init__(self, start_value=Path(), end_value=Path()): + super().__init__(start_value.to_superpath(), end_value.to_superpath()) + self.processed_end_path = None + self.processed_start_path = None + + def truncate_subpaths(self): + """Truncates the longer path so that all subpaths in both paths have an equal + number of bezier commands""" + s = [[]] + e = [[]] + # loop through all subpaths as long as there are remaining ones + while self.start_value and self.end_value: + # if both subpaths contain a bezier command, append it to s and e + if self.start_value[0] and self.end_value[0]: + s[-1].append(self.start_value[0].pop(0)) + e[-1].append(self.end_value[0].pop(0)) + # if the subpath of start_value is empty, add the remaining empty list as + # new subpath of s and one more item of end_value as new subpath of e. + # Afterwards, the loop terminates + elif self.end_value[0]: + s.append(self.start_value.pop(0)) + e[-1].append(self.end_value[0][0]) + e.append([self.end_value[0].pop(0)]) + elif self.start_value[0]: + e.append(self.end_value.pop(0)) + s[-1].append(self.start_value[0][0]) + s.append([self.start_value[0].pop(0)]) + # if there are no commands left in both start_value or end_value, add empty + # list to both start_value and end_value + else: + s.append(self.start_value.pop(0)) + e.append(self.end_value.pop(0)) + self.processed_start_path = s + self.processed_end_path = e + + def interpolate(self, time=0): + # create an interpolated path for each interval + interp = [] + # process subpaths + for ssubpath, esubpath in zip( + self.processed_start_path, self.processed_end_path + ): + if not (ssubpath or esubpath): + break + # add a new subpath to the interpolated path + interp.append([]) + # process each bezier command in the subpaths (which now have equal length) + for sbezier, ebezier in zip(ssubpath, esubpath): + if not (sbezier or ebezier): + break + # add a new bezier command to the last subpath + interp[-1].append([]) + # process points + for point1, point2 in zip(sbezier, ebezier): + if not (point1 or point2): + break + # add a new point to the last bezier command + interp[-1][-1].append( + ArrayInterpolator(point1, point2).interpolate(time) + ) + # remove final subpath if empty. + if not interp[-1]: + del interp[-1] + return CubicSuperPath(interp) + + +class EqualSubsegmentsInterpolator(PathInterpolator): + """Interpolates the path by rediscretizing the subpaths first.""" + + @staticmethod + def get_subpath_lenghts(path): + """prepare lengths for interpolation""" + sp_lenghts, total = csplength(path) + t = 0 + lenghts = [] + for sp in sp_lenghts: + for l in sp: + t += l / total + lenghts.append(t) + lenghts.sort() + return sp_lenghts, total, lenghts + + @staticmethod + def process_path(path, other): + """Rediscretize path so that all subpaths have an equal number of segments, + so that there is a node at the path "times" where path or other have a node + + Args: + path (Path): the first path + other (Path): the second path + + Returns: + Array: the prepared path description for the intermediate path""" + sp_lenghts, total, _ = EqualSubsegmentsInterpolator.get_subpath_lenghts(path) + _, _, lenghts = EqualSubsegmentsInterpolator.get_subpath_lenghts(other) + t = 0 + s = [[]] + for sp in sp_lenghts: + if not path[0]: + s.append(path.pop(0)) + s[-1].append(path[0].pop(0)) + for l in sp: + pt = t + t += l / total + if lenghts and t > lenghts[0]: + while lenghts and lenghts[0] < t: + nt = (lenghts[0] - pt) / (t - pt) + bezes = cspbezsplitatlength(s[-1][-1][:], path[0][0][:], nt) + s[-1][-1:] = bezes[:2] + path[0][0] = bezes[2] + pt = lenghts.pop(0) + s[-1].append(path[0].pop(0)) + return s + + def __init__(self, start_path=Path(), end_path=Path()): + super().__init__(start_path, end_path) + # rediscretisize both paths + start_copy = copy.deepcopy(self.start_value) + # TODO find out why self.start_value.copy() doesn't work + self.start_value = EqualSubsegmentsInterpolator.process_path( + self.start_value, self.end_value + ) + self.end_value = EqualSubsegmentsInterpolator.process_path( + self.end_value, start_copy + ) + + self.truncate_subpaths() + + +class FirstNodesInterpolator(PathInterpolator): + """Interpolates a path by discarding the trailing nodes of the longer subpath""" + + def __init__(self, start_path=Path(), end_path=Path()): + super().__init__(start_path, end_path) + # which path has fewer segments? + lengthdiff = len(self.start_value) - len(self.end_value) + # swap shortest first + if lengthdiff > 0: + self.start_value, self.end_value = self.end_value, self.start_value + # subdivide the shorter path + for _ in range(abs(lengthdiff)): + maxlen = 0 + subpath = 0 + segment = 0 + for y, _ in enumerate(self.start_value): + for z in range(1, len(self.start_value[y])): + leng = bezlenapprx( + self.start_value[y][z - 1], self.start_value[y][z] + ) + if leng > maxlen: + maxlen = leng + subpath = y + segment = z + sp1, sp2 = self.start_value[subpath][segment - 1 : segment + 1] + self.start_value[subpath][segment - 1 : segment + 1] = cspbezsplit(sp1, sp2) + # if swapped, swap them back + if lengthdiff > 0: + self.start_value, self.end_value = self.end_value, self.start_value + self.truncate_subpaths() diff --git a/share/extensions/inkex/units.py b/share/extensions/inkex/units.py new file mode 100644 index 0000000..fec0e87 --- /dev/null +++ b/share/extensions/inkex/units.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) Aaron Spike +# Aurélio A. Heckert +# Bulia Byak +# Nicolas Dufour, nicoduf@yahoo.fr +# Peter J. R. Moulder +# Martin Owens +# +# 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. +# +""" +Convert to and from various units and find the closest matching unit. +""" + +import re + +# a dictionary of unit to user unit conversion factors +CONVERSIONS = { + "in": 96.0, + "pt": 1.3333333333333333, + "px": 1.0, + "mm": 3.779527559055118, + "cm": 37.79527559055118, + "m": 3779.527559055118, + "km": 3779527.559055118, + "Q": 0.94488188976378, + "pc": 16.0, + "yd": 3456.0, + "ft": 1152.0, + "": 1.0, # Default px +} + +# allowed unit types, including percentages, relative units, and others +# that are not suitable for direct conversion to a length. +# Note that this is _not_ an exhaustive list of allowed unit types. +UNITS = [ + "in", + "pt", + "px", + "mm", + "cm", + "m", + "km", + "Q", + "pc", + "yd", + "ft", + "", + "%", + "em", + "ex", + "ch", + "rem", + "vw", + "vh", + "vmin", + "vmax", + "deg", + "grad", + "rad", + "turn", + "s", + "ms", + "Hz", + "kHz", + "dpi", + "dpcm", + "dppx", +] + +UNIT_MATCH = re.compile(rf"({'|'.join(UNITS)})") +NUMBER_MATCH = re.compile(r"(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)") +BOTH_MATCH = re.compile(rf"^\s*{NUMBER_MATCH.pattern}\s*{UNIT_MATCH.pattern}\s*$") + + +def parse_unit(value, default_unit="px", default_value=None): + """ + Takes a value such as 55.32px and returns (55.32, 'px') + Returns default (None) if no match can be found + """ + ret = BOTH_MATCH.match(str(value)) + if ret: + return float(ret.groups()[0]), ret.groups()[-1] or default_unit + return (default_value, default_unit) if default_value is not None else None + + +def are_near_relative(point_a, point_b, eps=0.01): + """Return true if the points are near to eps""" + return (point_a - point_b <= point_a * eps) and ( + point_a - point_b >= -point_a * eps + ) + + +def discover_unit(value, viewbox, default="px"): + """Attempt to detect the unit being used based on the viewbox""" + # Default 100px when width can't be parsed + (value, unit) = parse_unit(value, default_value=100.0) + if unit not in CONVERSIONS: + return default + this_factor = CONVERSIONS[unit] * value / viewbox + + # try to find the svgunitfactor in the list of units known. If we don't find + # something, ... + for unit, unit_factor in CONVERSIONS.items(): + if unit != "": + # allow 1% error in factor + if are_near_relative(this_factor, unit_factor, eps=0.01): + return unit + return default + + +def convert_unit(value, to_unit, default="px"): + """Returns userunits given a string representation of units in another system + + Args: + value: string + to_unit: unit to convert to + default: if ``value`` contains no unit, what unit should be assumed. + + .. versionadded:: 1.1 + """ + value, from_unit = parse_unit(value, default_unit=default, default_value=0.0) + if from_unit in CONVERSIONS and to_unit in CONVERSIONS: + return ( + value * CONVERSIONS[from_unit] / CONVERSIONS.get(to_unit, CONVERSIONS["px"]) + ) + return 0.0 + + +def render_unit(value, unit): + """Checks and then renders a number with its unit""" + try: + if isinstance(value, str): + (value, unit) = parse_unit(value, default_unit=unit) + return f"{value:.6g}{ unit:s}" + except TypeError: + return "" diff --git a/share/extensions/inkex/utils.py b/share/extensions/inkex/utils.py new file mode 100644 index 0000000..2d1dd94 --- /dev/null +++ b/share/extensions/inkex/utils.py @@ -0,0 +1,271 @@ +# coding=utf-8 +# +# Copyright (C) 2010 Nick Drobchenko, nick@cnc-club.ru +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +""" +Basic common utility functions for calculated things +""" +import os +import sys +import random +import re +import math +from argparse import ArgumentTypeError +from itertools import tee + +ABORT_STATUS = -5 + +(X, Y) = range(2) +PY3 = sys.version_info[0] == 3 + +# pylint: disable=line-too-long +# Taken from https://www.w3.org/Graphics/SVG/1.1/paths.html#PathDataBNF +DIGIT_REX_PART = r"[0-9]" +DIGIT_SEQUENCE_REX_PART = rf"(?:{DIGIT_REX_PART}+)" +INTEGER_CONSTANT_REX_PART = DIGIT_SEQUENCE_REX_PART +SIGN_REX_PART = r"[+-]" +EXPONENT_REX_PART = rf"(?:[eE]{SIGN_REX_PART}?{DIGIT_SEQUENCE_REX_PART})" +FRACTIONAL_CONSTANT_REX_PART = rf"(?:{DIGIT_SEQUENCE_REX_PART}?\.{DIGIT_SEQUENCE_REX_PART}|{DIGIT_SEQUENCE_REX_PART}\.)" +FLOATING_POINT_CONSTANT_REX_PART = rf"(?:{FRACTIONAL_CONSTANT_REX_PART}{EXPONENT_REX_PART}?|{DIGIT_SEQUENCE_REX_PART}{EXPONENT_REX_PART})" +NUMBER_REX = re.compile( + rf"(?:{SIGN_REX_PART}?{FLOATING_POINT_CONSTANT_REX_PART}|{SIGN_REX_PART}?{INTEGER_CONSTANT_REX_PART})" +) +# pylint: enable=line-too-long + + +def _pythonpath(): + for pth in os.environ.get("PYTHONPATH", "").split(":"): + if os.path.isdir(pth): + yield pth + + +def get_user_directory(): + """Return the user directory where extensions are stored. + + .. versionadded:: 1.1""" + if "INKSCAPE_PROFILE_DIR" in os.environ: + return os.path.abspath( + os.path.expanduser( + os.path.join(os.environ["INKSCAPE_PROFILE_DIR"], "extensions") + ) + ) + + home = os.path.expanduser("~") + for pth in _pythonpath(): + if pth.startswith(home): + return pth + return None + + +def get_inkscape_directory(): + """Return the system directory where inkscape's core is. + + .. versionadded:: 1.1""" + for pth in _pythonpath(): + if os.path.isdir(os.path.join(pth, "inkex")): + return pth + raise ValueError("Unable to determine the location of Inkscape") + + +class KeyDict(dict): + """ + A normal dictionary, except asking for anything not in the dictionary + always returns the key itself. This is used for translation dictionaries. + """ + + def __getitem__(self, key): + try: + return super().__getitem__(key) + except KeyError: + return key + + +def parse_percent(val: str): + """Parse strings that are either values (i.e., '3.14159') or percentages + (i.e. '75%') to a float. + + .. versionadded:: 1.2""" + val = val.strip() + if val.endswith("%"): + return float(val[:-1]) / 100 + return float(val) + + +def Boolean(value): + """ArgParser function to turn a boolean string into a python boolean""" + if value.upper() == "TRUE": + return True + if value.upper() == "FALSE": + return False + return None + + +def to_bytes(content): + """Ensures the content is bytes + + .. versionadded:: 1.1""" + if isinstance(content, bytes): + return content + return str(content).encode("utf8") + + +def debug(what): + """Print debug message if debugging is switched on""" + errormsg(what) + return what + + +def do_nothing(*args, **kwargs): # pylint: disable=unused-argument + """A blank function to do nothing + + .. versionadded:: 1.1""" + + +def errormsg(msg): + """Intended for end-user-visible error messages. + + (Currently just writes to stderr with an appended newline, but could do + something better in future: e.g. could add markup to distinguish error + messages from status messages or debugging output.) + + Note that this should always be combined with translation:: + + import inkex + ... + inkex.errormsg(_("This extension requires two selected paths.")) + """ + try: + sys.stderr.write(msg) + except TypeError: + sys.stderr.write(str(msg)) + except UnicodeEncodeError: + # Python 2: + # Fallback for cases where sys.stderr.encoding is not Unicode. + # Python 3: + # This will not work as write() does not accept byte strings, but AFAIK + # we should never reach this point as the default error handler is + # 'backslashreplace'. + + # This will be None by default if stderr is piped, so use ASCII as a + # last resort. + encoding = sys.stderr.encoding or "ascii" + sys.stderr.write(msg.encode(encoding, "backslashreplace")) + + # Write '\n' separately to avoid dealing with different string types. + sys.stderr.write("\n") + + +class AbortExtension(Exception): + """Raised to print a message to the user without backtrace""" + + +class DependencyError(NotImplementedError): + """Raised when we need an external python module that isn't available""" + + +class FragmentError(Exception): + """Raised when trying to do rooty things on an xml fragment""" + + +def to(kind): # pylint: disable=invalid-name + """ + Decorator which will turn a generator into a list, tuple or other object type. + """ + + def _inner(call): + def _outer(*args, **kw): + return kind(call(*args, **kw)) + + return _outer + + return _inner + + +def strargs(string, kind=float): + """Returns a list of floats from a string + + .. versionchanged:: 1.1 + also splits at -(minus) signs by adding a space in front of the - sign + + .. versionchanged:: 1.2 + Full support for the `SVG Path data BNF + `_ + """ + return [kind(val) for val in NUMBER_REX.findall(string)] + + +class classproperty: # pylint: disable=invalid-name, too-few-public-methods + """Combine classmethod and property decorators""" + + def __init__(self, func): + self.func = func + + def __get__(self, obj, owner): + return self.func(owner) + + +def filename_arg(name): + """Existing file to read or option used in script arguments""" + filename = os.path.abspath(os.path.expanduser(name)) + if not os.path.isfile(filename): + raise ArgumentTypeError(f"File not found: {name}") + return filename + + +def pairwise(iterable, start=True): + "Iterate over a list with overlapping pairs (see itertools recipes)" + first, then = tee(iterable) + starter = [(None, next(then, None))] + if not start: + starter = [] + return starter + list(zip(first, then)) + + +EVAL_GLOBALS = {} +EVAL_GLOBALS.update(random.__dict__) +EVAL_GLOBALS.update(math.__dict__) + + +def math_eval(function, variable="x"): + """Interpret a function string. All functions from math and random may be used. + + .. versionadded:: 1.1 + + Returns: + a lambda expression if sucessful; otherwise None. + """ + try: + if function != "": + return eval( + f"lambda {variable}: " + (function.strip('"') or "t"), EVAL_GLOBALS, {} + ) + # handle incomplete/invalid function gracefully + except SyntaxError: + pass + return None + + +def is_number(string): + """Checks if a value is a number + + .. versionadded:: 1.2""" + try: + float(string) + return True + except ValueError: + return False diff --git a/share/extensions/inkscape.extension.rng b/share/extensions/inkscape.extension.rng new file mode 100644 index 0000000..b0c3704 --- /dev/null +++ b/share/extensions/inkscape.extension.rng @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file + executable + extension + + + + + + + + + + + + + + + + + + + + python + perl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + path + extensions + inx + absolute + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + g + path + rect + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + header + url + + + + + + + default + preserve + + + + + + + + + + + + + + + + + + + + + + + + + + + + expand + + + + + + + + + + + + + + + + + + + + + + + + + + int + + + + + + + + + + + + + + full + + + + + + + + + + float + + + + + + + + + + + + + + + + + + + full + + + + + + + bool + + + + + + color + + + + + colorbutton + + + + + + + + + + + + string + + + + + + + + + + multiline + + + + + + + + + + + path + + + + + file + files + folder + folders + file_new + folder_new + + + + + + + + + + + + + optiongroup + + + + + combo + radio + + + + + + + + + + + + + + + + + + + + + + + + notebook + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + yes + no + + + + diff --git a/share/extensions/inkscape.extension.schema b/share/extensions/inkscape.extension.schema new file mode 100644 index 0000000..63cb97b --- /dev/null +++ b/share/extensions/inkscape.extension.schema @@ -0,0 +1,9 @@ + + + + + + Warning: @value values should be unique for a given option. + + + diff --git a/share/extensions/inkscape_follow_link.inx b/share/extensions/inkscape_follow_link.inx new file mode 100644 index 0000000..0865c00 --- /dev/null +++ b/share/extensions/inkscape_follow_link.inx @@ -0,0 +1,12 @@ + + + Follow Link + org.inkscape.follow_link + + all + + + + diff --git a/share/extensions/inkscape_follow_link.py b/share/extensions/inkscape_follow_link.py new file mode 100755 index 0000000..54dac76 --- /dev/null +++ b/share/extensions/inkscape_follow_link.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# coding=utf-8 + +import threading +import webbrowser + +import inkex +from inkex import Anchor + + +class ThreadWebsite(threading.Thread): + """Visit the website without locking inkscape""" + + def __init__(self, url): + threading.Thread.__init__(self) + self.url = url + + def run(self): + webbrowser.open(self.url) + + +class FollowLink(inkex.EffectExtension): + """Get the first selected item and follow it's href/url""" + + def effect(self): + for node in self.svg.selection.filter(Anchor): + vwswli = ThreadWebsite(node.get("xlink:href")) + vwswli.start() + break + + +if __name__ == "__main__": + FollowLink().run() diff --git a/share/extensions/inkweb.js b/share/extensions/inkweb.js new file mode 100644 index 0000000..81f3b23 --- /dev/null +++ b/share/extensions/inkweb.js @@ -0,0 +1,223 @@ +/* +** InkWeb - Inkscape's Javscript features for the open vector web +** +** Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +** +** ********* Bugs and New Fetures ************************************* +** If you found any bug on this script or if you want to propose a +** new feature, please report it in the inkscape bug tracker +** https://inkscape.org/report . +** ******************************************************************** +** +** This program 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 3 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 Lesser 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, see . +*/ + +var InkWeb = { + + version: 0.04, + + NS: { + svg: "http://www.w3.org/2000/svg", + sodipodi: "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + inkscape: "http://www.inkscape.org/namespaces/inkscape", + cc: "http://creativecommons.org/ns#", + dc: "http://purl.org/dc/elements/1.1/", + rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace" + } + +}; + +InkWeb.el = function (tag, attributes) { + // A helper to create SVG elements + var element = document.createElementNS( this.NS.svg, tag ); + for ( var att in attributes ) { + switch ( att ) { + case "parent": + attributes.parent.appendChild( element ); + break; + case "text": + element.appendChild( document.createTextNode( attributes.text ) ); + break; + default: + element.setAttribute( att, attributes[att] ); + } + } + return element; +} + +InkWeb.reGetStyleAttVal = function (att) { + return new RegExp( "(^|.*;)[ ]*"+ att +":([^;]*)(;.*|$)" ) +} + +InkWeb.getStyle = function (el, att) { + // This method is needed because el.style is only working + // to HTML style in the Firefox 3.0 + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + var match = this.reGetStyleAttVal(att).exec(style); + if ( match ) { + return match[2]; + } else { + return false; + } +} + +InkWeb.setStyle = function (el, att, val) { + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + re = this.reGetStyleAttVal(att); + if ( re.test(style) ) { + style = style.replace( re, "$1"+ att +":"+ val +"$3" ); + } else { + style += ";"+ att +":"+ val; + } + el.setAttribute( "style", style ); + return val +} + +InkWeb.transmitAtt = function (conf) { + conf.att = conf.att.split( /\s+/ ); + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to.join ) + conf.to = [ conf.to ]; + for ( var toEl,elN=0; toEl=conf.to[elN]; elN++ ) { + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + for ( var i=0; i + + Interpolate + org.ekips.filter.interp + 1.00 + 5 + + + + + true + false + false + + path + + + + + + diff --git a/share/extensions/interp.py b/share/extensions/interp.py new file mode 100755 index 0000000..6129162 --- /dev/null +++ b/share/extensions/interp.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# 2020 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +""" Interpolate between two paths, respecting their style """ +import copy + +import inkex +from inkex.utils import pairwise +from inkex.tween import ( + AttributeInterpolator, + StyleInterpolator, + EqualSubsegmentsInterpolator, + FirstNodesInterpolator, +) + +from inkex.localization import inkex_gettext as _ + + +class Interp(inkex.EffectExtension): + """Interpolate extension""" + + def add_arguments(self, pars): + pars.add_argument( + "-e", + "--exponent", + type=float, + default=1.0, + help="values other than zero give non linear interpolation", + ) + pars.add_argument( + "-s", "--steps", type=int, default=5, help="number of interpolation steps" + ) + pars.add_argument( + "-m", + "--method", + type=str, + default="equalSubsegments", + help="method of interpolation", + ) + pars.add_argument( + "-d", "--dup", type=inkex.Boolean, default=True, help="duplicate endpaths" + ) + pars.add_argument( + "--style", + type=inkex.Boolean, + default=False, + help="try interpolation of some style properties", + ) + pars.add_argument( + "--zsort", + type=inkex.Boolean, + default=False, + help="use z-order instead of selection order", + ) + + def effect(self): + steps = self.get_steps() + + objectpairs = self.get_copied_path_pairs() + if not objectpairs: + raise inkex.AbortExtension(_("At least two paths need to be selected")) + + for (elem1, elem2) in objectpairs: + + method = EqualSubsegmentsInterpolator + if self.options.method == "firstNodes": + method = FirstNodesInterpolator + + path_interpolator = AttributeInterpolator.create_from_attribute( + elem1, elem2, "d", method=method + ) + if self.options.style: + style_interpolator = StyleInterpolator(elem1, elem2) + + group = self.svg.get_current_layer().add(inkex.Group()) + for time in steps: + interpolated_path = path_interpolator.interpolate(time) + new = group.add(inkex.PathElement()) + new.path = interpolated_path + if self.options.style: + interpolated_style = style_interpolator.interpolate(time) + new.style = interpolated_style + else: + new.style = copy.deepcopy(elem1.style) + + def get_steps(self): + """Returns the interpolation steps as a monotonous array with elements between 0 and 1. + 0 and 1 are added as first and last elements if the source paths should be duplicated""" + exponent = self.options.exponent + # if exponent >= 0: + # exponent += 1.0 + # else: + # exponent = 1.0 / (1.0 - exponent) + steps = [ + ((i + 1) / (self.options.steps + 1.0)) ** exponent + for i in range(self.options.steps) + ] + if self.options.dup: + steps = [0] + steps + [1] + return steps + + def get_copied_path_pairs(self): + """Returns deep copies of pairs of subsequent objects of the + current selection, either in z order or in selection order. + Objects other than path objects are ignored. Transforms are baked in.""" + if self.options.zsort: + # work around selection order swapping with Live Preview + objects = self.svg.selection.rendering_order() + else: + # use selection order (default) + objects = self.svg.selection + + objects = [ + node for node in objects.values() if isinstance(node, inkex.PathElement) + ] + + for node in objects: + node.apply_transform() + + objectpairs = pairwise(objects, start=False) + return objectpairs + + +if __name__ == "__main__": + Interp().run() diff --git a/share/extensions/interp_att_g.inx b/share/extensions/interp_att_g.inx new file mode 100644 index 0000000..6c417a0 --- /dev/null +++ b/share/extensions/interp_att_g.inx @@ -0,0 +1,57 @@ + + + Interpolate Attribute in a group + org.inkscape.filter.interp_att_g + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + all + + + + + + diff --git a/share/extensions/interp_att_g.py b/share/extensions/interp_att_g.py new file mode 100755 index 0000000..61b8d8b --- /dev/null +++ b/share/extensions/interp_att_g.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# +""" +Interpolation of attributes in selected objects or group's children. +""" + +import inkex +from inkex.localization import inkex_gettext as _ +from inkex.tween import ColorInterpolator, ValueInterpolator, AttributeInterpolator +from inkex.utils import is_number + + +class InterpAttG(inkex.EffectExtension): + """ + This effect applies a value for any interpolatable attribute for all + elements inside the selected group or for all elements in a multiple selection. + """ + + def __init__(self): + super(InterpAttG, self).__init__() + self.arg_parser.add_argument( + "-a", + "--att", + type=str, + dest="att", + default="width", + help="Attribute to be interpolated.", + ) + self.arg_parser.add_argument( + "-o", + "--att-other", + type=str, + dest="att_other", + help="Other attribute (for a limited UI).", + ) + self.arg_parser.add_argument( + "-t", + "--att-other-type", + type=self.arg_class([ColorInterpolator, ValueInterpolator]), + dest="att_other_type", + help="The other attribute type.", + ) + self.arg_parser.add_argument( + "-w", + "--att-other-where", + type=str, + dest="att_other_where", + default="tag", + help="That is a tag attribute or a style attribute?", + ) + self.arg_parser.add_argument( + "-s", + "--start-val", + type=str, + dest="start_val", + default="#F00", + help="Initial interpolation value.", + ) + self.arg_parser.add_argument( + "-e", + "--end-val", + type=str, + dest="end_val", + default="#00F", + help="End interpolation value.", + ) + self.arg_parser.add_argument( + "-u", "--unit", type=str, dest="unit", default="none", help="Values unit." + ) + self.arg_parser.add_argument( + "--zsort", + type=inkex.Boolean, + dest="zsort", + default=False, + help="use z-order instead of selection order", + ) + self.arg_parser.add_argument( + "--tab", + type=str, + dest="tab", + help="The selected UI-tab when OK was pressed", + ) + + def get_elements(self): + """Returns a list of elements to work on""" + if not self.svg.selection: + return [] + + if len(self.svg.selection) > 1: + # multiple selection + if self.options.zsort: + return list(self.svg.selection.rendering_order().values()) + return list(self.svg.selection.values()) + + # must be a group + node = self.svg.selection.filter(inkex.Group).first() + return list(node) or [] + + def create_dummy_nodes(self, path): + """Create dummy nodes to use the interpolation classes defined in inkex.tween""" + pat1 = inkex.PathElement() + pat2 = inkex.PathElement() + + start_value = self.options.start_val.replace(",", ".") + end_value = self.options.end_val.replace(",", ".") + if self.options.unit != "none": + start_value += self.options.unit + end_value += self.options.unit + self.apply_value(pat1, path, start_value) + self.apply_value(pat2, path, end_value) + return pat1, pat2 + + @staticmethod + def apply_value(node, path, value): + """Applies a value to a given node. If path starts with "transform/" or "style/", the + value is applied to either transform or style.""" + if path.startswith("style/"): + att_name = path[6:] + node.style[att_name] = value + elif path.startswith("transform/"): + if not is_number(value): + raise inkex.AbortExtension( + _("Unable to set attribute {} to {}").format(path, value) + ) + if path == "transform/trans-x": + node.transform.add_translate(value, 0) + elif path == "transform/trans-y": + node.transform.add_translate(0, value) + elif path == "transform/scale": + node.transform.add_scale(value) + elif path == "transform": + node.transform @= value + else: + node.set(path, value) + + def effect(self): + method = None + if self.options.att == "other": + if self.options.att_other is None: + raise inkex.AbortExtension( + _("You selected 'Other'. Please enter an attribute to interpolate.") + ) + if self.options.att_other_where == "tag": + path = self.options.att_other + else: + path = self.options.att_other_where + "/" + self.options.att_other + method = self.options.att_other_type + else: + path = self.options.att + if self.options.att == "height" or self.options.att == "width": + method = inkex.tween.UnitValueInterpolator + + path1, path2 = self.create_dummy_nodes(path) + if path.startswith("transform"): + path = "transform" + try: + # maybe tween knows what do do with this attribute? + interpolator = AttributeInterpolator.create_from_attribute( + path1, path2, path, None + ) + except: + # okay, apparently not + interpolator = AttributeInterpolator.create_from_attribute( + path1, path2, path, method + ) + collection = self.get_elements() + if not collection: + raise inkex.AbortExtension(_("There is no selection to interpolate")) + + steps = [1.0 / (len(collection) - 1) * i for i in range(len(collection))] + + for time, node in zip(steps, collection): + new_value = interpolator.interpolate(time) + InterpAttG.apply_value(node, path, new_value) + + return True + + +if __name__ == "__main__": + InterpAttG().run() diff --git a/share/extensions/jessyInk.js b/share/extensions/jessyInk.js new file mode 100644 index 0000000..433c1d1 --- /dev/null +++ b/share/extensions/jessyInk.js @@ -0,0 +1,2727 @@ +// Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Set onload event handler. +window.onload = jessyInkInit; + +// Creating a namespace dictionary. The standard Inkscape namespaces are taken from inkex.py. +var NSS = new Object(); +NSS['sodipodi']='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'; +NSS['cc']='http://web.resource.org/cc/'; +NSS['svg']='http://www.w3.org/2000/svg'; +NSS['dc']='http://purl.org/dc/elements/1.1/'; +NSS['rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#'; +NSS['inkscape']='http://www.inkscape.org/namespaces/inkscape'; +NSS['xlink']='http://www.w3.org/1999/xlink'; +NSS['xml']='http://www.w3.org/XML/1998/namespace'; +NSS['jessyink']='https://launchpad.net/jessyink'; + +// Keycodes. +var LEFT_KEY = 37; // cursor left keycode +var UP_KEY = 38; // cursor up keycode +var RIGHT_KEY = 39; // cursor right keycode +var DOWN_KEY = 40; // cursor down keycode +var PAGE_UP_KEY = 33; // page up keycode +var PAGE_DOWN_KEY = 34; // page down keycode +var HOME_KEY = 36; // home keycode +var END_KEY = 35; // end keycode +var ENTER_KEY = 13; // next slide +var SPACE_KEY = 32; +var ESCAPE_KEY = 27; + +// Presentation modes. +var SLIDE_MODE = 1; +var INDEX_MODE = 2; +var DRAWING_MODE = 3; + +// Mouse handler actions. +var MOUSE_UP = 1; +var MOUSE_DOWN = 2; +var MOUSE_MOVE = 3; +var MOUSE_WHEEL = 4; + +// Parameters. +var ROOT_NODE = document.getElementsByTagNameNS(NSS["svg"], "svg")[0]; +var HEIGHT = 0; +var WIDTH = 0; +var INDEX_COLUMNS_DEFAULT = 4; +var INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; +var INDEX_OFFSET = 0; +var STATE_START = -1; +var STATE_END = -2; +var BACKGROUND_COLOR = null; +var slides = new Array(); + +// Initialisation. +var currentMode = SLIDE_MODE; +var masterSlide = null; +var activeSlide = 0; +var activeEffect = 0; +var timeStep = 30; // 40 ms equal 25 frames per second. +var lastFrameTime = null; +var processingEffect = false; +var transCounter = 0; +var effectArray = 0; +var defaultTransitionInDict = new Object(); +defaultTransitionInDict["name"] = "appear"; +var defaultTransitionOutDict = new Object(); +defaultTransitionOutDict["name"] = "appear"; +var jessyInkInitialised = false; + +// Initialise char and key code dictionaries. +var charCodeDictionary = getDefaultCharCodeDictionary(); +var keyCodeDictionary = getDefaultKeyCodeDictionary(); + +// Initialise mouse handler dictionary. +var mouseHandlerDictionary = getDefaultMouseHandlerDictionary(); + +var progress_bar_visible = false; +var timer_elapsed = 0; +var timer_start = timer_elapsed; +var timer_duration = 15; // 15 minutes + +var history_counter = 0; +var history_original_elements = new Array(); +var history_presentation_elements = new Array(); + +var mouse_original_path = null; +var mouse_presentation_path = null; +var mouse_last_x = -1; +var mouse_last_y = -1; +var mouse_min_dist_sqr = 3 * 3; +var path_colour = "red"; +var path_width_default = 3; +var path_width = path_width_default; +var path_paint_width = path_width; + +var number_of_added_slides = 0; + +/** Initialisation function. + * The whole presentation is set-up in this function. + */ +function jessyInkInit() +{ + // Make sure we only execute this code once. Double execution can occur if the onload event handler is set + // in the main svg tag as well (as was recommended in earlier versions). Executing this function twice does + // not lead to any problems, but it takes more time. + if (jessyInkInitialised) + return; + + // Making the presentation scalable. + var VIEWBOX = ROOT_NODE.getAttribute("viewBox"); + + if (VIEWBOX) + { + WIDTH = ROOT_NODE.viewBox.animVal.width; + HEIGHT = ROOT_NODE.viewBox.animVal.height; + } + else + { + HEIGHT = parseFloat(ROOT_NODE.getAttribute("height")); + WIDTH = parseFloat(ROOT_NODE.getAttribute("width")); + ROOT_NODE.setAttribute("viewBox", "0 0 " + WIDTH + " " + HEIGHT); + } + + ROOT_NODE.setAttribute("width", "100%"); + ROOT_NODE.setAttribute("height", "100%"); + + // Setting the background color. + var namedViews = document.getElementsByTagNameNS(NSS["sodipodi"], "namedview"); + + for (var counter = 0; counter < namedViews.length; counter++) + { + if (namedViews[counter].hasAttribute("id") && namedViews[counter].hasAttribute("pagecolor")) + { + if (namedViews[counter].getAttribute("id") == "base") + { + BACKGROUND_COLOR = namedViews[counter].getAttribute("pagecolor"); + var newAttribute = "background-color:" + BACKGROUND_COLOR + ";"; + + if (ROOT_NODE.hasAttribute("style")) + newAttribute += ROOT_NODE.getAttribute("style"); + + ROOT_NODE.setAttribute("style", newAttribute); + } + } + } + + // Defining clip-path. + var defsNodes = document.getElementsByTagNameNS(NSS["svg"], "defs"); + + if (defsNodes.length > 0) + { + var existingClipPath = document.getElementById("jessyInkSlideClipPath"); + + if (!existingClipPath) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + var clipPath = document.createElementNS(NSS["svg"], "clipPath"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + + clipPath.setAttribute("id", "jessyInkSlideClipPath"); + clipPath.setAttribute("clipPathUnits", "userSpaceOnUse"); + + clipPath.appendChild(rectNode); + defsNodes[0].appendChild(clipPath); + } + } + + // Making a list of the slide and finding the master slide. + var nodes = document.getElementsByTagNameNS(NSS["svg"], "g"); + var tempSlides = new Array(); + var existingJessyInkPresentationLayer = null; + + for (var counter = 0; counter < nodes.length; counter++) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") && (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") == "layer")) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "masterSlide") == "masterSlide") + masterSlide = nodes[counter]; + else if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "presentationLayer") == "presentationLayer") + existingJessyInkPresentationLayer = nodes[counter]; + else + tempSlides.push(nodes[counter].getAttribute("id")); + } + else if (nodes[counter].getAttributeNS(NSS['jessyink'], 'element')) + { + handleElement(nodes[counter]); + } + } + + // Hide master slide set default transitions. + if (masterSlide) + { + masterSlide.style.display = "none"; + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionIn")) + defaultTransitionInDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionIn")); + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionOut")) + defaultTransitionOutDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionOut")); + } + + if (existingJessyInkPresentationLayer != null) + { + existingJessyInkPresentationLayer.parentNode.removeChild(existingJessyInkPresentationLayer); + } + + // Set start slide. + var hashObj = new LocationHash(window.location.hash); + + activeSlide = hashObj.slideNumber; + activeEffect = hashObj.effectNumber; + + if (activeSlide < 0) + activeSlide = 0; + else if (activeSlide >= tempSlides.length) + activeSlide = tempSlides.length - 1; + + var originalNode = document.getElementById(tempSlides[counter]); + + var JessyInkPresentationLayer = document.createElementNS(NSS["svg"], "g"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "label", "JessyInk Presentation Layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["jessyink"], "presentationLayer", "presentationLayer"); + JessyInkPresentationLayer.setAttribute("id", "jessyink_presentation_layer"); + JessyInkPresentationLayer.style.display = "inherit"; + ROOT_NODE.appendChild(JessyInkPresentationLayer); + + // Gathering all the information about the transitions and effects of the slides, set the background + // from the master slide and substitute the auto-texts. + for (var counter = 0; counter < tempSlides.length; counter++) + { + var originalNode = document.getElementById(tempSlides[counter]); + originalNode.style.display = "none"; + var node = suffixNodeIds(originalNode.cloneNode(true), "_" + counter); + JessyInkPresentationLayer.appendChild(node); + slides[counter] = new Object(); + slides[counter]["original_element"] = originalNode; + slides[counter]["element"] = node; + + // Set build in transition. + slides[counter]["transitionIn"] = new Object(); + + var dict; + + if (node.hasAttributeNS(NSS["jessyink"], "transitionIn")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionIn")); + else + dict = defaultTransitionInDict; + + slides[counter]["transitionIn"]["name"] = dict["name"]; + slides[counter]["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + slides[counter]["transitionOut"] = new Object(); + + if (node.hasAttributeNS(NSS["jessyink"], "transitionOut")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionOut")); + else + dict = defaultTransitionOutDict; + + slides[counter]["transitionOut"]["name"] = dict["name"]; + slides[counter]["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + counter); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + node.insertBefore(clonedNode, node.firstChild); + } + + // Setting clip path. + node.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + + // Substitute auto texts. + substituteAutoTexts(node, node.getAttributeNS(NSS["inkscape"], "label"), counter + 1, tempSlides.length); + + node.removeAttributeNS(NSS["inkscape"], "groupmode"); + node.removeAttributeNS(NSS["inkscape"], "label"); + + // Set effects. + var tempEffects = new Array(); + var groups = new Object(); + + for (var IOCounter = 0; IOCounter <= 1; IOCounter++) + { + var propName = ""; + var dir = 0; + + if (IOCounter == 0) + { + propName = "effectIn"; + dir = 1; + } + else if (IOCounter == 1) + { + propName = "effectOut"; + dir = -1; + } + + var effects = getElementsByPropertyNS(node, NSS["jessyink"], propName); + + for (var effectCounter = 0; effectCounter < effects.length; effectCounter++) + { + var element = document.getElementById(effects[effectCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], propName)); + + // Put every element that has an effect associated with it, into its own group. + // Unless of course, we already put it into its own group. + if (!(groups[element.id])) + { + var newGroup = document.createElementNS(NSS["svg"], "g"); + + element.parentNode.insertBefore(newGroup, element); + newGroup.appendChild(element.parentNode.removeChild(element)); + groups[element.id] = newGroup; + } + + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = dir; + effectDict["element"] = groups[element.id]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + if (!tempEffects[dict["order"]]) + tempEffects[dict["order"]] = new Array(); + + tempEffects[dict["order"]][tempEffects[dict["order"]].length] = effectDict; + } + } + + // Make invisible, but keep in rendering tree to ensure that bounding box can be calculated. + node.setAttribute("opacity",0); + node.style.display = "inherit"; + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (node.firstChild) + transformGroup.appendChild(node.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (node.getAttribute("transform")) + { + transformGroup.setAttribute("transform", node.getAttribute("transform")); + node.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + slides[counter]["viewGroup"] = node.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + counter); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + slides[counter]["viewGroup"].insertBefore(rectNode, slides[counter]["viewGroup"].firstChild); + } + + // Set views. + var tempViews = new Array(); + var views = getElementsByPropertyNS(node, NSS["jessyink"], "view"); + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + // Set initial view even if there are no other views. + slides[counter]["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + slides[counter].initialView = matrixOld.toAttribute(); + + for (var viewCounter = 0; viewCounter < views.length; viewCounter++) + { + var element = document.getElementById(views[viewCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], "view")); + + if (dict["order"] == 0) + { + matrixOld = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + slides[counter].initialView = matrixOld.toAttribute(); + } + else + { + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = 1; + effectDict["element"] = slides[counter]["viewGroup"]; + effectDict["order"] = dict["order"]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + effectDict["options"]["matrixNew"] = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + + tempViews[dict["order"]] = effectDict; + } + + // Remove element. + element.parentNode.removeChild(element); + } + + // Consolidate view array and append it to the effect array. + if (tempViews.length > 0) + { + for (var viewCounter = 0; viewCounter < tempViews.length; viewCounter++) + { + if (tempViews[viewCounter]) + { + tempViews[viewCounter]["options"]["matrixOld"] = matrixOld; + matrixOld = tempViews[viewCounter]["options"]["matrixNew"]; + + if (!tempEffects[tempViews[viewCounter]["order"]]) + tempEffects[tempViews[viewCounter]["order"]] = new Array(); + + tempEffects[tempViews[viewCounter]["order"]][tempEffects[tempViews[viewCounter]["order"]].length] = tempViews[viewCounter]; + } + } + } + + // Set consolidated effect array. + if (tempEffects.length > 0) + { + slides[counter]["effects"] = new Array(); + + for (var effectCounter = 0; effectCounter < tempEffects.length; effectCounter++) + { + if (tempEffects[effectCounter]) + slides[counter]["effects"][slides[counter]["effects"].length] = tempEffects[effectCounter]; + } + } + + node.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + + // Set visibility for initial state. + if (counter == activeSlide) + { + node.style.display = "inherit"; + node.setAttribute("opacity",1); + } + else + { + node.style.display = "none"; + node.setAttribute("opacity",0); + } + } + + // Set key handler. + var jessyInkObjects = document.getElementsByTagNameNS(NSS["svg"], "g"); + + for (var counter = 0; counter < jessyInkObjects.length; counter++) + { + var elem = jessyInkObjects[counter]; + + if (elem.getAttributeNS(NSS["jessyink"], "customKeyBindings")) + { + if (elem.getCustomKeyBindings != undefined) + keyCodeDictionary = elem.getCustomKeyBindings(); + + if (elem.getCustomCharBindings != undefined) + charCodeDictionary = elem.getCustomCharBindings(); + } + } + + // Set mouse handler. + var jessyInkMouseHandler = document.getElementsByTagNameNS(NSS["jessyink"], "mousehandler"); + + for (var counter = 0; counter < jessyInkMouseHandler.length; counter++) + { + var elem = jessyInkMouseHandler[counter]; + + if (elem.getMouseHandler != undefined) + { + var tempDict = elem.getMouseHandler(); + + for (mode in tempDict) + { + if (!mouseHandlerDictionary[mode]) + mouseHandlerDictionary[mode] = new Object(); + + for (handler in tempDict[mode]) + mouseHandlerDictionary[mode][handler] = tempDict[mode][handler]; + } + } + } + + // Check effect number. + if ((activeEffect < 0) || (!slides[activeSlide].effects)) + { + activeEffect = 0; + } + else if (activeEffect > slides[activeSlide].effects.length) + { + activeEffect = slides[activeSlide].effects.length; + } + + createProgressBar(JessyInkPresentationLayer); + hideProgressBar(); + setProgressBarValue(activeSlide); + setTimeIndicatorValue(0); + setInterval("updateTimer()", 1000); + setSlideToState(activeSlide, activeEffect); + jessyInkInitialised = true; +} + +/** Function to substitute the auto-texts. + * + * @param node the node + * @param slideName name of the slide the node is on + * @param slideNumber number of the slide the node is on + * @param numberOfSlides number of slides in the presentation + */ +function substituteAutoTexts(node, slideName, slideNumber, numberOfSlides) +{ + var texts = node.getElementsByTagNameNS(NSS["svg"], "tspan"); + + for (var textCounter = 0; textCounter < texts.length; textCounter++) + { + if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideNumber") + texts[textCounter].firstChild.nodeValue = slideNumber; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "numberOfSlides") + texts[textCounter].firstChild.nodeValue = numberOfSlides; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideTitle") + texts[textCounter].firstChild.nodeValue = slideName; + } +} + +/** Convenience function to get an element depending on whether it has a property with a particular name. + * This function emulates some dearly missed XPath functionality. + * + * @param node the node + * @param namespace namespace of the attribute + * @param name attribute name + */ +function getElementsByPropertyNS(node, namespace, name) +{ + var elems = new Array(); + + if (node.getAttributeNS(namespace, name)) + elems.push(node.getAttribute("id")); + + for (var counter = 0; counter < node.childNodes.length; counter++) + { + if (node.childNodes[counter].nodeType == 1) + elems = elems.concat(getElementsByPropertyNS(node.childNodes[counter], namespace, name)); + } + + return elems; +} + +/** Function to dispatch the next effect, if there is none left, change the slide. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function dispatchEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (dir == 1) + { + effectArray = slides[activeSlide]["effects"][activeEffect]; + activeEffect += dir; + } + else if (dir == -1) + { + activeEffect += dir; + effectArray = slides[activeSlide]["effects"][activeEffect]; + } + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to skip effects and directly either put the slide into start or end state or change slides. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function skipEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (slides[activeSlide]["effects"] && (dir == 1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == 1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + processingEffect = false; + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to change between slides. + * + * @param dir direction (1 = forwards, -1 = backwards) + */ +function changeSlide(dir) +{ + processingEffect = true; + effectArray = new Array(); + + effectArray[0] = new Object(); + if (dir == 1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[0]["dir"] = -1; + } + else if (dir == -1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[0]["dir"] = 1; + } + effectArray[0]["element"] = slides[activeSlide]["element"]; + + activeSlide += dir; + setProgressBarValue(activeSlide); + + effectArray[1] = new Object(); + + if (dir == 1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[1]["dir"] = 1; + } + else if (dir == -1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[1]["dir"] = -1; + } + + effectArray[1]["element"] = slides[activeSlide]["element"]; + + if (slides[activeSlide]["effects"] && (dir == -1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == -1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); +} + +/** Function to toggle between index and slide mode. +*/ +function toggleSlideIndex() +{ + var suspendHandle = ROOT_NODE.suspendRedraw(500); + + if (currentMode == SLIDE_MODE) + { + hideProgressBar(); + INDEX_OFFSET = -1; + indexSetPageSlide(activeSlide); + currentMode = INDEX_MODE; + } + else if (currentMode == INDEX_MODE) + { + for (var counter = 0; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("transform","scale(1)"); + + if (counter == activeSlide) + { + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",1); + activeEffect = 0; + } + else + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + } + currentMode = SLIDE_MODE; + setSlideToState(activeSlide, STATE_START); + setProgressBarValue(activeSlide); + + if (progress_bar_visible) + { + showProgressBar(); + } + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to run an effect. + * + * @param dir direction in which to play the effect (1 = forwards, -1 = backwards) + */ +function effect(dir) +{ + var done = true; + + var suspendHandle = ROOT_NODE.suspendRedraw(200); + + for (var counter = 0; counter < effectArray.length; counter++) + { + if (effectArray[counter]["effect"] == "fade") + done &= fade(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "appear") + done &= appear(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "pop") + done &= pop(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "view") + done &= view(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); + + if (!done) + { + var currentTime = (new Date()).getTime(); + var timeDiff = 1; + + transCounter = currentTime - startTime; + + if (lastFrameTime != null) + { + timeDiff = timeStep - (currentTime - lastFrameTime); + + if (timeDiff <= 0) + timeDiff = 1; + } + + lastFrameTime = currentTime; + + window.setTimeout("effect(" + dir + ")", timeDiff); + } + else + { + window.location.hash = (activeSlide + 1) + '_' + activeEffect; + processingEffect = false; + } +} + +/** Function to display the index sheet. + * + * @param offsetNumber offset number + */ +function displayIndex(offsetNumber) +{ + var offsetX = 0; + var offsetY = 0; + + if (offsetNumber < 0) + offsetNumber = 0; + else if (offsetNumber >= slides.length) + offsetNumber = slides.length - 1; + + for (var counter = 0; counter < slides.length; counter++) + { + if ((counter < offsetNumber) || (counter > offsetNumber + INDEX_COLUMNS * INDEX_COLUMNS - 1)) + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + else + { + offsetX = ((counter - offsetNumber) % INDEX_COLUMNS) * WIDTH; + offsetY = Math.floor((counter - offsetNumber) / INDEX_COLUMNS) * HEIGHT; + + slides[counter]["element"].setAttribute("transform","scale("+1/INDEX_COLUMNS+") translate("+offsetX+","+offsetY+")"); + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",0.5); + } + + setSlideToState(counter, STATE_END); + } + + //do we need to save the current offset? + if (INDEX_OFFSET != offsetNumber) + INDEX_OFFSET = offsetNumber; +} + +/** Function to set the active slide in the slide view. + * + * @param nbr index of the active slide + */ +function slideSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0); + slides[activeSlide]["element"].style.display = "none"; + + activeSlide = parseInt(nbr); + + setSlideToState(activeSlide, STATE_START); + slides[activeSlide]["element"].style.display = "inherit"; + slides[activeSlide]["element"].setAttribute("opacity",1); + + activeEffect = 0; + setProgressBarValue(nbr); +} + +/** Function to set the active slide in the index view. + * + * @param nbr index of the active slide + */ +function indexSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0.5); + + activeSlide = parseInt(nbr); + window.location.hash = (activeSlide + 1) + '_0'; + + slides[activeSlide]["element"].setAttribute("opacity",1); +} + +/** Function to set the page and active slide in index view. + * + * @param nbr index of the active slide + * + * NOTE: To force a redraw, + * set INDEX_OFFSET to -1 before calling indexSetPageSlide(). + * + * This is necessary for zooming (otherwise the index might not + * get redrawn) and when switching to index mode. + * + * INDEX_OFFSET = -1 + * indexSetPageSlide(activeSlide); + */ +function indexSetPageSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + //calculate the offset + var offset = nbr - nbr % (INDEX_COLUMNS * INDEX_COLUMNS); + + if (offset < 0) + offset = 0; + + //if different from kept offset, then record and change the page + if (offset != INDEX_OFFSET) + { + INDEX_OFFSET = offset; + displayIndex(INDEX_OFFSET); + } + + //set the active slide + indexSetActiveSlide(nbr); +} + +/** Event handler for key press. + * + * @param e the event + */ +function keydown(e) +{ + if (!e) + e = window.event; + + code = e.keyCode || e.charCode; + + if (!processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code]) + return keyCodeDictionary[currentMode][code](); + else + document.onkeypress = keypress; +} +// Set event handler for key down. +document.onkeydown = keydown; + +/** Event handler for key press. + * + * @param e the event + */ +function keypress(e) +{ + document.onkeypress = null; + + if (!e) + e = window.event; + + str = String.fromCharCode(e.keyCode || e.charCode); + + if (!processingEffect && charCodeDictionary[currentMode] && charCodeDictionary[currentMode][str]) + return charCodeDictionary[currentMode][str](); +} + +/** Function to supply the default char code dictionary. + * + * @returns default char code dictionary + */ +function getDefaultCharCodeDictionary() +{ + var charCodeDict = new Object(); + + charCodeDict[SLIDE_MODE] = new Object(); + charCodeDict[INDEX_MODE] = new Object(); + charCodeDict[DRAWING_MODE] = new Object(); + + charCodeDict[SLIDE_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[SLIDE_MODE]["d"] = function () { return slideSwitchToDrawingMode(); }; + charCodeDict[SLIDE_MODE]["D"] = function () { return slideQueryDuration(); }; + charCodeDict[SLIDE_MODE]["n"] = function () { return slideAddSlide(activeSlide); }; + charCodeDict[SLIDE_MODE]["p"] = function () { return slideToggleProgressBarVisibility(); }; + charCodeDict[SLIDE_MODE]["t"] = function () { return slideResetTimer(); }; + charCodeDict[SLIDE_MODE]["e"] = function () { return slideUpdateExportLayer(); }; + + charCodeDict[DRAWING_MODE]["d"] = function () { return drawingSwitchToSlideMode(); }; + charCodeDict[DRAWING_MODE]["0"] = function () { return drawingResetPathWidth(); }; + charCodeDict[DRAWING_MODE]["1"] = function () { return drawingSetPathWidth(1.0); }; + charCodeDict[DRAWING_MODE]["3"] = function () { return drawingSetPathWidth(3.0); }; + charCodeDict[DRAWING_MODE]["5"] = function () { return drawingSetPathWidth(5.0); }; + charCodeDict[DRAWING_MODE]["7"] = function () { return drawingSetPathWidth(7.0); }; + charCodeDict[DRAWING_MODE]["9"] = function () { return drawingSetPathWidth(9.0); }; + charCodeDict[DRAWING_MODE]["b"] = function () { return drawingSetPathColour("blue"); }; + charCodeDict[DRAWING_MODE]["c"] = function () { return drawingSetPathColour("cyan"); }; + charCodeDict[DRAWING_MODE]["g"] = function () { return drawingSetPathColour("green"); }; + charCodeDict[DRAWING_MODE]["k"] = function () { return drawingSetPathColour("black"); }; + charCodeDict[DRAWING_MODE]["m"] = function () { return drawingSetPathColour("magenta"); }; + charCodeDict[DRAWING_MODE]["o"] = function () { return drawingSetPathColour("orange"); }; + charCodeDict[DRAWING_MODE]["r"] = function () { return drawingSetPathColour("red"); }; + charCodeDict[DRAWING_MODE]["w"] = function () { return drawingSetPathColour("white"); }; + charCodeDict[DRAWING_MODE]["y"] = function () { return drawingSetPathColour("yellow"); }; + charCodeDict[DRAWING_MODE]["z"] = function () { return drawingUndo(); }; + + charCodeDict[INDEX_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[INDEX_MODE]["-"] = function () { return indexDecreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["="] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["+"] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["0"] = function () { return indexResetNumberOfColumns(); }; + + return charCodeDict; +} + +/** Function to supply the default key code dictionary. + * + * @returns default key code dictionary + */ +function getDefaultKeyCodeDictionary() +{ + var keyCodeDict = new Object(); + + keyCodeDict[SLIDE_MODE] = new Object(); + keyCodeDict[INDEX_MODE] = new Object(); + keyCodeDict[DRAWING_MODE] = new Object(); + + keyCodeDict[SLIDE_MODE][LEFT_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][RIGHT_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][UP_KEY] = function() { return skipEffects(-1); }; + keyCodeDict[SLIDE_MODE][DOWN_KEY] = function() { return skipEffects(1); }; + keyCodeDict[SLIDE_MODE][PAGE_UP_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][HOME_KEY] = function() { return slideSetActiveSlide(0); }; + keyCodeDict[SLIDE_MODE][END_KEY] = function() { return slideSetActiveSlide(slides.length - 1); }; + keyCodeDict[SLIDE_MODE][SPACE_KEY] = function() { return dispatchEffects(1); }; + + keyCodeDict[INDEX_MODE][LEFT_KEY] = function() { return indexSetPageSlide(activeSlide - 1); }; + keyCodeDict[INDEX_MODE][RIGHT_KEY] = function() { return indexSetPageSlide(activeSlide + 1); }; + keyCodeDict[INDEX_MODE][UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][HOME_KEY] = function() { return indexSetPageSlide(0); }; + keyCodeDict[INDEX_MODE][END_KEY] = function() { return indexSetPageSlide(slides.length - 1); }; + keyCodeDict[INDEX_MODE][ENTER_KEY] = function() { return toggleSlideIndex(); }; + + keyCodeDict[DRAWING_MODE][ESCAPE_KEY] = function () { return drawingSwitchToSlideMode(); }; + + return keyCodeDict; +} + +/** Function to handle all mouse events. + * + * @param evnt event + * @param action type of event (e.g. mouse up, mouse wheel) + */ +function mouseHandlerDispatch(evnt, action) +{ + if (!evnt) + evnt = window.event; + + var retVal = true; + + if (!processingEffect && mouseHandlerDictionary[currentMode] && mouseHandlerDictionary[currentMode][action]) + { + var subRetVal = mouseHandlerDictionary[currentMode][action](evnt); + + if (subRetVal != null && subRetVal != undefined) + retVal = subRetVal; + } + + if (evnt.preventDefault && !retVal) + evnt.preventDefault(); + + evnt.returnValue = retVal; + + return retVal; +} + +// Set mouse event handler. +document.onmousedown = function(e) { return mouseHandlerDispatch(e, MOUSE_DOWN); }; +document.onmouseup = function(e) { return mouseHandlerDispatch(e, MOUSE_UP); }; +document.onmousemove = function(e) { return mouseHandlerDispatch(e, MOUSE_MOVE); }; + +// Moz +if (window.addEventListener) +{ + window.addEventListener('DOMMouseScroll', function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }, false); +} + +// Opera Safari OK - may not work in IE +window.onmousewheel = function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }; + +/** Function to supply the default mouse handler dictionary. + * + * @returns default mouse handler dictionary + */ +function getDefaultMouseHandlerDictionary() +{ + var mouseHandlerDict = new Object(); + + mouseHandlerDict[SLIDE_MODE] = new Object(); + mouseHandlerDict[INDEX_MODE] = new Object(); + mouseHandlerDict[DRAWING_MODE] = new Object(); + + mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN] = function(evnt) { return dispatchEffects(1); }; + mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL] = function(evnt) { return slideMousewheel(evnt); }; + + mouseHandlerDict[INDEX_MODE][MOUSE_DOWN] = function(evnt) { return toggleSlideIndex(); }; + + mouseHandlerDict[DRAWING_MODE][MOUSE_DOWN] = function(evnt) { return drawingMousedown(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_UP] = function(evnt) { return drawingMouseup(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_MOVE] = function(evnt) { return drawingMousemove(evnt); }; + + return mouseHandlerDict; +} + +/** Function to switch from slide mode to drawing mode. +*/ +function slideSwitchToDrawingMode() +{ + currentMode = DRAWING_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "crosshair"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to switch from drawing mode to slide mode. +*/ +function drawingSwitchToSlideMode() +{ + currentMode = SLIDE_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "auto"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to decrease the number of columns in index mode. +*/ +function indexDecreaseNumberOfColumns() +{ + if (INDEX_COLUMNS >= 3) + { + INDEX_COLUMNS -= 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to increase the number of columns in index mode. +*/ +function indexIncreaseNumberOfColumns() +{ + if (INDEX_COLUMNS < 7) + { + INDEX_COLUMNS += 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset the number of columns in index mode. +*/ +function indexResetNumberOfColumns() +{ + if (INDEX_COLUMNS != INDEX_COLUMNS_DEFAULT) + { + INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset path width in drawing mode. +*/ +function drawingResetPathWidth() +{ + path_width = path_width_default; + set_path_paint_width(); +} + +/** Function to set path width in drawing mode. + * + * @param width new path width + */ +function drawingSetPathWidth(width) +{ + path_width = width; + set_path_paint_width(); +} + +/** Function to set path colour in drawing mode. + * + * @param colour new path colour + */ +function drawingSetPathColour(colour) +{ + path_colour = colour; +} + +/** Function to query the duration of the presentation from the user in slide mode. +*/ +function slideQueryDuration() +{ + var new_duration = prompt("Length of presentation in minutes?", timer_duration); + + if ((new_duration != null) && (new_duration != '')) + { + timer_duration = new_duration; + } + + updateTimer(); +} + +/** Function to add new slide in slide mode. + * + * @param afterSlide after which slide to insert the new one + */ +function slideAddSlide(afterSlide) +{ + addSlide(afterSlide); + slideSetActiveSlide(afterSlide + 1); + updateTimer(); +} + +/** Function to toggle the visibility of the progress bar in slide mode. +*/ +function slideToggleProgressBarVisibility() +{ + if (progress_bar_visible) + { + progress_bar_visible = false; + hideProgressBar(); + } + else + { + progress_bar_visible = true; + showProgressBar(); + } +} + +/** Function to reset the timer in slide mode. +*/ +function slideResetTimer() +{ + timer_start = timer_elapsed; + updateTimer(); +} + +/** Convenience function to pad a string with zero in front up to a certain length. + */ +function padString(str, len) +{ + var outStr = str; + + while (outStr.length < len) + { + outStr = '0' + outStr; + } + + return outStr; +} + +/** Function to update the export layer. + */ +function slideUpdateExportLayer() +{ + // Suspend redraw since we are going to mess with the slides. + var suspendHandle = ROOT_NODE.suspendRedraw(2000); + + var tmpActiveSlide = activeSlide; + var tmpActiveEffect = activeEffect; + var exportedLayers = new Array(); + + for (var counterSlides = 0; counterSlides < slides.length; counterSlides++) + { + var exportNode; + + setSlideToState(counterSlides, STATE_START); + + var maxEffect = 0; + + if (slides[counterSlides].effects) + { + maxEffect = slides[counterSlides].effects.length; + } + + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString("0", maxEffect.toString().length)); + + exportedLayers.push(exportNode); + + if (slides[counterSlides]["effects"]) + { + for (var counter = 0; counter < slides[counterSlides]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[counterSlides]["effects"][counter].length; subCounter++) + { + var effect = slides[counterSlides]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + } + + var layerName = "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString((counter + 1).toString(), maxEffect.toString().length); + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", layerName); + exportNode.setAttribute("id", layerName); + + exportedLayers.push(exportNode); + } + } + } + + activeSlide = tmpActiveSlide; + activeEffect = tmpActiveEffect; + setSlideToState(activeSlide, activeEffect); + + // Copy image. + var newDoc = document.documentElement.cloneNode(true); + + // Delete viewbox form new imag and set width and height. + newDoc.removeAttribute('viewbox'); + newDoc.setAttribute('width', WIDTH); + newDoc.setAttribute('height', HEIGHT); + + // Delete all layers and script elements. + var nodesToBeRemoved = new Array(); + + for (var childCounter = 0; childCounter < newDoc.childNodes.length; childCounter++) + { + var child = newDoc.childNodes[childCounter]; + + if (child.nodeType == 1) + { + if ((child.nodeName.toUpperCase() == 'G') || (child.nodeName.toUpperCase() == 'SCRIPT')) + { + nodesToBeRemoved.push(child); + } + } + } + + for (var ndCounter = 0; ndCounter < nodesToBeRemoved.length; ndCounter++) + { + var nd = nodesToBeRemoved[ndCounter]; + + // Before removing the node, check whether it contains any definitions. + var defs = nd.getElementsByTagNameNS(NSS["svg"], "defs"); + + for (var defsCounter = 0; defsCounter < defs.length; defsCounter++) + { + if (defs[defsCounter].id) + { + newDoc.appendChild(defs[defsCounter].cloneNode(true)); + } + } + + // Remove node. + nd.parentNode.removeChild(nd); + } + + // Set current layer. + if (exportedLayers[0]) + { + var namedView; + + for (var nodeCounter = 0; nodeCounter < newDoc.childNodes.length; nodeCounter++) + { + if ((newDoc.childNodes[nodeCounter].nodeType == 1) && (newDoc.childNodes[nodeCounter].getAttribute('id') == 'base')) + { + namedView = newDoc.childNodes[nodeCounter]; + } + } + + if (namedView) + { + namedView.setAttributeNS(NSS['inkscape'], 'current-layer', exportedLayers[0].getAttributeNS(NSS['inkscape'], 'label')); + } + } + + // Add exported layers. + while (exportedLayers.length > 0) + { + var nd = exportedLayers.pop(); + + nd.setAttribute("opacity",1); + nd.style.display = "inherit"; + + newDoc.appendChild(nd); + } + + // Serialise the new document. + window.location = 'data:application/svg+xml;base64;charset=utf-8,' + window.btoa(unescape(encodeURIComponent((new XMLSerializer()).serializeToString(newDoc)))); + + // Unsuspend redraw. + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to undo last drawing operation. +*/ +function drawingUndo() +{ + mouse_presentation_path = null; + mouse_original_path = null; + + if (history_presentation_elements.length > 0) + { + var p = history_presentation_elements.pop(); + var parent = p.parentNode.removeChild(p); + + p = history_original_elements.pop(); + parent = p.parentNode.removeChild(p); + } +} + +/** Event handler for mouse down in drawing mode. + * + * @param e the event + */ +function drawingMousedown(e) +{ + var value = 0; + + if (e.button) + value = e.button; + else if (e.which) + value = e.which; + + if (value == 1) + { + history_counter++; + + var p = calcCoord(e); + + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + mouse_original_path = document.createElementNS(NSS["svg"], "path"); + mouse_original_path.setAttribute("stroke", path_colour); + mouse_original_path.setAttribute("stroke-width", path_paint_width); + mouse_original_path.setAttribute("fill", "none"); + mouse_original_path.setAttribute("id", "path " + Date()); + mouse_original_path.setAttribute("d", "M" + p.x + "," + p.y); + slides[activeSlide]["original_element"].appendChild(mouse_original_path); + history_original_elements.push(mouse_original_path); + + mouse_presentation_path = document.createElementNS(NSS["svg"], "path"); + mouse_presentation_path.setAttribute("stroke", path_colour); + mouse_presentation_path.setAttribute("stroke-width", path_paint_width); + mouse_presentation_path.setAttribute("fill", "none"); + mouse_presentation_path.setAttribute("id", "path " + Date() + " presentation copy"); + mouse_presentation_path.setAttribute("d", "M" + p.x + "," + p.y); + + if (slides[activeSlide]["viewGroup"]) + slides[activeSlide]["viewGroup"].appendChild(mouse_presentation_path); + else + slides[activeSlide]["element"].appendChild(mouse_presentation_path); + + history_presentation_elements.push(mouse_presentation_path); + + return false; + } + + return true; +} + +/** Event handler for mouse up in drawing mode. + * + * @param e the event + */ +function drawingMouseup(e) +{ + if(!e) + e = window.event; + + if (mouse_presentation_path != null) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_presentation_path = null; + mouse_original_path.setAttribute("d", d); + mouse_original_path = null; + + return false; + } + + return true; +} + +/** Event handler for mouse move in drawing mode. + * + * @param e the event + */ +function drawingMousemove(e) +{ + if(!e) + e = window.event; + + var dist = (mouse_last_x - e.clientX) * (mouse_last_x - e.clientX) + (mouse_last_y - e.clientY) * (mouse_last_y - e.clientY); + + if (mouse_presentation_path == null) + { + return true; + } + + if (dist >= mouse_min_dist_sqr) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_original_path.setAttribute("d", d); + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + } + + return false; +} + +/** Event handler for mouse wheel events in slide mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function slideMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + skipEffects(-1); + else if (delta < 0) + skipEffects(1); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Event handler for mouse wheel events in index mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function indexMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); + else if (delta < 0) + indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Function to set the path paint width. +*/ +function set_path_paint_width() +{ + var svgPoint1 = document.documentElement.createSVGPoint(); + var svgPoint2 = document.documentElement.createSVGPoint(); + + svgPoint1.x = 0.0; + svgPoint1.y = 0.0; + svgPoint2.x = 1.0; + svgPoint2.y = 0.0; + + var matrix = slides[activeSlide]["element"].getTransformToElement(ROOT_NODE); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getTransformToElement(ROOT_NODE); + + svgPoint1 = svgPoint1.matrixTransform(matrix); + svgPoint2 = svgPoint2.matrixTransform(matrix); + + path_paint_width = path_width / Math.sqrt((svgPoint2.x - svgPoint1.x) * (svgPoint2.x - svgPoint1.x) + (svgPoint2.y - svgPoint1.y) * (svgPoint2.y - svgPoint1.y)); +} + +/** The view effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect); for the view effect the options need to contain the old and the new matrix. + */ +function view(dir, element, time, options) +{ + var length = 250; + var fraction; + + if (!options["matrixInitial"]) + { + var tempString = slides[activeSlide]["viewGroup"].getAttribute("transform"); + + if (tempString) + options["matrixInitial"] = (new matrixSVG()).fromAttribute(tempString); + else + options["matrixInitial"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0); + } + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixNew"].toAttribute()); + + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixNew"], fraction).toAttribute()); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixOld"].toAttribute()); + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixOld"], fraction).toAttribute()); + } + } + + return false; +} + +/** The fade effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function fade(dir, element, time, options) +{ + var length = 250; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.style.display = "none"; + element.setAttribute("opacity", 0); + } + else if (fraction >= 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", fraction); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.style.display = "none"; + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1 - fraction); + } + } + return false; +} + +/** The appear effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function appear(dir, element, time, options) +{ + if (dir == 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity",1); + } + else if (dir == -1) + { + element.style.display = "none"; + element.setAttribute("opacity",0); + } + return true; +} + +/** The pop effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function pop(dir, element, time, options) +{ + var length = 500; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 0); + element.setAttribute("transform", "scale(0)"); + element.style.display = "none"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 1); + element.removeAttribute("transform"); + element.style.display = "inherit"; + return true; + } + else + { + element.style.display = "inherit"; + var opacityFraction = fraction * 3; + if (opacityFraction > 1) + opacityFraction = 1; + element.setAttribute("opacity", opacityFraction); + var offsetX = WIDTH * (1.0 - fraction) / 2.0; + var offsetY = HEIGHT * (1.0 - fraction) / 2.0; + element.setAttribute("transform", "translate(" + offsetX + "," + offsetY + ") scale(" + fraction + ")"); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 1); + element.setAttribute("transform", "scale(1)"); + element.style.display = "inherit"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.removeAttribute("transform"); + element.style.display = "none"; + return true; + } + else + { + element.setAttribute("opacity", 1 - fraction); + element.setAttribute("transform", "scale(" + 1 - fraction + ")"); + element.style.display = "inherit"; + } + } + return false; +} + +/** Function to set a slide either to the start or the end state. + * + * @param slide the slide to use + * @param state the state into which the slide should be set + */ +function setSlideToState(slide, state) +{ + slides[slide]["viewGroup"].setAttribute("transform", slides[slide].initialView); + + if (slides[slide]["effects"]) + { + if (state == STATE_END) + { + for (var counter = 0; counter < slides[slide]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + else if (state == STATE_START) + { + for (var counter = slides[slide]["effects"].length - 1; counter >= 0; counter--) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + } + } + } + else + { + setSlideToState(slide, STATE_START); + + for (var counter = 0; counter < slides[slide]["effects"].length && counter < state; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + } + + window.location.hash = (activeSlide + 1) + '_' + activeEffect; +} + +/** Convenience function to translate a attribute string into a dictionary. + * + * @param str the attribute string + * @return a dictionary + * @see dictToPropStr + */ +function propStrToDict(str) +{ + var list = str.split(";"); + var obj = new Object(); + + for (var counter = 0; counter < list.length; counter++) + { + var subStr = list[counter]; + var subList = subStr.split(":"); + if (subList.length == 2) + { + obj[subList[0]] = subList[1]; + } + } + + return obj; +} + +/** Convenience function to translate a dictionary into a string that can be used as an attribute. + * + * @param dict the dictionary to convert + * @return a string that can be used as an attribute + * @see propStrToDict + */ +function dictToPropStr(dict) +{ + var str = ""; + + for (var key in dict) + { + str += key + ":" + dict[key] + ";"; + } + + return str; +} + +/** Sub-function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @param replace dictionary of replaced ids + * @see suffixNodeIds + */ +function suffixNoneIds_sub(node, suffix, replace) +{ + if (node.nodeType == 1) + { + if (node.getAttribute("id")) + { + var id = node.getAttribute("id") + replace["#" + id] = id + suffix; + node.setAttribute("id", id + suffix); + } + + if ((node.nodeName == "use") && (node.getAttributeNS(NSS["xlink"], "href")) && (replace[node.getAttribute(NSS["xlink"], "href")])) + node.setAttribute(NSS["xlink"], "href", node.getAttribute(NSS["xlink"], "href") + suffix); + + if (node.childNodes) + { + for (var counter = 0; counter < node.childNodes.length; counter++) + suffixNoneIds_sub(node.childNodes[counter], suffix, replace); + } + } +} + +/** Function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @return the changed node + * @see suffixNodeIds_sub + */ +function suffixNodeIds(node, suffix) +{ + var replace = new Object(); + + suffixNoneIds_sub(node, suffix, replace); + + return node; +} + +/** Function to build a progress bar. + * + * @param parent node to attach the progress bar to + */ +function createProgressBar(parent_node) +{ + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "layer_progress_bar"); + g.setAttribute("style", "display: none;"); + + var rect_progress_bar = document.createElementNS(NSS["svg"], "rect"); + rect_progress_bar.setAttribute("style", "marker: none; fill: rgb(128, 128, 128); stroke: none;"); + rect_progress_bar.setAttribute("id", "rect_progress_bar"); + rect_progress_bar.setAttribute("x", 0); + rect_progress_bar.setAttribute("y", 0.99 * HEIGHT); + rect_progress_bar.setAttribute("width", 0); + rect_progress_bar.setAttribute("height", 0.01 * HEIGHT); + g.appendChild(rect_progress_bar); + + var circle_timer_indicator = document.createElementNS(NSS["svg"], "circle"); + circle_timer_indicator.setAttribute("style", "marker: none; fill: rgb(255, 0, 0); stroke: none;"); + circle_timer_indicator.setAttribute("id", "circle_timer_indicator"); + circle_timer_indicator.setAttribute("cx", 0.005 * HEIGHT); + circle_timer_indicator.setAttribute("cy", 0.995 * HEIGHT); + circle_timer_indicator.setAttribute("r", 0.005 * HEIGHT); + g.appendChild(circle_timer_indicator); + + parent_node.appendChild(g); +} + +/** Function to hide the progress bar. + * + */ +function hideProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: none;"); +} + +/** Function to show the progress bar. + * + */ +function showProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: inherit;"); +} + +/** Set progress bar value. + * + * @param value the current slide number + * + */ +function setProgressBarValue(value) +{ + var rect_progress_bar = document.getElementById("rect_progress_bar"); + + if (!rect_progress_bar) + { + return; + } + + if (value < 1) + { + // First slide, assumed to be the title of the presentation + var x = 0; + var w = 0.01 * HEIGHT; + } + else if (value >= slides.length - 1) + { + // Last slide, assumed to be the end of the presentation + var x = WIDTH - 0.01 * HEIGHT; + var w = 0.01 * HEIGHT; + } + else + { + value -= 1; + value /= (slides.length - 2); + + var x = WIDTH * value; + var w = WIDTH / (slides.length - 2); + } + + rect_progress_bar.setAttribute("x", x); + rect_progress_bar.setAttribute("width", w); +} + +/** Set time indicator. + * + * @param value the percentage of time elapse so far between 0.0 and 1.0 + * + */ +function setTimeIndicatorValue(value) +{ + var circle_timer_indicator = document.getElementById("circle_timer_indicator"); + + if (!circle_timer_indicator) + { + return; + } + + if (value < 0.0) + { + value = 0.0; + } + + if (value > 1.0) + { + value = 1.0; + } + + var cx = (WIDTH - 0.01 * HEIGHT) * value + 0.005 * HEIGHT; + circle_timer_indicator.setAttribute("cx", cx); +} + +/** Update timer. + * + */ +function updateTimer() +{ + timer_elapsed += 1; + setTimeIndicatorValue((timer_elapsed - timer_start) / (60 * timer_duration)); +} + +/** Convert screen coordinates to document coordinates. + * + * @param e event with screen coordinates + * + * @return coordinates in SVG file coordinate system + */ +function calcCoord(e) +{ + var svgPoint = document.documentElement.createSVGPoint(); + svgPoint.x = e.clientX + window.pageXOffset; + svgPoint.y = e.clientY + window.pageYOffset; + + var matrix = slides[activeSlide]["element"].getScreenCTM(); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getScreenCTM(); + + svgPoint = svgPoint.matrixTransform(matrix.inverse()); + return svgPoint; +} + +/** Add slide. + * + * @param after_slide after which slide the new slide should be inserted into the presentation + */ +function addSlide(after_slide) +{ + number_of_added_slides++; + + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date() + " presentation copy"); + g.setAttribute("style", "display: none;"); + + var new_slide = new Object(); + new_slide["element"] = g; + + // Set build in transition. + new_slide["transitionIn"] = new Object(); + var dict = defaultTransitionInDict; + new_slide["transitionIn"]["name"] = dict["name"]; + new_slide["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + new_slide["transitionOut"] = new Object(); + dict = defaultTransitionOutDict; + new_slide["transitionOut"]["name"] = dict["name"]; + new_slide["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + Date() + " presentation_copy"); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + g.appendChild(clonedNode); + } + + // Substitute auto texts. + substituteAutoTexts(g, "Whiteboard " + number_of_added_slides, "W" + number_of_added_slides, slides.length); + + g.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + (after_slide + 1) + ")) { indexSetActiveSlide(" + (after_slide + 1) + "); };"); + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (g.firstChild) + transformGroup.appendChild(g.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (g.getAttribute("transform")) + { + transformGroup.setAttribute("transform", g.getAttribute("transform")); + g.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + new_slide["viewGroup"] = g.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + Date()); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + new_slide["viewGroup"].insertBefore(rectNode, new_slide["viewGroup"].firstChild); + } + + // Set initial view even if there are no other views. + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + new_slide["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + new_slide.initialView = matrixOld.toAttribute(); + + // Insert slide + var node = slides[after_slide]["element"]; + var next_node = node.nextSibling; + var parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + g = document.createElementNS(NSS["svg"], "g"); + g.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + g.setAttributeNS(NSS["inkscape"], "label", "Whiteboard " + number_of_added_slides); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date()); + g.setAttribute("style", "display: none;"); + + new_slide["original_element"] = g; + + node = slides[after_slide]["original_element"]; + next_node = node.nextSibling; + parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + before_new_slide = slides.slice(0, after_slide + 1); + after_new_slide = slides.slice(after_slide + 1); + slides = before_new_slide.concat(new_slide, after_new_slide); + + //resetting the counter attributes on the slides that follow the new slide... + for (var counter = after_slide+2; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + } +} + +/** Convenience function to obtain a transformation matrix from a point matrix. + * + * @param mPoints Point matrix. + * @return A transformation matrix. + */ +function pointMatrixToTransformation(mPoints) +{ + mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1); + + return mPointsOld.mult(mPoints.inv()); +} + +/** Convenience function to obtain a matrix with three corners of a rectangle. + * + * @param rect an svg rectangle + * @return a matrixSVG containing three corners of the rectangle + */ +function rectToMatrix(rect) +{ + rectWidth = rect.getBBox().width; + rectHeight = rect.getBBox().height; + rectX = rect.getBBox().x; + rectY = rect.getBBox().y; + rectXcorr = 0; + rectYcorr = 0; + + scaleX = WIDTH / rectWidth; + scaleY = HEIGHT / rectHeight; + + if (scaleX > scaleY) + { + scaleX = scaleY; + rectXcorr -= (WIDTH / scaleX - rectWidth) / 2; + rectWidth = WIDTH / scaleX; + } + else + { + scaleY = scaleX; + rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2; + rectHeight = HEIGHT / scaleY; + } + + if (rect.transform.baseVal.numberOfItems < 1) + { + mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix); + } + + newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1); + newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0); + + return mRectTrans.mult(newBasePoints.add(newVectors)); +} + +/** Function to handle JessyInk elements. + * + * @param node Element node. + */ +function handleElement(node) +{ + if (node.getAttributeNS(NSS['jessyink'], 'element') == 'core.video') + { + var url; + var width; + var height; + var x; + var y; + var transform; + + var tspans = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "tspan"); + + for (var tspanCounter = 0; tspanCounter < tspans.length; tspanCounter++) + { + if (tspans[tspanCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "url") + { + url = tspans[tspanCounter].firstChild.nodeValue; + } + } + + var rects = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "rect"); + + for (var rectCounter = 0; rectCounter < rects.length; rectCounter++) + { + if (rects[rectCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "rect") + { + x = rects[rectCounter].getAttribute("x"); + y = rects[rectCounter].getAttribute("y"); + width = rects[rectCounter].getAttribute("width"); + height = rects[rectCounter].getAttribute("height"); + transform = rects[rectCounter].getAttribute("transform"); + } + } + + for (var childCounter = 0; childCounter < node.childNodes.length; childCounter++) + { + if (node.childNodes[childCounter].nodeType == 1) + { + if (node.childNodes[childCounter].style) + { + node.childNodes[childCounter].style.display = 'none'; + } + else + { + node.childNodes[childCounter].setAttribute("style", "display: none;"); + } + } + } + + var foreignNode = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"); + foreignNode.setAttribute("x", x); + foreignNode.setAttribute("y", y); + foreignNode.setAttribute("width", width); + foreignNode.setAttribute("height", height); + foreignNode.setAttribute("transform", transform); + + var videoNode = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); + videoNode.setAttribute("src", url); + + foreignNode.appendChild(videoNode); + node.appendChild(foreignNode); + } +} + +/** Class processing the location hash. + * + * @param str location hash + */ +function LocationHash(str) +{ + this.slideNumber = 0; + this.effectNumber = 0; + + str = str.substr(1, str.length - 1); + + var parts = str.split('_'); + + // Try to extract slide number. + if (parts.length >= 1) + { + try + { + var slideNumber = parseInt(parts[0]); + + if (!isNaN(slideNumber)) + { + this.slideNumber = slideNumber - 1; + } + } + catch (e) + { + } + } + + // Try to extract effect number. + if (parts.length >= 2) + { + try + { + var effectNumber = parseInt(parts[1]); + + if (!isNaN(effectNumber)) + { + this.effectNumber = effectNumber; + } + } + catch (e) + { + } + } +} + +/** Class representing an svg matrix. +*/ +function matrixSVG() +{ + this.e11 = 0; // a + this.e12 = 0; // c + this.e13 = 0; // e + this.e21 = 0; // b + this.e22 = 0; // d + this.e23 = 0; // f + this.e31 = 0; + this.e32 = 0; + this.e33 = 0; +} + +/** Constructor function. + * + * @param a element a (i.e. 1, 1) as described in the svg standard. + * @param b element b (i.e. 2, 1) as described in the svg standard. + * @param c element c (i.e. 1, 2) as described in the svg standard. + * @param d element d (i.e. 2, 2) as described in the svg standard. + * @param e element e (i.e. 1, 3) as described in the svg standard. + * @param f element f (i.e. 2, 3) as described in the svg standard. + */ +matrixSVG.prototype.fromSVGElements = function(a, b, c, d, e, f) +{ + this.e11 = a; + this.e12 = c; + this.e13 = e; + this.e21 = b; + this.e22 = d; + this.e23 = f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param matrix an svg matrix as described in the svg standard. + */ +matrixSVG.prototype.fromSVGMatrix = function(m) +{ + this.e11 = m.a; + this.e12 = m.c; + this.e13 = m.e; + this.e21 = m.b; + this.e22 = m.d; + this.e23 = m.f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param e11 element 1, 1 of the matrix. + * @param e12 element 1, 2 of the matrix. + * @param e13 element 1, 3 of the matrix. + * @param e21 element 2, 1 of the matrix. + * @param e22 element 2, 2 of the matrix. + * @param e23 element 2, 3 of the matrix. + * @param e31 element 3, 1 of the matrix. + * @param e32 element 3, 2 of the matrix. + * @param e33 element 3, 3 of the matrix. + */ +matrixSVG.prototype.fromElements = function(e11, e12, e13, e21, e22, e23, e31, e32, e33) +{ + this.e11 = e11; + this.e12 = e12; + this.e13 = e13; + this.e21 = e21; + this.e22 = e22; + this.e23 = e23; + this.e31 = e31; + this.e32 = e32; + this.e33 = e33; + + return this; +} + +/** Constructor function. + * + * @param attrString string value of the "transform" attribute (currently only "matrix" is accepted) + */ +matrixSVG.prototype.fromAttribute = function(attrString) +{ + str = attrString.substr(7, attrString.length - 8); + + str = str.trim(); + + strArray = str.split(","); + + // Opera does not use commas to separate the values of the matrix, only spaces. + if (strArray.length != 6) + strArray = str.split(" "); + + this.e11 = parseFloat(strArray[0]); + this.e21 = parseFloat(strArray[1]); + this.e31 = 0; + this.e12 = parseFloat(strArray[2]); + this.e22 = parseFloat(strArray[3]); + this.e32 = 0; + this.e13 = parseFloat(strArray[4]); + this.e23 = parseFloat(strArray[5]); + this.e33 = 1; + + return this; +} + +/** Output function + * + * @return a string that can be used as the "transform" attribute. + */ +matrixSVG.prototype.toAttribute = function() +{ + return "matrix(" + this.e11 + ", " + this.e21 + ", " + this.e12 + ", " + this.e22 + ", " + this.e13 + ", " + this.e23 + ")"; +} + +/** Matrix nversion. + * + * @return the inverse of the matrix + */ +matrixSVG.prototype.inv = function() +{ + out = new matrixSVG(); + + det = this.e11 * (this.e33 * this.e22 - this.e32 * this.e23) - this.e21 * (this.e33 * this.e12 - this.e32 * this.e13) + this.e31 * (this.e23 * this.e12 - this.e22 * this.e13); + + out.e11 = (this.e33 * this.e22 - this.e32 * this.e23) / det; + out.e12 = -(this.e33 * this.e12 - this.e32 * this.e13) / det; + out.e13 = (this.e23 * this.e12 - this.e22 * this.e13) / det; + out.e21 = -(this.e33 * this.e21 - this.e31 * this.e23) / det; + out.e22 = (this.e33 * this.e11 - this.e31 * this.e13) / det; + out.e23 = -(this.e23 * this.e11 - this.e21 * this.e13) / det; + out.e31 = (this.e32 * this.e21 - this.e31 * this.e22) / det; + out.e32 = -(this.e32 * this.e11 - this.e31 * this.e12) / det; + out.e33 = (this.e22 * this.e11 - this.e21 * this.e12) / det; + + return out; +} + +/** Matrix multiplication. + * + * @param op another svg matrix + * @return this * op + */ +matrixSVG.prototype.mult = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 * op.e11 + this.e12 * op.e21 + this.e13 * op.e31; + out.e12 = this.e11 * op.e12 + this.e12 * op.e22 + this.e13 * op.e32; + out.e13 = this.e11 * op.e13 + this.e12 * op.e23 + this.e13 * op.e33; + out.e21 = this.e21 * op.e11 + this.e22 * op.e21 + this.e23 * op.e31; + out.e22 = this.e21 * op.e12 + this.e22 * op.e22 + this.e23 * op.e32; + out.e23 = this.e21 * op.e13 + this.e22 * op.e23 + this.e23 * op.e33; + out.e31 = this.e31 * op.e11 + this.e32 * op.e21 + this.e33 * op.e31; + out.e32 = this.e31 * op.e12 + this.e32 * op.e22 + this.e33 * op.e32; + out.e33 = this.e31 * op.e13 + this.e32 * op.e23 + this.e33 * op.e33; + + return out; +} + +/** Matrix addition. + * + * @param op another svg matrix + * @return this + op + */ +matrixSVG.prototype.add = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 + op.e11; + out.e12 = this.e12 + op.e12; + out.e13 = this.e13 + op.e13; + out.e21 = this.e21 + op.e21; + out.e22 = this.e22 + op.e22; + out.e23 = this.e23 + op.e23; + out.e31 = this.e31 + op.e31; + out.e32 = this.e32 + op.e32; + out.e33 = this.e33 + op.e33; + + return out; +} + +/** Matrix mixing. + * + * @param op another svg matrix + * @parma contribOp contribution of the other matrix (0 <= contribOp <= 1) + * @return (1 - contribOp) * this + contribOp * op + */ +matrixSVG.prototype.mix = function(op, contribOp) +{ + contribThis = 1.0 - contribOp; + out = new matrixSVG(); + + out.e11 = contribThis * this.e11 + contribOp * op.e11; + out.e12 = contribThis * this.e12 + contribOp * op.e12; + out.e13 = contribThis * this.e13 + contribOp * op.e13; + out.e21 = contribThis * this.e21 + contribOp * op.e21; + out.e22 = contribThis * this.e22 + contribOp * op.e22; + out.e23 = contribThis * this.e23 + contribOp * op.e23; + out.e31 = contribThis * this.e31 + contribOp * op.e31; + out.e32 = contribThis * this.e32 + contribOp * op.e32; + out.e33 = contribThis * this.e33 + contribOp * op.e33; + + return out; +} + +/** Trimming function for strings. +*/ +String.prototype.trim = function() +{ + return this.replace(/^\s+|\s+$/g, ''); +} + +/** SVGElement.getTransformToElement polyfill */ +SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) { + return elem.getScreenCTM().inverse().multiply(this.getScreenCTM()); +}; diff --git a/share/extensions/jessyInk_core_mouseHandler_noclick.js b/share/extensions/jessyInk_core_mouseHandler_noclick.js new file mode 100644 index 0000000..4e66c51 --- /dev/null +++ b/share/extensions/jessyInk_core_mouseHandler_noclick.js @@ -0,0 +1,53 @@ +// Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Add event listener for initialisation. +document.addEventListener("DOMContentLoaded", jessyInk_core_mouseHandler_noclick_init, false); + +/** Initialisation function. + * + * This function looks for the objects of the appropriate sub-type and hands them to another function that will add the required methods. + */ +function jessyInk_core_mouseHandler_noclick_init() +{ + var elems = document.getElementsByTagNameNS("https://launchpad.net/jessyink", "mousehandler"); + + for (var counter = 0; counter < elems.length; counter++) + { + if (elems[counter].getAttributeNS("https://launchpad.net/jessyink", "subtype") == "jessyInk_core_mouseHandler_noclick") + jessyInk_core_mouseHandler_noclick(elems[counter]); + } +} + +/** Function to initialise an object. + * + * @param obj Object to be initialised. + */ +function jessyInk_core_mouseHandler_noclick(obj) +{ + /** Function supplying a custom mouse handler. + * + * @returns A dictionary containing the new mouse handler functions. + */ + obj.getMouseHandler = function () + { + var handlerDictio = new Object(); + + handlerDictio[SLIDE_MODE] = new Object(); + handlerDictio[SLIDE_MODE][MOUSE_DOWN] = null; + + return handlerDictio; + } +} + diff --git a/share/extensions/jessyInk_core_mouseHandler_zoomControl.js b/share/extensions/jessyInk_core_mouseHandler_zoomControl.js new file mode 100644 index 0000000..cd200c8 --- /dev/null +++ b/share/extensions/jessyInk_core_mouseHandler_zoomControl.js @@ -0,0 +1,434 @@ +// Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Add event listener for initialisation. +document.addEventListener("DOMContentLoaded", jessyInk_core_mouseHandler_zoomControl_init, false); + +/** Initialisation function. + * + * This function looks for the objects of the appropriate sub-type and hands them to another function that will add the required methods. + */ +function jessyInk_core_mouseHandler_zoomControl_init() +{ + var elems = document.getElementsByTagNameNS("https://launchpad.net/jessyink", "mousehandler"); + + for (var counter = 0; counter < elems.length; counter++) + { + if (elems[counter].getAttributeNS("https://launchpad.net/jessyink", "subtype") == "jessyInk_core_mouseHandler_zoomControl") + jessyInk_core_mouseHandler_zoomControl(elems[counter]); + } +} + +/** Function to initialise an object. + * + * @param obj Object to be initialised. + */ +function jessyInk_core_mouseHandler_zoomControl(obj) +{ + // Last dragging position. + obj.dragging_last; + // Flag to indicate whether dragging is active currently. + obj.dragging_active = false; + // Flag to indicate whether dragging is working currently. + obj.dragging_working = false; + // Flag to indicate whether the user clicked. + obj.click = false; + + /** Function supplying a custom mouse handler. + * + * @returns A dictionary containing the new mouse handler functions. + */ + obj.getMouseHandler = function () + { + var handlerDictio = new Object(); + + handlerDictio[SLIDE_MODE] = new Object(); + handlerDictio[SLIDE_MODE][MOUSE_DOWN] = obj.mousedown; + handlerDictio[SLIDE_MODE][MOUSE_MOVE] = obj.mousemove; + handlerDictio[SLIDE_MODE][MOUSE_UP] = obj.mouseup; + handlerDictio[SLIDE_MODE][MOUSE_WHEEL] = obj.mousewheel; + + return handlerDictio; + } + + /** Event handler for mouse clicks. + * + * @param e Event object. + */ + obj.mouseclick = function (e) + { + var elem = obj.getAdHocViewBbox(slides[activeSlide]["viewGroup"], obj.getCoords(e)); + + processingEffect = true; + + effectArray = new Array(); + + effectArray[0] = new Object(); + effectArray[0]["effect"] = "view"; + effectArray[0]["dir"] = 1; + effectArray[0]["element"] = slides[activeSlide]["viewGroup"]; + effectArray[0]["options"] = new Object(); + effectArray[0]["options"]["length"] = 200; + + if (elem == null) + effectArray[0]["options"]["matrixNew"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0); + else + effectArray[0]["options"]["matrixNew"] = obj.pointMatrixToTransformation(obj.rectToMatrix(elem)).mult((new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(elem.parentNode.getScreenCTM())).inv()); + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(1); + + return false; + } + + /** Function to search for the element the user clicked on. + * + * This function searches for the element with the highest z-order, which encloses the point the user clicked on + * and which view box fits entierly into the currently visible part of the slide. + * + * @param elem Element to start the search from. + * @param pnt Point where the user clicked. + * @returns The element the user clicked on or null, if no element could be found. + */ + obj.getAdHocViewBbox = function (elem, pnt) + { + var children = elem.childNodes; + + for (var counter = 0; counter < children.length; counter++) + { + if (children[counter].getBBox) + { + var childPointList = obj.projectRect(children[counter].getBBox(), children[counter].getScreenCTM()); + + var viewBbox = document.documentElement.createSVGRect(); + + viewBbox.x = 0.0; + viewBbox.y = 0.0; + viewBbox.width = WIDTH; + viewBbox.height = HEIGHT; + + var screenPointList = obj.projectRect(viewBbox, slides[activeSlide]["element"].getScreenCTM()); + + if (obj.pointsWithinRect([pnt], childPointList) && obj.pointsWithinRect(childPointList, screenPointList)) + return children[counter]; + + child = obj.getAdHocViewBbox(children[counter], pnt); + + if (child != null) + return child; + } + } + + return null; + } + + /** Function to project a rectangle using the projection matrix supplied. + * + * @param rect The rectangle to project. + * @param projectionMatrix The projection matrix. + * @returns A list of the four corners of the projected rectangle starting from the upper left corner and going counter-clockwise. + */ + obj.projectRect = function (rect, projectionMatrix) + { + var pntUL = document.documentElement.createSVGPoint(); + pntUL.x = rect.x; + pntUL.y = rect.y; + pntUL = pntUL.matrixTransform(projectionMatrix); + + var pntLL = document.documentElement.createSVGPoint(); + pntLL.x = rect.x; + pntLL.y = rect.y + rect.height; + pntLL = pntLL.matrixTransform(projectionMatrix); + + var pntUR = document.documentElement.createSVGPoint(); + pntUR.x = rect.x + rect.width; + pntUR.y = rect.y; + pntUR = pntUR.matrixTransform(projectionMatrix); + + var pntLR = document.documentElement.createSVGPoint(); + pntLR.x = rect.x + rect.width; + pntLR.y = rect.y + rect.height; + pntLR = pntLR.matrixTransform(projectionMatrix); + + return [pntUL, pntLL, pntUR, pntLR]; + } + + /** Function to determine whether all the points supplied in a list are within a rectangle. + * + * @param pnts List of points to check. + * @param pointList List of points representing the four corners of the rectangle. + * @return True, if all points are within the rectangle; false, otherwise. + */ + obj.pointsWithinRect = function (pnts, pointList) + { + var pntUL = pointList[0]; + var pntLL = pointList[1]; + var pntUR = pointList[2]; + + var matrixOrig = (new matrixSVG()).fromElements(pntUL.x, pntLL.x, pntUR.x, pntUL.y, pntLL.y, pntUR.y, 1, 1, 1); + var matrixProj = (new matrixSVG()).fromElements(0, 0, 1, 0, 1, 0, 1, 1, 1); + + var matrixProjection = matrixProj.mult(matrixOrig.inv()); + + for (var blockCounter = 0; blockCounter < Math.ceil(pnts.length / 3.0); blockCounter++) + { + var subPnts = new Array(); + + for (var pntCounter = 0; pntCounter < 3.0; pntCounter++) + { + if (blockCounter * 3.0 + pntCounter < pnts.length) + subPnts[pntCounter] = pnts[blockCounter * 3.0 + pntCounter]; + else + { + var tmpPnt = document.documentElement.createSVGPoint(); + + tmpPnt.x = 0.0; + tmpPnt.y = 0.0; + + subPnts[pntCounter] = tmpPnt; + } + } + + var matrixPnt = (new matrixSVG).fromElements(subPnts[0].x, subPnts[1].x, subPnts[2].x, subPnts[0].y, subPnts[1].y, subPnts[2].y, 1, 1, 1); + var matrixTrans = matrixProjection.mult(matrixPnt); + + for (var pntCounter = 0; pntCounter < 3.0; pntCounter++) + { + if (blockCounter * 3.0 + pntCounter < pnts.length) + { + if ((pntCounter == 0) && !((matrixTrans.e11 > 0.01) && (matrixTrans.e11 < 0.99) && (matrixTrans.e21 > 0.01) && (matrixTrans.e21 < 0.99))) + return false; + else if ((pntCounter == 1) && !((matrixTrans.e12 > 0.01) && (matrixTrans.e12 < 0.99) && (matrixTrans.e22 > 0.01) && (matrixTrans.e22 < 0.99))) + return false; + else if ((pntCounter == 2) && !((matrixTrans.e13 > 0.01) && (matrixTrans.e13 < 0.99) && (matrixTrans.e23 > 0.01) && (matrixTrans.e23 < 0.99))) + return false; + } + } + } + + return true; + } + + /** Event handler for mouse movements. + * + * @param e Event object. + */ + obj.mousemove = function (e) + { + obj.click = false; + + if (!obj.dragging_active || obj.dragging_working) + return false; + + obj.dragging_working = true; + + var p = obj.getCoords(e); + + if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1) + { + var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix); + } + + matrix.e13 += p.x - obj.dragging_last.x; + matrix.e23 += p.y - obj.dragging_last.y; + + slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute()); + + obj.dragging_last = p; + obj.dragging_working = false; + + return false; + } + + /** Event handler for mouse down. + * + * @param e Event object. + */ + obj.mousedown = function (e) + { + if (obj.dragging_active) + return false; + + var value = 0; + + if (e.button) + value = e.button; + else if (e.which) + value = e.which; + + if (value == 1) + { + obj.dragging_last = obj.getCoords(e); + obj.dragging_active = true; + obj.click = true; + } + + return false; + } + + /** Event handler for mouse up. + * + * @param e Event object. + */ + obj.mouseup = function (e) + { + obj.dragging_active = false; + + if (obj.click) + return obj.mouseclick(e); + else + return false; + } + + /** Function to get the coordinates of a point corrected for the offset of the viewport. + * + * @param e Point. + * @returns Coordinates of the point corrected for the offset of the viewport. + */ + obj.getCoords = function (e) + { + var svgPoint = document.documentElement.createSVGPoint(); + svgPoint.x = e.clientX + window.pageXOffset; + svgPoint.y = e.clientY + window.pageYOffset; + + return svgPoint; + } + + /** Event handler for scrolling. + * + * @param e Event object. + */ + obj.mousewheel = function(e) + { + var p = obj.projectCoords(obj.getCoords(e)); + + if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1) + { + var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix); + } + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + var widthOld = p.x * matrix.e11 + p.y * matrix.e12; + var heightOld = p.x * matrix.e21 + p.y * matrix.e22; + + matrix.e11 *= (1.0 - delta / 20.0); + matrix.e12 *= (1.0 - delta / 20.0); + matrix.e21 *= (1.0 - delta / 20.0); + matrix.e22 *= (1.0 - delta / 20.0); + + var widthNew = p.x * matrix.e11 + p.y * matrix.e12; + var heightNew = p.x * matrix.e21 + p.y * matrix.e22; + + matrix.e13 += (widthOld - widthNew); + matrix.e23 += (heightOld - heightNew); + + slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute()); + + return false; + } + + /** Function to project a point to screen coordinates. + * + * @param Point. + * @returns The point projected to screen coordinates. + */ + obj.projectCoords = function(pnt) + { + var matrix = slides[activeSlide]["element"].getScreenCTM(); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getScreenCTM(); + + pnt = pnt.matrixTransform(matrix.inverse()); + return pnt; + } + + /** Function to convert a rectangle into a point matrix. + * + * The function figures out a rectangle that encloses the rectangle given and has the same width/height ratio as the viewport of the presentation. + * + * @param rect Rectangle. + * @return The upper left, upper right and lower right corner of the rectangle in a point matrix. + */ + obj.rectToMatrix = function(rect) + { + rectWidth = rect.getBBox().width; + rectHeight = rect.getBBox().height; + rectX = rect.getBBox().x; + rectY = rect.getBBox().y; + rectXcorr = 0; + rectYcorr = 0; + + scaleX = WIDTH / rectWidth; + scaleY = HEIGHT / rectHeight; + + if (scaleX > scaleY) + { + scaleX = scaleY; + rectXcorr -= (WIDTH / scaleX - rectWidth) / 2; + rectWidth = WIDTH / scaleX; + } + else + { + scaleY = scaleX; + rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2; + rectHeight = HEIGHT / scaleY; + } + + if (rect.transform.baseVal.numberOfItems < 1) + { + mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix); + } + + newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1); + newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0); + + return mRectTrans.mult(newBasePoints.add(newVectors)); + } + + /** Function to return a transformation matrix from a point matrix. + * + * @param mPoints The point matrix. + * @returns The transformation matrix. + */ + obj.pointMatrixToTransformation = function(mPoints) + { + mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1); + + return mPointsOld.mult(mPoints.inv()); + } +} + diff --git a/share/extensions/jessyink_autotexts.inx b/share/extensions/jessyink_autotexts.inx new file mode 100644 index 0000000..de87a33 --- /dev/null +++ b/share/extensions/jessyink_autotexts.inx @@ -0,0 +1,28 @@ + + + Auto-texts + org.inkscape.jessyink.auto_texts + + + + + + + + + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_autotexts.py b/share/extensions/jessyink_autotexts.py new file mode 100755 index 0000000..3509c86 --- /dev/null +++ b/share/extensions/jessyink_autotexts.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Automatic text for jessyInk""" + + +import inkex +from jessyink_install import JessyInkMixin, _ + + +class AutoTexts(JessyInkMixin, inkex.EffectExtension): + """Add AutoText to jessyInk""" + + def add_arguments(self, pars): + pars.add_argument("--tab", dest="what") + pars.add_argument("--autoText", default="none") + + def effect(self): + self.is_installed() + + if not self.svg.selection: + inkex.errormsg(_("To assign an effect, please select an object.\n\n")) + + for node in self.svg.selection.get(inkex.Tspan): + if self.options.autoText == "slideTitle": + node.set("jessyink:autoText", "slideTitle") + elif self.options.autoText == "slideNumber": + node.set("jessyink:autoText", "slideNumber") + elif self.options.autoText == "numberOfSlides": + node.set("jessyink:autoText", "numberOfSlides") + elif node.get("jessyink:autoText"): + node.set("jessyink:autoText", None) + + +if __name__ == "__main__": + AutoTexts().run() diff --git a/share/extensions/jessyink_effects.inx b/share/extensions/jessyink_effects.inx new file mode 100644 index 0000000..13e8cb2 --- /dev/null +++ b/share/extensions/jessyink_effects.inx @@ -0,0 +1,40 @@ + + + Effects + org.inkscape.jessyink.jessyink_effects + + + + 1 + 0.8 + + + + + + + + 1 + 0.8 + + + + + + + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_effects.py b/share/extensions/jessyink_effects.py new file mode 100755 index 0000000..1845339 --- /dev/null +++ b/share/extensions/jessyink_effects.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# 2020 Martin Owens +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Jessyink effect extension.""" + +import inkex + +from jessyink_install import JessyInkMixin, _ + + +class JessyinkEffects(JessyInkMixin, inkex.EffectExtension): + """Add ad effect to jessy ink selected items""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--effectInOrder", type=int, default=1) + pars.add_argument("--effectInDuration", type=float, default=0.8) + pars.add_argument("--effectIn", default="none") + pars.add_argument("--effectOutOrder", type=int, default=1) + pars.add_argument("--effectOutDuration", type=float, default=0.8) + pars.add_argument("--effectOut", default="none") + + def effect(self): + self.is_installed() + if not self.svg.selection: + raise inkex.AbortExtension( + _( + "No object selected. Please select the object you want to " + "assign an effect to and then press apply.\n" + ) + ) + + for elem in self.svg.selection.values(): + self._process(elem, "effectIn") + self._process(elem, "effectOut") + + def _process(self, elem, name): + effect = getattr(self.options, name) + order = getattr(self.options, name + "Order") + duration = int(getattr(self.options, name + "Duration") * 1000) + + if effect in ("appear", "fade", "pop"): + elem.set( + "jessyink:" + name, + inkex.Style(name=effect, order=order, length=duration), + ) + # Remove possible view argument. + elem.pop("jessyink:view", None) + else: + elem.pop("jessyink:" + name, None) + + +if __name__ == "__main__": + JessyinkEffects().run() diff --git a/share/extensions/jessyink_export.inx b/share/extensions/jessyink_export.inx new file mode 100644 index 0000000..a29f0a2 --- /dev/null +++ b/share/extensions/jessyink_export.inx @@ -0,0 +1,29 @@ + + + JessyInk zipped pdf or png output + jessyink.export + org.inkscape.output.svg.inkscape + + + + + + + 92 + + + + + + + .zip + application/x-zip + JessyInk zipped pdf or png output (*.zip) + Creates a zip file containing pdfs or pngs of all slides of a JessyInk presentation. + true + + + diff --git a/share/extensions/jessyink_export.py b/share/extensions/jessyink_export.py new file mode 100755 index 0000000..171c46f --- /dev/null +++ b/share/extensions/jessyink_export.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +""" +JessyInk Export to zipfile multiple layers. +""" + +import zipfile + +import inkex +from inkex.base import TempDirMixin +from inkex.command import take_snapshot + +from jessyink_install import JessyInkMixin + + +class Export(JessyInkMixin, TempDirMixin, inkex.OutputExtension): + """ + JessyInkExport Output Extension saves to a zipfile each of the layers. + """ + + dir_prefix = "jessyInk-" + + def add_arguments(self, pars): + pars.add_argument("--tab", type=str, dest="what") + pars.add_argument("--type", type=str, dest="type", default="pdf") + pars.add_argument("--resolution", type=int, default=92) + + def save(self, stream): + self.is_installed() + + with zipfile.ZipFile(stream, "w", compression=zipfile.ZIP_STORED) as output: + + # Find layers. + layers = self.svg.xpath("//svg:g[@inkscape:groupmode='layer']") + + if len(layers) < 1: + inkex.errormsg("No layers found.") + return + + for node in layers: + # Make all layers invisible + node.style["display"] = "none" + + for node in layers: + # Show only one layer at a time. + node.style.update("display:inherit;opacity:1") + + name = node.get("inkscape:label") + newname = "{}.{}".format(name, self.options.type) + filename = take_snapshot( + self.document, + dirname=self.tempdir, + name=name, + ext=self.options.type, + dpi=self.options.resolution, + ) + output.write(filename, newname) + + node.style["display"] = "none" + + +if __name__ == "__main__": + Export().run() diff --git a/share/extensions/jessyink_install.inx b/share/extensions/jessyink_install.inx new file mode 100644 index 0000000..d44cd88 --- /dev/null +++ b/share/extensions/jessyink_install.inx @@ -0,0 +1,21 @@ + + + Install/update + jessyink.install + jessyInk.js + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_install.py b/share/extensions/jessyink_install.py new file mode 100755 index 0000000..dee36d3 --- /dev/null +++ b/share/extensions/jessyink_install.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Install jessyInk scripts""" + +import inkex +from inkex import Script + +from inkex.localization import inkex_gettext as _ + +inkex.NSS["jessyink"] = "https://launchpad.net/jessyink" + + +class JessyInkMixin(object): + """Common jessyInk items""" + + def is_installed(self): + """Check jessyInk is installed correctly""" + scripts = self.svg.getElement("//svg:script[@jessyink:version='1.5.5']") + if scripts is None: + raise inkex.AbortExtension( + _( + "The JessyInk script is not installed in this SVG file or has a " + "different version than the JessyInk extensions. Please select " + '"install/update..." from the "JessyInk" sub-menu of the "Extensions" ' + "menu to install or update the JessyInk script.\n\n" + ) + ) + + def attr_remove(self, prop, is_removed=True): + """Remove a property if it exists in the svg""" + if is_removed: + for node in self.svg.xpath(f"//*[@jessyink:{prop}]"): + node.set(f"jessyink:{prop}", None) + for node in self.svg.xpath(f"//*[@jessyInk_{prop}]"): + node.set(f"jessyInk_{prop}", None) + + def attr_update(self, name): + """Update a single attr""" + for node in self.svg.xpath(f"//*[@jessyInk_{name}]"): + node.set(f"jessyink:{name}", node.get(f"jessyInk_{name}")) + node.set(f"jessyInk_{name}", None) + for node in self.svg.xpath(f"//*[@jessyink:{name}]"): + node.set(f"jessyink:{name}", node.get(f"jessyink:{name}").replace("=", ":")) + + @staticmethod + def prop_str_to_list(string): + """Script string to list of instructions""" + return [prop.strip() for prop in string.split(";") if prop] + + @staticmethod + def list_to_prop_str(lst): + """List of instructions to script string""" + return "; ".join(lst) + ";" + + +class Install(JessyInkMixin, inkex.EffectExtension): + """Install jessyInk extension into an SVG""" + + def add_arguments(self, pars): + pars.add_argument("--tab", type=str, dest="what") + + def effect(self): + # Find and delete old script node + for node in self.svg.xpath("//svg:script[@id='JessyInk']"): + node.getparent().remove(node) + + # Create new script node + script_elem = Script() + with open(self.get_resource("jessyInk.js")) as fhl: + script_elem.text = fhl.read() + script_elem.set("id", "JessyInk") + script_elem.set("jessyink:version", "1.5.5") + self.svg.append(script_elem) + + # Remove "jessyInkInit()" in the "onload" attribute, if present. + prop_list = [prop.strip() for prop in self.svg.get("onload", "").split(";")] + if "jessyInkInit()" in prop_list: + prop_list.remove("jessyInkInit()") + self.svg.set("onload", "; ".join(prop_list) or None) + + # Update jessyInk attributes to new formats + for attr in ( + "effectIn", + "effectOut", + "masterSlide", + "transitionIn", + "transitionOut", + "autoText", + ): + self.attr_update(attr) + + +# Create effect instance +if __name__ == "__main__": + Install().run() diff --git a/share/extensions/jessyink_key_bindings.inx b/share/extensions/jessyink_key_bindings.inx new file mode 100644 index 0000000..22f27e2 --- /dev/null +++ b/share/extensions/jessyink_key_bindings.inx @@ -0,0 +1,70 @@ + + + Key bindings + org.inkscape.jessyink.key_bindings + + + LEFT, PAGE_UP + RIGHT, PAGE_DOWN, SPACE + UP + DOWN + HOME + END + i + d + D + n + p + t + e + + + ESCAPE, d + 0 + 1 + 3 + 5 + 7 + 9 + z + + + b + c + g + k + m + o + r + w + y + + + LEFT + RIGHT + UP + DOWN + PAGE_UP + PAGE_DOWN + HOME + END + ENTER, i + - + +, = + 0 + + + + + + + g + + + + + + + diff --git a/share/extensions/jessyink_key_bindings.py b/share/extensions/jessyink_key_bindings.py new file mode 100755 index 0000000..2d28a95 --- /dev/null +++ b/share/extensions/jessyink_key_bindings.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Effect to add key bindings to jessyInk slide show""" + +import inkex +from inkex import Group, Script +from jessyink_install import JessyInkMixin + +KEY_CODES = ( + "LEFT", + "RIGHT", + "DOWN", + "UP", + "HOME", + "END", + "ENTER", + "SPACE", + "PAGE_UP", + "PAGE_DOWN", + "ESCAPE", +) + + +class KeyBindings(JessyInkMixin, inkex.EffectExtension): + """Add key bindings to slide show""" + + modes = ("slide", "index", "drawing") + + def set_options(self, namespace, opt_str, value): + """Sort through all the options and combine them""" + slot, action = opt_str.split("_", 1) + keycodes = getattr(namespace, f"{slot}KeyCodes", {}) + charcodes = getattr(namespace, f"{slot}CharCodes", {}) + if value: + for val in value.split(","): + val = val.strip() + if val in KEY_CODES: + keycodes[val + "_KEY"] = self.actions[slot][action] + elif len(val) == 1: + charcodes[val] = self.actions[slot][action] + setattr(namespace, f"{slot}KeyCodes", keycodes) + setattr(namespace, f"{slot}CharCodes", charcodes) + + actions = { + "slide": { + "export": "slideUpdateExportLayer();", + "addSlide": "slideAddSlide(activeSlide);", + "resetTimer": "slideResetTimer();", + "setDuration": "slideQueryDuration();", + "backWithEffects": "dispatchEffects(-1);", + "nextWithEffects": "dispatchEffects(1);", + "backWithoutEffects": "skipEffects(-1);", + "nextWithoutEffects": "skipEffects(1);", + "switchToIndexMode": "toggleSlideIndex();", + "switchToDrawingMode": "slideSwitchToDrawingMode();", + "toggleProgressBar": "slideToggleProgressBarVisibility();", + "firstSlide": "slideSetActiveSlide(0);", + "lastSlide": "slideSetActiveSlide(slides.length - 1);", + }, + "drawing": { + "undo": "drawingUndo();", + "switchToSlideMode": "drawingSwitchToSlideMode();", + "pathWidthDefault": "drawingResetPathWidth();", + "pathWidth1": "drawingSetPathWidth(1.0);", + "pathWidth3": "drawingSetPathWidth(3.0);", + "pathWidth5": "drawingSetPathWidth(5.0);", + "pathWidth7": "drawingSetPathWidth(7.0);", + "pathWidth9": "drawingSetPathWidth(9.0);", + "pathColourBlue": 'drawingSetPathColour("blue");', + "pathColourCyan": 'drawingSetPathColour("cyan");', + "pathColourGreen": 'drawingSetPathColour("green");', + "pathColourBlack": 'drawingSetPathColour("black");', + "pathColourMagenta": 'drawingSetPathColour("magenta");', + "pathColourOrange": 'drawingSetPathColour("orange");', + "pathColourRed": 'drawingSetPathColour("red");', + "pathColourWhite": 'drawingSetPathColour("white");', + "pathColourYellow": 'drawingSetPathColour("yellow");', + }, + "index": { + "selectSlideToLeft": "indexSetPageSlide(activeSlide - 1);", + "selectSlideToRight": "indexSetPageSlide(activeSlide + 1);", + "selectSlideAbove": "indexSetPageSlide(activeSlide - INDEX_COLUMNS);", + "selectSlideBelow": "indexSetPageSlide(activeSlide + INDEX_COLUMNS);", + "previousPage": "indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS);", + "nextPage": "indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS);", + "firstSlide": "indexSetPageSlide(0);", + "lastSlide": "indexSetPageSlide(slides.length - 1);", + "switchToSlideMode": "toggleSlideIndex();", + "decreaseNumberOfColumns": "indexDecreaseNumberOfColumns();", + "increaseNumberOfColumns": "indexIncreaseNumberOfColumns();", + "setNumberOfColumnsToDefault": "indexResetNumberOfColumns();", + }, + } + + def add_arguments(self, pars): + pars.add_argument("--tab") + for slot, actions in self.actions.items(): + for action in actions: + pars.add_argument(f"--{slot}_{action}") + + def effect(self): + self.is_installed() + + for name in list(self.options.__dict__): + if "_" in name: + self.set_options(self.options, name, self.options.__dict__.pop(name)) + + # Remove old master slide property + for node in self.svg.xpath( + "//svg:g[@jessyink:customKeyBindings='customKeyBindings']" + ): + node.delete() + + # Set custom key bindings. + node_text = """function getCustomKeyBindingsSub() +{ + var keyDict = new Object(); + keyDict[SLIDE_MODE] = new Object(); + keyDict[INDEX_MODE] = new Object(); + keyDict[DRAWING_MODE] = new Object(); +""" + + for key, value in self.options.slideKeyCodes.items(): + node_text += f" keyDict[SLIDE_MODE][{key}] = function() {{ {value} }};\n" + + for key, value in self.options.drawingKeyCodes.items(): + node_text += ( + f" keyDict[DRAWING_MODE][{key}] = function() {{ {value} }};\n" + ) + + for key, value in self.options.indexKeyCodes.items(): + node_text += f" keyDict[INDEX_MODE][{key}] = function() {{ {value} }};\n" + + # Set custom char bindings. + node_text += """ return keyDict; +} + +function getCustomCharBindingsSub() +{ + var charDict = new Object(); + charDict[SLIDE_MODE] = new Object(); + charDict[INDEX_MODE] = new Object(); + charDict[DRAWING_MODE] = new Object(); +""" + + for key, value in self.options.slideCharCodes.items(): + node_text += ( + f' charDict[SLIDE_MODE]["{key}"] = function() {{ {value} }};\n' + ) + + for key, value in self.options.drawingCharCodes.items(): + node_text += ( + f' charDict[DRAWING_MODE]["{key}"] = function() {{ {value} }};\n' + ) + + for key, value in self.options.indexCharCodes.items(): + node_text += ( + f' charDict[INDEX_MODE]["{key}"] = function() {{ {value} }};\n' + ) + + node_text += " return charDict;" + "\n" + node_text += "}" + "\n" + + # Create new script node + group = self.svg.add(Group()) + script = group.add(Script()) + script.text = node_text + group.set("jessyink:customKeyBindings", "customKeyBindings") + group.set( + "onload", + "this.getCustomCharBindings = function() { " + "return getCustomCharBindingsSub(); }; " + "this.getCustomKeyBindings = function() { return getCustomKeyBindingsSub(); };", + ) + + +if __name__ == "__main__": + KeyBindings().run() diff --git a/share/extensions/jessyink_master_slide.inx b/share/extensions/jessyink_master_slide.inx new file mode 100644 index 0000000..8ca3074 --- /dev/null +++ b/share/extensions/jessyink_master_slide.inx @@ -0,0 +1,24 @@ + + + Master slide + org.inkscape.jessyink.master_slide + + + + + + + + + + + g + + + + + + + diff --git a/share/extensions/jessyink_master_slide.py b/share/extensions/jessyink_master_slide.py new file mode 100755 index 0000000..fe5c533 --- /dev/null +++ b/share/extensions/jessyink_master_slide.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +""" +Jessyink Set Master Slide +""" + +import inkex + +from jessyink_install import JessyInkMixin, _ + + +class MasterSlide(JessyInkMixin, inkex.EffectExtension): + """Effect Extension for master slide""" + + def add_arguments(self, pars): + self.arg_parser.add_argument("--tab") + self.arg_parser.add_argument("--layerName", default="") + + def effect(self): + self.is_installed() + # Remove old master slide property + for node in self.svg.xpath("//*[@jessyink:masterSlide='masterSlide']"): + node.set("jessyink:masterSlide", None) + + # Set new master slide. + if self.options.layerName != "": + nodes = self.svg.xpath( + f"//*[@inkscape:groupmode='layer' " + f"and @inkscape:label='{self.options.layerName}']" + ) + if not nodes: + inkex.errormsg( + _("Layer not found. Removed current master slide selection.\n") + ) + elif len(nodes) > 1: + inkex.errormsg( + _( + "More than one layer with this name found. " + "Removed current master slide selection.\n" + ) + ) + else: + nodes[0].set("jessyink:masterSlide", "masterSlide") + + +if __name__ == "__main__": + MasterSlide().run() diff --git a/share/extensions/jessyink_mouse_handler.inx b/share/extensions/jessyink_mouse_handler.inx new file mode 100644 index 0000000..c1b0af4 --- /dev/null +++ b/share/extensions/jessyink_mouse_handler.inx @@ -0,0 +1,27 @@ + + + Mouse handler + org.inkscape.jessyink.add_mouse_handler + + + + + + + + + + + + + + g + + + + + + + diff --git a/share/extensions/jessyink_mouse_handler.py b/share/extensions/jessyink_mouse_handler.py new file mode 100755 index 0000000..d600d8f --- /dev/null +++ b/share/extensions/jessyink_mouse_handler.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Add mouse handler for jessyInk""" + +import inkex +from inkex.elements import BaseElement, Script +from jessyink_install import JessyInkMixin + + +class MouseHandler(BaseElement): + """jessyInk mouse handler""" + + tag_name = "jessyink:mousehandler" + + +class AddMouseHandler(JessyInkMixin, inkex.EffectExtension): + """Add mouse handler""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--mouseSetting", default="default") + + def effect(self): + self.is_installed() + # Remove old mouse handler + for node in self.svg.xpath("//jessyink:mousehandler"): + node.delete() + + # Create new script node. + script = Script() + group = MouseHandler() + + if self.options.mouseSetting == "noclick": + name = "noclick" + elif self.options.mouseSetting == "draggingZoom": + name = "zoomControl" + elif self.options.mouseSetting == "default": + # Default is to remove script and continue + return + + with open(self.get_resource(f"jessyInk_core_mouseHandler_{name}.js")) as fhl: + script.text = fhl.read() + group.set("jessyink:subtype", f"jessyInk_core_mouseHandler_{name}") + + group.append(script) + self.svg.append(group) + + +if __name__ == "__main__": + AddMouseHandler().run() diff --git a/share/extensions/jessyink_summary.inx b/share/extensions/jessyink_summary.inx new file mode 100644 index 0000000..3a6b688 --- /dev/null +++ b/share/extensions/jessyink_summary.inx @@ -0,0 +1,20 @@ + + + Summary + jessyink.summary + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_summary.py b/share/extensions/jessyink_summary.py new file mode 100755 index 0000000..698abbf --- /dev/null +++ b/share/extensions/jessyink_summary.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Effect to print out jessyInk summary""" + +from collections import defaultdict +import inkex + +from jessyink_install import JessyInkMixin, _ + + +class Summary(JessyInkMixin, inkex.EffectExtension): + """Print of jessyInk summary""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + + def effect(self): + self.is_installed() + + # Find the script node, if present + for node in self.svg.xpath("//svg:script[@id='JessyInk']"): + version = node.get("jessyink:version") + if version: + self.msg(_("JessyInk script version {} installed.".format(version))) + else: + self.msg(_("JessyInk script installed.")) + + slides = [] + master_slide = None + + for node in self.svg.descendants().get(inkex.Layer): + if node.get("jessyink:master_slide"): + master_slide = node + else: + slides.append(node) + + if master_slide is not None: + self.msg(_("\nMaster slide:")) + self.describe_node( + master_slide, + "\t", + ["", len(slides), ""], + ) + + for i, slide in enumerate(slides): + self.msg(_("\nSlide {0!s}:").format(i + 1)) + self.describe_node(slide, "\t", [i + 1, len(slides), slide.label]) + + def describe_node(self, node, prefix, dat): + """Standard print out formatter""" + + self.msg(_(f"{prefix}Layer name: {node.label}")) + self.describe_transition(node, prefix, "In") + self.describe_transition(node, prefix, "Out") + self.describe_autotext(node, prefix, dat) + self.describe_effects(node, prefix) + + def describe_transition(self, node, prefix, transition): + """Display information about transitions.""" + trans = inkex.Style(node.get(f"jessyink:transition{transition}")) + if trans: + name = trans["name"] + if name != "appear" and "length" in trans: + length = int(trans["length"] / 1000.0) + self.msg( + _( + "{0}Transition {1}: {2} ({3!s} s)".format( + prefix, transition, name, length + ) + ) + ) + else: + self.msg(_(f"{prefix}Transition {transition}: {name}")) + + def describe_autotext(self, node, prefix, dat): + """Display information about auto-texts.""" + auto_texts = {"slide_num": dat[0], "num": dat[1], "title": dat[2]} + for x, child in enumerate(node.xpath(".//*[@jessyink:autoText]")): + if not x: + self.msg(_("\n{0}Auto-texts:").format(prefix)) + + pid = child.getparent().get("id") + val = auto_texts[child.get("jessyink:autoText")] + self.msg( + _( + _('{0}\t"{1}" (object id "{2}") will be replaced by "{3}".').format( + prefix, child.text, pid, val + ) + ) + ) + + def describe_effects(self, node, prefix): + """Display information about effects.""" + effects = sorted(self.collect_effects(node), key=lambda val: val[0]) + for x, (enum, effect) in enumerate(effects): + ret = "" + + order = effect[0]["order"] + if not x: + ret += _("\n{0}Initial effect (order number {1}):").format( + prefix, order + ) + else: + ret += _("\n{0}Effect {1} (order number {2}):").format( + prefix, enum, order + ) + + for item in effect: + eid = item["id"] + if item["type"] == "view": + ret += _('{0}\tView will be set according to object "{1}"').format( + prefix, eid + ) + else: + ret += _('{0}\tObject "{1}"').format(prefix, eid) + + if item["direction"] == "in": + ret += _(" will appear") + elif item["direction"] == "out": + ret += _(" will disappear") + + if item["name"] != "appear": + ret += _(' using effect "{0}"').format(item["name"]) + + if "length" in item: + ret += _(" in {0!s} s").format(int(item["length"]) / 1000.0) + + self.msg(ret + ".\n") + + @staticmethod + def collect_effects(node): + """Collect information about effects.""" + effects = defaultdict(list) + for child in node.xpath(".//*[@jessyink:effectIn]"): + effect_data = inkex.Style(child.get("jessyink:effectIn")) + effect_data["direction"] = "in" + effect_data["id"] = child.get("id") + effect_data["type"] = "effect" + effects[effect_data["order"]].append(effect_data) + + for child in node.xpath(".//*[@jessyink:effectOut]"): + effect_data = inkex.Style(child.get("jessyink:effectOut")) + effect_data["direction"] = "out" + effect_data["id"] = child.get("id") + effect_data["type"] = "effect" + effects[effect_data["order"]].append(effect_data) + + for child in node.xpath(".//*[@jessyink:view]"): + effect_data = inkex.Style(child.get("jessyink:view")) + effect_data["id"] = child.get("id") + effect_data["type"] = "view" + effects[effect_data["order"]].append(effect_data) + return effects + + +if __name__ == "__main__": + Summary().run() diff --git a/share/extensions/jessyink_transitions.inx b/share/extensions/jessyink_transitions.inx new file mode 100644 index 0000000..90701f5 --- /dev/null +++ b/share/extensions/jessyink_transitions.inx @@ -0,0 +1,39 @@ + + + Transitions + jessyink.transitions + + + + + 0.8 + + + + + + + + 0.8 + + + + + + + + + + + + + g + + + + + + + diff --git a/share/extensions/jessyink_transitions.py b/share/extensions/jessyink_transitions.py new file mode 100755 index 0000000..3ddc1d3 --- /dev/null +++ b/share/extensions/jessyink_transitions.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Effect to add transitions""" + +import inkex +from inkex.styles import Style + +from jessyink_install import JessyInkMixin, _ + + +class Transitions(JessyInkMixin, inkex.EffectExtension): + """Add transition to later""" + + def add_arguments(self, pars): + pars.add_argument("--tab", dest="what") + pars.add_argument("--layerName", default="") + pars.add_argument("--effectIn", default="default") + pars.add_argument("--effectOut", default="default") + pars.add_argument("--effectInDuration", type=float, default=0.8) + pars.add_argument("--effectOutDuration", type=float, default=0.8) + + def effect(self): + self.is_installed() + + if not self.options.layerName: + raise inkex.AbortExtension(_("Please enter a layer name.")) + + node = self.svg.getElement( + f"//*[@inkscape:groupmode='layer' " + f"and @inkscape:label='{self.options.layerName}']" + ) + if node is None: + raise inkex.AbortExtension( + _("Layer '{}' not found.").format(self.options.layerName) + ) + + if self.options.effectIn == "default": + node.set("jessyink:transitionIn", None) + else: + length = int(self.options.effectInDuration * 1000) + node.set( + "jessyink:transitionIn", + Style(name=self.options.effectIn, length=length), + ) + + if self.options.effectOut == "default": + node.set("jessyink:transitionOut", None) + else: + length = int(self.options.effectOutDuration * 1000) + node.set( + "jessyink:transitionOut", + Style(name=self.options.effectOut, length=length), + ) + + +if __name__ == "__main__": + Transitions().run() diff --git a/share/extensions/jessyink_uninstall.inx b/share/extensions/jessyink_uninstall.inx new file mode 100644 index 0000000..a5d1711 --- /dev/null +++ b/share/extensions/jessyink_uninstall.inx @@ -0,0 +1,29 @@ + + + Uninstall/remove + jessyink.uninstall + + + + true + true + true + true + true + true + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_uninstall.py b/share/extensions/jessyink_uninstall.py new file mode 100755 index 0000000..4bdbca0 --- /dev/null +++ b/share/extensions/jessyink_uninstall.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Uninstall jessyInk""" + +import inkex +from jessyink_install import JessyInkMixin + + +class Uninstall(JessyInkMixin, inkex.EffectExtension): + """Uninstall jessyInk from this svg""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--remove_script", type=inkex.Boolean, default=True) + pars.add_argument("--remove_effects", type=inkex.Boolean, default=True) + pars.add_argument("--remove_masterSlide", type=inkex.Boolean, default=True) + pars.add_argument("--remove_transitions", type=inkex.Boolean, default=True) + pars.add_argument("--remove_autoTexts", type=inkex.Boolean, default=True) + pars.add_argument("--remove_views", type=inkex.Boolean, default=True) + + def effect(self): + # Remove script, if so desired. + if self.options.remove_script: + # Find and delete script node. + for node in self.svg.xpath("//svg:script[@id='JessyInk']"): + node.delete() + + # Remove "jessyInkInit()" in the "onload" attribute, if present. + prop_list = [] + if self.svg.get("onload"): + prop_list = self.prop_str_to_list(self.svg.get("onload")) + + for prop in prop_list: + if prop == "jessyInkInit()": + prop_list.remove("jessyInkInit()") + + if prop_list: + self.svg.set("onload", self.list_to_prop_str(prop_list)) + else: + if self.document.getroot().get("onload"): + del self.document.getroot().attrib["onload"] + + self.attr_remove("effectIn", self.options.remove_effects) + self.attr_remove("effectOut", self.options.remove_effects) + self.attr_remove("masterSlide", self.options.remove_masterSlide) + self.attr_remove("transitionIn", self.options.remove_transitions) + self.attr_remove("transitionOut", self.options.remove_transitions) + self.attr_remove("autoText", self.options.remove_autoTexts) + self.attr_remove("view", self.options.remove_views) + + +# Create effect instance. +if __name__ == "__main__": + Uninstall().run() diff --git a/share/extensions/jessyink_video.inx b/share/extensions/jessyink_video.inx new file mode 100644 index 0000000..62a7e4c --- /dev/null +++ b/share/extensions/jessyink_video.inx @@ -0,0 +1,20 @@ + + + Video + jessyink.core.video + + + + + + + all + + + + + + + diff --git a/share/extensions/jessyink_video.py b/share/extensions/jessyink_video.py new file mode 100755 index 0000000..63b0afb --- /dev/null +++ b/share/extensions/jessyink_video.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Add a video to the slideshow""" + +import re +from copy import deepcopy + +import inkex +from jessyink_install import JessyInkMixin, _ + + +class Video(JessyInkMixin, inkex.EffectExtension): + """Add jessyink video""" + + def add_arguments(self, pars): + self.arg_parser.add_argument("--tab", dest="what") + + def effect(self): + self.is_installed() + # Check version. + base_view = self.svg.xpath("//sodipodi:namedview[@id='base']") + if base_view is None: + raise inkex.AbortExtension( + _( + "Could not obtain the selected layer for inclusion of the video element." + ) + ) + + layer = self.svg.get_current_layer() + if layer is None: + raise inkex.AbortExtension( + _( + "Could not obtain the selected layer for inclusion of the video element.\n\n" + ) + ) + + template = inkex.load_svg(self.get_resource("jessyink_video.svg")) + root = template.getroot() + + elem = layer.add( + root.getElement("//svg:g[@jessyink:element='core.video']").copy() + ) + node_dict = find_internal_links(elem, root, {}) + delete_ids(elem) + + for node in node_dict.values(): + elem.insert(0, node) + + for node in node_dict.values(): + node.set_id(self.svg.get_unique_id("jessyink.core.video"), backlinks=True) + + +def find_internal_links(node, svg, node_dict): + """Get all clone links and css links""" + for entry in re.findall(rb"url\(#.*\)", node.tostring()): + entry = entry.decode() + link_id = entry[5 : len(entry) - 1] + + if link_id not in node_dict: + node_dict[link_id] = deepcopy(svg.getElementById(link_id)) + find_internal_links(node_dict[link_id], svg, node_dict) + + for entry in node.iter(): + if entry.get("xlink:href"): + link_id = entry.get("xlink:href") + if link_id not in node_dict: + node_dict[link_id] = deepcopy(svg.getElementById(link_id)) + find_internal_links(node_dict[link_id], svg, node_dict) + + return node_dict + + +def delete_ids(node): + """Delete ids in the given node's children""" + for entry in node.iter(): + if "id" in entry.attrib: + del entry.attrib["id"] + + +if __name__ == "__main__": + Video().run() diff --git a/share/extensions/jessyink_video.svg b/share/extensions/jessyink_video.svg new file mode 100644 index 0000000..1d9e755 --- /dev/null +++ b/share/extensions/jessyink_video.svg @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + <replace this text with the url of the movie> + + + + + + + JessyInk video element + + + diff --git a/share/extensions/jessyink_view.inx b/share/extensions/jessyink_view.inx new file mode 100644 index 0000000..e71c9ad --- /dev/null +++ b/share/extensions/jessyink_view.inx @@ -0,0 +1,26 @@ + + + View + jessyink.view + + + 1 + 0.8 + false + + + + + + + + rect + + + + + + + diff --git a/share/extensions/jessyink_view.py b/share/extensions/jessyink_view.py new file mode 100755 index 0000000..e501080 --- /dev/null +++ b/share/extensions/jessyink_view.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# Copyright 2008, 2009 Hannes Hochreiner +# +# 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 3 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, see http://www.gnu.org/licenses/. +# +"""Extension to sssign jessyInk views to objects""" + +import inkex + +from jessyink_install import JessyInkMixin, _ + + +class View(JessyInkMixin, inkex.EffectExtension): + """Assign jessyInk views to objects""" + + def add_arguments(self, pars): + pars.add_argument("--tab", dest="what") + pars.add_argument("--viewOrder", type=int, default=1) + pars.add_argument("--viewDuration", type=float, default=0.8) + pars.add_argument("--removeView", type=inkex.Boolean) + + def effect(self): + self.is_installed() + + rect = self.svg.selection.first() + + if rect is None: + raise inkex.AbortExtension( + _( + "No object selected. Please select the object you want " + "to assign a view to and then press apply.\n" + ) + ) + + if not self.options.removeView: + view_order = str(self.options.viewOrder) + # Remove the view that currently has the requested order number. + for node in rect.xpath( + "ancestor::svg:g[@inkscape:groupmode='layer']" + "/descendant::*[@jessyink:view]" + ): + prop_dict = inkex.Style(node.get("jessyink:view")) + + if prop_dict["order"] == view_order: + node.set("jessyink:view", None) + + # Set the new view. + rect.set( + "jessyink:view", + inkex.Style( + name="view", + order=view_order, + length=int(self.options.viewDuration * 1000), + ), + ) + + # Remove possible effect arguments. + self.attr_remove("effectIn") + self.attr_remove("effectOut") + else: + self.attr_remove("view") + + +if __name__ == "__main__": + View().run() diff --git a/share/extensions/jitternodes.inx b/share/extensions/jitternodes.inx new file mode 100644 index 0000000..bd298ed --- /dev/null +++ b/share/extensions/jitternodes.inx @@ -0,0 +1,31 @@ + + + Jitter nodes + org.inkscape.filter.jitter_nodes + + + 10.0 + 10.0 + true + false + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/jitternodes.py b/share/extensions/jitternodes.py new file mode 100755 index 0000000..7fcc69d --- /dev/null +++ b/share/extensions/jitternodes.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2012 Juan Pablo Carbajal ajuanpi-dev@gmail.com +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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 3 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. +# + +import math +import random +import inkex + + +class JitterNodes(inkex.EffectExtension): + """Jiggle nodes around""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--radiusx", type=float, default=10.0, help="Randum radius X") + pars.add_argument("--radiusy", type=float, default=10.0, help="Randum radius Y") + pars.add_argument( + "--ctrl", type=inkex.Boolean, default=False, help="Randomize ctrl points" + ) + pars.add_argument( + "--end", type=inkex.Boolean, default=True, help="Randomize nodes" + ) + pars.add_argument( + "--dist", + type=self.arg_method("dist"), + default=self.dist_uniform, + help="Distribution of displacement", + ) + + def effect(self): + for node in self.svg.selection.filter(inkex.PathElement): + path = node.path.to_superpath() + for subpath in path: + closed = subpath[0] == subpath[-1] + for index, csp in enumerate(subpath): + if closed and index == len(subpath) - 1: + subpath[index] = subpath[0] + break + if self.options.end: + delta = self.randomize([0, 0]) + csp[0][0] += delta[0] + csp[0][1] += delta[1] + csp[1][0] += delta[0] + csp[1][1] += delta[1] + csp[2][0] += delta[0] + csp[2][1] += delta[1] + if self.options.ctrl: + csp[0] = self.randomize(csp[0]) + csp[2] = self.randomize(csp[2]) + node.path = path + + def randomize(self, pos): + """Randomise the given position [x, y] as set in the options""" + delta = self.options.dist(self.options.radiusx, self.options.radiusy) + return [pos[0] + delta[0], pos[1] + delta[1]] + + @staticmethod + def dist_gaussian(x, y): + """Gaussian distribution""" + return random.gauss(0.0, x), random.gauss(0.0, y) + + @staticmethod + def dist_pareto(x, y): + """Pareto distribution""" + # sign is used to fake a double sided pareto distribution. + # for parameter value between 1 and 2 the distribution has infinite variance + # I truncate the distribution to a high value and then normalize it. + # The idea is to get spiky distributions, any distribution with long-tails is + # good (ideal would be Levy distribution). + sign = random.uniform(-1.0, 1.0) + return x * math.copysign( + min(random.paretovariate(1.0), 20.0) / 20.0, sign + ), y * math.copysign(min(random.paretovariate(1.0), 20.0) / 20.0, sign) + + @staticmethod + def dist_lognorm(x, y): + """Log Norm distribution""" + sign = random.uniform(-1.0, 1.0) + return x * math.copysign( + random.lognormvariate(0.0, 1.0) / 3.5, sign + ), y * math.copysign(random.lognormvariate(0.0, 1.0) / 3.5, sign) + + @staticmethod + def dist_uniform(x, y): + """Uniform distribution""" + return random.uniform(-x, x), random.uniform(-y, y) + + +if __name__ == "__main__": + JitterNodes().run() diff --git a/share/extensions/layer2png.inx b/share/extensions/layer2png.inx new file mode 100644 index 0000000..1242854 --- /dev/null +++ b/share/extensions/layer2png.inx @@ -0,0 +1,36 @@ + + + Export Layer Slices + org.inkscape.output.export_slices + + + false + 128, 64, 48, 32, 24, 16 + slices + true + + 300 + + + + + + + + + + + + + + all + + + + + + + diff --git a/share/extensions/layer2png.py b/share/extensions/layer2png.py new file mode 100755 index 0000000..57146be --- /dev/null +++ b/share/extensions/layer2png.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007-2019 Matt Harrison, matthewharrison [at] gmail.com +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +A script that slices images. It might be useful for web design. + +You pass it the name of a layer containing rectangles that cover +the areas that you want exported (the default name for this layer +is "slices"). It then sets the opacity to 0 for all the rectangles +defined in that layer and exports as png whatever they covered. +The output filenames are based on the "Id" field of "Object Properties" +right click contextual menu of the rectangles. + +One side effect is that after exporting, it sets the slice rectangles +to different colors with a 25% opacity. (If you want to hide them, +just click on the eye next to the layer). + + * red - overwrote a file + * green - wrote a new file + * grey - skipped (not overwriting) + +For good pixel exports set the Document Properties, default units to "px" +and the width/height to the real size. (I use 1024x768) + +Here's the process I've used for slicing web layout with +Inkscape: Create your webpage layout (set page units to "px", +width/height appropriately and snap to 1 pixel intervals. This should +allow pixel perfect alignment). Then create a new layer, naming it +slices. Draw rectangles over the areas you want to slice (set +x,y,width,height to whole pixel values). Name these rectangles using +the Object Properties found in the right click contextual menu (the +saved images name will be based on that value, so name them something +like "header" instead of the default/non-useful "rect4312"). +""" +import os +import tempfile + +import inkex +from inkex.command import inkscape +from inkex.localization import inkex_gettext as _ + + +class ExportSlices(inkex.EffectExtension): + """Exports all rectangles in the current layer""" + + GREEN = "#00ff00" # new export + GREY = "#555555" # not exported + RED = "#ff0000" # overwrite + + def __init__(self): + super(ExportSlices, self).__init__() + self.color_map = {} # map node id to color based on overwrite + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument( + "--directory", + default=os.path.expanduser("~"), + help="Existing destination directory", + ) + pars.add_argument( + "--layer", default="slices", help="Layer with slices (rects) in it" + ) + pars.add_argument("--iconmode", type=inkex.Boolean, help="Icon export mode") + pars.add_argument( + "--sizes", + default="128, 64, 48, 32, 24, 16", + help="sizes to export comma separated", + ) + pars.add_argument( + "--overwrite", type=inkex.Boolean, help="Overwrite existing exports?" + ) + pars.add_argument("--dpi", default="300", help="Dots per inch (300 default)") + + def effect(self): + if not os.path.isdir(self.options.directory): + os.makedirs(self.options.directory) + + nodes = self.get_layer_nodes(self.options.layer) + if nodes is None: + raise inkex.AbortExtension( + _("Slice: '{}' does not exist.").format(self.options.layer) + ) + + # set opacity to zero in slices + for node in nodes: + self.clear_color(node) + + # save file once now + # if we have multiple slices we will make multiple calls + # to inkscape + (__, tmp_svg) = tempfile.mkstemp(".svg") + with open(tmp_svg, "wb") as fout: + fout.write(self.svg.tostring()) + + # in case there are overlapping rects, clear them all out before + # saving any + for node in nodes: + if self.options.iconmode: + for size in self.options.sizes.split(","): + size = size.strip() + if size.isdigit(): + png_size = int(size) + self.export_node(node, png_size, png_size) + else: + self.export_node(node) + + # change slice colors to grey/green/red and set opacity to 25% in real document + for node in nodes: + self.change_color(node) + return self.document + + def get_layer_nodes(self, layer_name): + """ + given the name of a layer one that contains the rectangles defining slices, + return the nodes of the rectangles. + """ + # get layer we intend to slice + slice_node = None + slice_layer = self.svg.findall("svg:g") + for node in slice_layer: + label_value = node.label + if label_value == layer_name: + slice_node = node + + if slice_node is not None: + return slice_node.findall("svg:rect") + return slice_node + + def clear_color(self, node): + """ + set opacity to zero, and stroke to none + + Node looks like this: + + + 3 - Convert Glyph Layers to SVG Font + org.inkscape.typography.layers_to_svg_font + + all + + + + + + diff --git a/share/extensions/layers2svgfont.py b/share/extensions/layers2svgfont.py new file mode 100755 index 0000000..f5631cd --- /dev/null +++ b/share/extensions/layers2svgfont.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# +"""Convert known layer structures to svg font glyphs""" + +import inkex +from inkex import SVGfont, FontFace, Glyph + + +class LayersToSvgFont(inkex.EffectExtension): + """Convert layers to an svg font""" + + def guideline_value(self, label, index): + for guide in self.svg.namedview.get_guides(): + if guide.label == label: + return guide.point[index] + return 0 + + def flip_cordinate_system(self, path, emsize, baseline): + """Flip Y axis because SVG fonts use a different orientation than regular SVG""" + path = path.copy() + path.transform.add_scale(1, -1) + path.transform.add_translate(0, int(emsize) - int(baseline)) + path.apply_transform() + return str(path.path) + + def effect(self): + """Main extension code""" + emsize = int(float(self.svg.get("width"))) + baseline = self.guideline_value("baseline", 1) + ascender = self.guideline_value("ascender", 1) - baseline + caps = self.guideline_value("caps", 1) - baseline + xheight = self.guideline_value("xheight", 1) - baseline + descender = baseline - self.guideline_value("descender", 1) + + font = self.svg.defs.get_or_create("svg:font", SVGfont) + font.set("horiz-adv-x", str(emsize)) + font.set("horiz-origin-y", str(baseline)) + + fontface = font.get_or_create("font-face", FontFace) + fontface.set("font-family", "SVGFont") + fontface.set("units-per-em", str(emsize)) + fontface.set("cap-height", str(caps)) + fontface.set("x-height", str(xheight)) + fontface.set("ascent", str(ascender)) + fontface.set("descent", str(descender)) + + for group in self.svg.findall("svg:g"): + label = group.label + if "GlyphLayer-" in label: + unicode_char = label.split("GlyphLayer-")[1] + if unicode_char == "'": + glyph = font.get_or_create("""svg:glyph[@unicode="'"]""", Glyph) + else: + glyph = font.get_or_create( + "svg:glyph[@unicode='{}']".format(unicode_char), Glyph + ) + glyph.set("unicode", unicode_char) + + ############################ + # Option 1: + # Using clone (svg:use) as childnode of svg:glyph + + # use = glyph.get_or_create('svg:use', UseElement) + # use.set('xlink:href', "#"+group.get("id")) + # TODO: This creates nodes; why do they do not render on svg fonts dialog? + + ############################ + # Option 2: + # Using svg:paths as childnodes of svg:glyph + + # for p in group.findall('svg:path'): + # d = p.get("d") + # d = self.flip_cordinate_system(d, emsize, baseline) + # path = glyph.add(PathElement()) + # path.set("d", d) + + ############################ + # Option 3: + # Using curve description in d attribute of svg:glyph + + path_d = "" + for path in group.findall("svg:path"): + path_d += " " + self.flip_cordinate_system(path, emsize, baseline) + glyph.set("d", path_d) + + +if __name__ == "__main__": + LayersToSvgFont().run() diff --git a/share/extensions/layout_nup.inx b/share/extensions/layout_nup.inx new file mode 100644 index 0000000..96dc343 --- /dev/null +++ b/share/extensions/layout_nup.inx @@ -0,0 +1,75 @@ + + + N-up layout + org.greygreen.inkscape.effects.nup + + + + + + + + + + 816 + 1056 + + 0 + 0 + 0 + 0 + + + 2 + 2 + 100 + 200 + true + + 12 + 12 + 12 + 12 + + 0 + 0 + 0 + 0 + + + true + true + true + false + false + false + + + + + + + + all + + + + + + + + + + + diff --git a/share/extensions/layout_nup.py b/share/extensions/layout_nup.py new file mode 100755 index 0000000..db7a544 --- /dev/null +++ b/share/extensions/layout_nup.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 Terry Brown, terry_n_brown@yahoo.com +# +# 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. +# +from __future__ import absolute_import, unicode_literals + +import inkex +from inkex import Use, Rectangle +from inkex.base import SvgOutputMixin +from inkex.localization import inkex_gettext as _ + + +class Nup(inkex.OutputExtension, SvgOutputMixin): + """N-up Layout generator""" + + def add_arguments(self, pars): + pars.add_argument("--unit", default="px") + pars.add_argument("--rows", type=int, default=2) + pars.add_argument("--cols", type=int, default=2) + pars.add_argument("--paddingTop", type=float) + pars.add_argument("--paddingBottom", type=float) + pars.add_argument("--paddingLeft", type=float) + pars.add_argument("--paddingRight", type=float) + pars.add_argument("--marginTop", type=float) + pars.add_argument("--marginBottom", type=float) + pars.add_argument("--marginLeft", type=float) + pars.add_argument("--marginRight", type=float) + pars.add_argument("--pgMarginTop", type=float) + pars.add_argument("--pgMarginBottom", type=float) + pars.add_argument("--pgMarginLeft", type=float) + pars.add_argument("--pgMarginRight", type=float) + pars.add_argument("--pgSizeX", type=float) + pars.add_argument("--pgSizeY", type=float) + pars.add_argument("--sizeX", type=float) + pars.add_argument("--sizeY", type=float) + pars.add_argument("--calculateSize", type=inkex.Boolean, default=True) + pars.add_argument("--showHolder", type=inkex.Boolean, default=True) + pars.add_argument("--showCrosses", type=inkex.Boolean, default=True) + pars.add_argument("--showInner", type=inkex.Boolean, default=True) + pars.add_argument("--showOuter", type=inkex.Boolean, default=False) + pars.add_argument("--showInnerBox", type=inkex.Boolean, default=False) + pars.add_argument("--showOuterBox", type=inkex.Boolean, default=False) + pars.add_argument("--tab") + + def save(self, stream): + show_list = [] + for i in [ + "showHolder", + "showCrosses", + "showInner", + "showOuter", + "showInnerBox", + "showOuterBox", + ]: + if getattr(self.options, i): + show_list.append(i.lower().replace("show", "")) + opt = self.options + ret = self.generate_nup( + unit=opt.unit, + pgSize=(opt.pgSizeX, opt.pgSizeY), + pgMargin=( + opt.pgMarginTop, + opt.pgMarginRight, + opt.pgMarginBottom, + opt.pgMarginLeft, + ), + num=(opt.rows, opt.cols), + calculateSize=opt.calculateSize, + size=(opt.sizeX, opt.sizeY), + margin=(opt.marginTop, opt.marginRight, opt.marginBottom, opt.marginLeft), + padding=( + opt.paddingTop, + opt.paddingRight, + opt.paddingBottom, + opt.paddingLeft, + ), + show=show_list, + ) + if ret: + stream.write(ret) + + def expandTuple(self, unit, x, length=4): + try: + iter(x) + except: + return None + + if len(x) != length: + x *= 2 + if len(x) != length: + raise Exception("expandTuple: requires 2 or 4 item tuple") + try: + return tuple( + map( + lambda ev: ( + self.svg.unittouu(str(eval(str(ev))) + unit) + / self.svg.unittouu("1px") + ), + x, + ) + ) + except: + return None + + def generate_nup( + self, + unit="px", + pgSize=("8.5*96", "11*96"), + pgMargin=(0, 0), + pgPadding=(0, 0), + num=(2, 2), + calculateSize=True, + size=None, + margin=(0, 0), + padding=(20, 20), + show=["default"], + ): + """Generate the SVG. Inputs are run through 'eval(str(x))' so you can use + '8.5*72' instead of 612. Margin / padding dimension tuples can be + (top & bottom, left & right) or (top, right, bottom, left). + + Keyword arguments: + pgSize -- page size, width x height + pgMargin -- extra space around each page + pgPadding -- added to pgMargin + n -- rows x cols + size -- override calculated size, width x height + margin -- white space around each piece + padding -- inner padding for each piece + show -- list of keywords indicating what to show + - 'crosses' - cutting guides + - 'inner' - inner boundary + - 'outer' - outer boundary + """ + + if "default" in show: + show = set(show).union(["inner", "innerbox", "holder", "crosses"]) + + pgMargin = self.expandTuple(unit, pgMargin) + pgPadding = self.expandTuple(unit, pgPadding) + margin = self.expandTuple(unit, margin) + padding = self.expandTuple(unit, padding) + + pgSize = self.expandTuple(unit, pgSize, length=2) + # num = tuple(map(lambda ev: eval(str(ev)), num)) + + if not pgMargin or not pgPadding: + return inkex.errormsg(_("No padding or margin available.")) + + page_edge = list(map(sum, zip(pgMargin, pgPadding))) + + top, right, bottom, left = 0, 1, 2, 3 + width, height = 0, 1 + rows, cols = 0, 1 + size = self.expandTuple(unit, size, length=2) + if ( + size is None + or calculateSize + or len(size) < 2 + or size[0] == 0 + or size[1] == 0 + ): + size = ( + ( + pgSize[width] + - page_edge[left] + - page_edge[right] + - num[cols] * (margin[left] + margin[right]) + ) + / num[cols], + ( + pgSize[height] + - page_edge[top] + - page_edge[bottom] + - num[rows] * (margin[top] + margin[bottom]) + ) + / num[rows], + ) + else: + size = self.expandTuple(unit, size, length=2) + + # sep is separation between same points on pieces + sep = ( + size[width] + margin[right] + margin[left], + size[height] + margin[top] + margin[bottom], + ) + + style = "stroke:#000000;stroke-opacity:1;fill:none;fill-opacity:1;" + + padbox = Rectangle( + x=str(page_edge[left] + margin[left] + padding[left]), + y=str(page_edge[top] + margin[top] + padding[top]), + width=str(size[width] - padding[left] - padding[right]), + height=str(size[height] - padding[top] - padding[bottom]), + style=style, + ) + margbox = Rectangle( + x=str(page_edge[left] + margin[left]), + y=str(page_edge[top] + margin[top]), + width=str(size[width]), + height=str(size[height]), + style=style, + ) + + doc = self.get_template(width=pgSize[width], height=pgSize[height]) + svg = doc.getroot() + + def make_clones(under, to): + for row in range(0, num[rows]): + for col in range(0, num[cols]): + if row == 0 and col == 0: + continue + use = under.add(Use()) + use.set("xlink:href", "#" + to) + use.transform.add_translate(col * sep[width], row * sep[height]) + + # guidelayer ##################################################### + if {"inner", "outer"}.intersection(show): + layer = svg.add(inkex.Layer.new("Guide Layer")) + if "inner" in show: + ibox = layer.add(padbox.copy()) + ibox.style["stroke"] = "#8080ff" + ibox.set("id", "innerguide") + make_clones(layer, "innerguide") + if "outer" in show: + obox = layer.add(margbox.copy()) + obox.style["stroke"] = "#8080ff" + obox.set("id", "outerguide") + make_clones(layer, "outerguide") + + # crosslayer ##################################################### + if {"crosses"}.intersection(show): + layer = svg.add(inkex.Layer.new("Cut Layer")) + + if "crosses" in show: + crosslen = 12 + group = layer.add(inkex.Group(id="cross")) + x, y = 0, 0 + path = "M%f %f" % ( + x + page_edge[left] + margin[left], + y + page_edge[top] + margin[top] - crosslen, + ) + path += " L%f %f" % ( + x + page_edge[left] + margin[left], + y + page_edge[top] + margin[top] + crosslen, + ) + path += " M%f %f" % ( + x + page_edge[left] + margin[left] - crosslen, + y + page_edge[top] + margin[top], + ) + path += " L%f %f" % ( + x + page_edge[left] + margin[left] + crosslen, + y + page_edge[top] + margin[top], + ) + group.add( + inkex.PathElement( + style=style + "stroke-width:0.05", d=path, id="crossmarker" + ) + ) + for row in 0, 1: + for col in 0, 1: + if row or col: + cln = group.add(Use()) + cln.set("xlink:href", "#crossmarker") + cln.transform.add_translate( + col * size[width], row * size[height] + ) + make_clones(layer, "cross") + + # clonelayer ##################################################### + layer = svg.add(inkex.Layer.new("Clone Layer")) + make_clones(layer, "main") + + # mainlayer ###################################################### + layer = svg.add(inkex.Layer.new("Main Layer")) + group = layer.add(inkex.Group(id="main")) + + if "innerbox" in show: + group.add(padbox) + if "outerbox" in show: + group.add(margbox) + if "holder" in show: + x, y = ( + page_edge[left] + margin[left] + padding[left], + page_edge[top] + margin[top] + padding[top], + ) + w, h = ( + size[width] - padding[left] - padding[right], + size[height] - padding[top] - padding[bottom], + ) + path = "M{:f} {:f}".format(x + w / 2.0, y) + path += " L{:f} {:f}".format(x + w, y + h / 2.0) + path += " L{:f} {:f}".format(x + w / 2.0, y + h) + path += " L{:f} {:f}".format(x, y + h / 2.0) + path += " Z" + group.add(inkex.PathElement(style=style, d=path)) + + return svg.tostring() + + +if __name__ == "__main__": + Nup().run() diff --git a/share/extensions/lindenmayer.inx b/share/extensions/lindenmayer.inx new file mode 100644 index 0000000..32fe8bc --- /dev/null +++ b/share/extensions/lindenmayer.inx @@ -0,0 +1,51 @@ + + + L-system + org.ekips.filter.turtle.lindenmayer + + + ++F + F=FF-[-F+F+F]+[+F-F-F] + 3 + 25.0 + 0.0 + 16.0 + 16.0 + 0.0 + + + + + + + all + + + + + + diff --git a/share/extensions/lindenmayer.py b/share/extensions/lindenmayer.py new file mode 100755 index 0000000..04e896a --- /dev/null +++ b/share/extensions/lindenmayer.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# + +import random +import inkex +from inkex import turtle as pturtle + + +class Lindenmayer(inkex.GenerateExtension): + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--order", type=int, default=3, help="number of iteration") + pars.add_argument( + "--langle", type=float, default=16.0, help="angle for turning left" + ) + pars.add_argument( + "--rangle", type=float, default=16.0, help="angle for turning right" + ) + pars.add_argument("--step", type=float, default=25.0, help="step size") + pars.add_argument( + "--randomizestep", type=float, default=0.0, help="randomize step" + ) + pars.add_argument( + "--randomizeangle", type=float, default=0.0, help="randomize angle" + ) + pars.add_argument("--axiom", default="++F", help="initial state of system") + pars.add_argument( + "--rules", default="F=FF-[-F+F+F]+[+F-F-F]", help="replacement rules" + ) + self.stack = [] + self.turtle = pturtle.pTurtle() + + def iterate(self): + self.rules = dict( + [ + map((lambda s: s.strip()), i.split("=")) + for i in self.options.rules.upper().split(";") + if i.count("=") == 1 + ] + ) + string = self.__recurse(self.options.axiom.upper(), 0) + self.__compose_path(string) + return self.turtle.getPath() + + def __compose_path(self, string): + self.turtle.pu() + point = self.svg.namedview.center + self.turtle.setpos(point) + self.turtle.pd() + for c in string: + if c in "ABCDEF": + self.turtle.pd() + self.turtle.fd( + self.options.step + * (random.normalvariate(1.0, 0.01 * self.options.randomizestep)) + ) + elif c in "GHIJKL": + self.turtle.pu() + self.turtle.fd( + self.options.step + * (random.normalvariate(1.0, 0.01 * self.options.randomizestep)) + ) + elif c == "+": + self.turtle.lt( + self.options.langle + * (random.normalvariate(1.0, 0.01 * self.options.randomizeangle)) + ) + elif c == "-": + self.turtle.rt( + self.options.rangle + * (random.normalvariate(1.0, 0.01 * self.options.randomizeangle)) + ) + elif c == "|": + self.turtle.lt(180) + elif c == "[": + self.stack.append([self.turtle.getpos(), self.turtle.getheading()]) + elif c == "]": + self.turtle.pu() + pos, heading = self.stack.pop() + self.turtle.setpos(pos) + self.turtle.setheading(heading) + + def __recurse(self, rule, level): + level_string = "" + for c in rule: + if level < self.options.order: + try: + level_string = level_string + self.__recurse( + self.rules[c], level + 1 + ) + except KeyError: + level_string = level_string + c + else: + level_string = level_string + c + return level_string + + def generate(self): + self.options.step = self.svg.unittouu(str(self.options.step) + "px") + sty = { + "stroke-linejoin": "miter", + "stroke-width": str(self.svg.unittouu("1px")), + "stroke-opacity": "1.0", + "fill-opacity": "1.0", + "stroke": "#000000", + "stroke-linecap": "butt", + "fill": "none", + } + return inkex.PathElement(style=str(inkex.Style(sty)), d=self.iterate()) + + +if __name__ == "__main__": + Lindenmayer().run() diff --git a/share/extensions/lorem_ipsum.inx b/share/extensions/lorem_ipsum.inx new file mode 100644 index 0000000..bb68693 --- /dev/null +++ b/share/extensions/lorem_ipsum.inx @@ -0,0 +1,25 @@ + + + Lorem ipsum + com.kaioa.lorem_ipsum + + + 5 + 16 + 4 + true + + + + + + + all + + + + + + diff --git a/share/extensions/lorem_ipsum.py b/share/extensions/lorem_ipsum.py new file mode 100755 index 0000000..a20e2c9 --- /dev/null +++ b/share/extensions/lorem_ipsum.py @@ -0,0 +1,316 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2006 Jos Hirth, kaioa.com +# 2020 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +""" +Example filltext sentences generated over at http://lipsum.com/ +""" + +import random + +import inkex +from inkex import Layer, FlowRoot, FlowRegion, FlowPara, Rectangle, TextElement, Tspan + +CORPA = [ + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ", + "Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. ", + "Phasellus at purus sed purus cursus iaculis. ", + "Suspendisse fermentum. ", + "Pellentesque et arcu. ", + "Maecenas viverra. ", + "In consectetuer, lorem eu lobortis egestas, velit odio imperdiet" + " eros, sit amet sagittis nunc mi ac neque. ", + "Sed non ipsum. ", + "Nullam venenatis gravida orci. ", + "Curabitur nunc ante, ullamcorper vel, auctor a, aliquam at, tortor. ", + "Etiam sodales orci nec ligula. ", + "Sed at turpis vitae velit euismod aliquet. ", + "Fusce venenatis ligula in pede. ", + "Pellentesque viverra dolor non nunc. ", + "Donec interdum vestibulum libero. ", + "Morbi volutpat. ", + "Phasellus hendrerit. ", + "Quisque dictum quam vel neque. ", + "Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis" + " risus, at nonummy arcu urna pulvinar nibh. ", + "Nam pharetra. ", + "Nam rhoncus, lectus vel hendrerit congue, nisl lorem feugiat ante, in" + " fermentum erat nulla tristique arcu. ", + "Mauris et dolor. ", + "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere" + " cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta" + " est, eget sollicitudin lectus lectus eget lacus. ", + "Praesent a lacus vitae turpis consequat semper. ", + "In commodo, dolor quis fermentum ullamcorper, urna massa volutpat" + " massa, vitae mattis purus arcu nec nulla. ", + "In hac habitasse platea dictumst. ", + "Praesent scelerisque. ", + "Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. ", + "Vestibulum non arcu a ante feugiat vestibulum. ", + "Nam laoreet dui sed magna. ", + "Proin diam augue, semper vitae, varius et, viverra id, felis. ", + "Pellentesque sit amet dui vel justo gravida auctor. ", + "Aenean scelerisque metus eget sem. ", + "Maecenas rhoncus rhoncus ipsum. ", + "Donec nonummy lacinia leo. ", + "Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. ", + "Pellentesque habitant morbi tristique senectus et netus et malesuada" + " fames ac turpis egestas. ", + "Mauris tempus diam. ", + "Maecenas justo. ", + "Sed a lorem ut est tincidunt consectetuer. ", + "Ut eu metus id lectus vestibulum ultrices. ", + "Suspendisse lectus. ", + "Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu" + " auctor metus nulla non lorem. ", + "Suspendisse potenti. ", + "Integer fringilla. ", + "Morbi urna. ", + "Morbi pulvinar nulla sit amet nisl. ", + "Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. ", + "Morbi a mauris. ", + "Pellentesque suscipit accumsan massa. ", + "Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. ", + "Quisque facilisis, urna sit amet pulvinar mollis, purus arcu adipiscing" + " velit, non condimentum diam purus eu massa. ", + "Suspendisse potenti. ", + "Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. ", + "Aliquam metus. ", + "Nam a nunc. ", + "Vivamus feugiat. ", + "Nunc metus. ", + "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere" + " cubilia Curae; Vivamus eu orci. ", + "Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales" + " sapien, sit amet posuere quam purus at lacus. ", + "Curabitur tincidunt tellus nec purus. ", + "Nam consectetuer mollis dolor. ", + "Sed quis elit. ", + "Aenean luctus vulputate turpis. ", + "Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. ", + "Nulla facilisi. ", + "Aliquam vel nibh. ", + "Vivamus nisi elit, nonummy id, facilisis non, blandit ac, dolor. ", + "Etiam cursus purus interdum libero. ", + "Nam id neque. ", + "Etiam pede nunc, vestibulum vel, rutrum et, tincidunt eu, enim. ", + "Aenean id purus. ", + "Aenean ultrices turpis. ", + "Mauris et pede. ", + "Suspendisse potenti. ", + "Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. ", + "Maecenas convallis dui. ", + "In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. ", + "Mauris ac massa vestibulum nisl facilisis viverra. ", + "Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. ", + "Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. ", + "Praesent semper, neque vel condimentum hendrerit, lectus elit pretium" + "ligula, nec consequat nisl velit at dui. ", + "Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. ", + "Aenean ligula. ", + "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere" + " cubilia Curae; Suspendisse potenti. ", + "Etiam pharetra lacus sed velit imperdiet bibendum. ", + "Nunc in turpis ac lacus eleifend sagittis. ", + "Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. ", + "In tempus urna. ", + "Quisque vehicula porttitor odio. ", + "Aliquam sed erat. ", + "Vestibulum viverra varius enim. ", + "Donec ut purus. ", + "Pellentesque convallis dolor vel libero. ", + "Integer tempus malesuada pede. ", + "Integer porta. ", + "Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. ", + "Nulla blandit justo a metus. ", + "Curabitur accumsan felis in erat. ", + "Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. ", + "Nulla sagittis condimentum ligula. ", + "Aliquam imperdiet lobortis metus. ", + "Suspendisse molestie sem. ", + "Ut venenatis. ", + "Pellentesque condimentum felis a sem. ", + "Fusce nonummy commodo dui. ", + "Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. ", + "Etiam fermentum. ", + "Phasellus auctor enim eget sem. ", + "Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. ", + "Sed fringilla. ", + "Nam malesuada sapien eu nibh. ", + "Pellentesque ac turpis. ", + "Nulla sed lacus. ", + "Mauris sed nulla quis nisi interdum tempor. ", + "Quisque pretium rutrum ligula. ", + "Mauris tempor ultrices justo. ", + "In hac habitasse platea dictumst. ", + "Donec sit amet enim. ", + "Suspendisse venenatis. ", + "Nam nisl quam, posuere non, volutpat sed, semper vitae, magna. ", + "Donec ut urna. ", + "Integer risus velit, facilisis eget, viverra et, venenatis id, leo. ", + "Cras facilisis felis sit amet lorem. ", + "Nam molestie nisl at metus. ", + "Suspendisse viverra placerat tortor. ", + "Phasellus lacinia iaculis mi. ", + "Sed dolor. ", + "Quisque malesuada nulla sed pede volutpat pulvinar. ", + "Cras gravida. ", + "Mauris tincidunt aliquam ante. ", + "Fusce consectetuer tellus ut nisl. ", + "Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. ", + "Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. ", + "Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac" + " pretium nisl lectus at magna. ", + "Vivamus quis mi. ", + "Nam sed nisl nec elit suscipit ullamcorper. ", + "Donec tempus quam quis neque. ", + "Donec rutrum venenatis dui. ", + "Praesent a eros. ", + "Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. ", + "Etiam non neque ac mi vestibulum placerat. ", + "Donec at diam a tellus dignissim vestibulum. ", + "Integer accumsan. ", + "Cras ac enim vel dui vestibulum suscipit. ", + "Pellentesque tempor. ", + "Praesent lacus. ", +] + + +class LoremIpsum(inkex.EffectExtension): + """Generate text with psuedo latin content""" + + def add_arguments(self, pars): + pars.add_argument( + "--num", type=int, default=5, help="Number of paragraphs to generate" + ) + pars.add_argument( + "-c", "--sentencecount", type=int, default=16, help="Number of Sentences" + ) + pars.add_argument("-f", "--fluctuation", type=int, default=4, help="+/-") + pars.add_argument("--tab", help="The selected UI-tab when OK was pressed") + pars.add_argument( + "--svg2", help="Use SVG2 flowed text", default=True, type=inkex.Boolean + ) + + def make_paragraph(self, text_index=0): + """Make a paragraph""" + _min = max(1, self.options.sentencecount - self.options.fluctuation) + _max = max(2, self.options.sentencecount + self.options.fluctuation) + scount = int(random.random() * _max + _min) + for sentence in range(scount): + if text_index + sentence == 0: + yield CORPA[0] + else: + index = int(random.random() * (len(CORPA) - 1)) + yield CORPA[index] + + def add_text_svg12(self, node): + """Create many flowed text paragraph and append to node""" + for text_index in range(self.options.num): + para = node.add(FlowPara()) + para.text = "".join(self.make_paragraph(text_index)) + node.append(FlowPara()) + + def add_text_svg2(self, node): + """Add paragraphs to SVG2 flowed text node""" + tspan = node.add(Tspan()) + newtext = "\n\n".join( + [ + "".join(self.make_paragraph(text_index)) + for text_index in range(self.options.num) + ] + ) + tspan.text = newtext + + def get_layer(self): + """Returns the current layer if set, otherwise creates a new layer to the document and + returns it""" + parent = self.svg.get_current_layer() + if parent is None: + parent = self.svg.add(Layer.new("lorum ipsum")) + return parent + + def create_text_svg2(self, shape): + """Creates a new SVG2 flowed text with the given shape inside. If no shape inside was set, + the flowed text is appended to the selected layer""" + style = inkex.Style() + if shape is not None and not isinstance(shape, TextElement): + parent = shape.getparent() + style["shape-inside"] = shape.get_id(as_url=2) + else: + parent = self.get_layer() + style["inline-size"] = self.svg.viewbox_width + textelement = parent.add(TextElement()) + textelement.style = style + textelement.style["white-space"] = "pre" + textelement.style["font-size"] = self.svg.viewport_to_unit("8pt") + self.add_text_svg2(textelement) + + def create_text_svg12(self, shape): + """Creates a new SVG1.2 flowed text with the given shape inside. If no shape inside was set, + the flowed text is appended to the selected layer""" + root = FlowRoot() + root.set("xml:space", "preserve") + root.style["font-size"] = self.svg.viewport_to_unit("8pt") + region = root.add(FlowRegion()) + if shape is not None and not isinstance(shape, TextElement): + parent = shape.getparent() + # For svg1.2 flowed text, store a copy of the shape inside the flowregion. + region.add(shape.copy()) + else: + # Nothing selected, create a new flowtext + parent = self.get_layer() + shape = region.add( + Rectangle( + x="0", + y="0", + width=str(int(self.svg.viewbox_width)), + height=str(int(self.svg.viewbox_height)), + ) + ) + parent.add(root) + self.add_text_svg12(root) + + def effect(self): + # Existing text flow to insert new text into + done = False + for node in self.svg.selection.filter(FlowRoot): + self.add_text_svg12(node) + done = True + for node in self.svg.selection.filter(TextElement): + shape = node.style.get("shape-inside") + inlinesize = node.style.get("inline-size") + if ( + shape is not None and self.svg.getElementById(shape[4:-1]) is not None + ) or inlinesize is not None: + self.add_text_svg2(node) + done = True + + if done: + return + + shape = self.svg.selection.first() + if self.options.svg2: + self.create_text_svg2(shape) + else: + self.create_text_svg12(shape) + + +if __name__ == "__main__": + LoremIpsum().run() diff --git a/share/extensions/markers_strokepaint.inx b/share/extensions/markers_strokepaint.inx new file mode 100644 index 0000000..ec895a9 --- /dev/null +++ b/share/extensions/markers_strokepaint.inx @@ -0,0 +1,39 @@ + + + Color Markers + org.inkscape.filter.markers_stroke_paint + + + + + + + + false + true + + + + + true + -1 + + + true + 255 + + + + + false + + + all + + + + + + diff --git a/share/extensions/markers_strokepaint.py b/share/extensions/markers_strokepaint.py new file mode 100755 index 0000000..33e652b --- /dev/null +++ b/share/extensions/markers_strokepaint.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# coding=utf-8 +# coding=utf-8 +# +# Copyright (C) 2006 Aaron Spike, aaron@ekips.org +# Copyright (C) 2010 Nicolas Dufour, nicoduf@yahoo.fr (color options) +# +# 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. +# + +import inkex +from inkex.localization import inkex_gettext as _ + +MARKERS = ["marker", "marker-start", "marker-mid", "marker-end"] + + +class MarkersStrokePaint(inkex.EffectExtension): + """Add marker stroke to outline markers on selected objects.""" + + def add_arguments(self, pars): + pars.add_argument( + "--modify", + type=inkex.Boolean, + default=False, + help="Do not create a copy, modify the markers", + ) + pars.add_argument( + "--type", + dest="fill_type", + default="solid", + help="Replace the markers' fill with the object stroke or fill color", + ) + pars.add_argument( + "--alpha", + type=inkex.Boolean, + dest="assign_alpha", + default=True, + help="Assign the object fill and stroke alpha to the markers", + ) + pars.add_argument( + "--invert", + type=inkex.Boolean, + default=False, + help="Invert fill and stroke colors", + ) + pars.add_argument( + "--assign_fill", + type=inkex.Boolean, + default=True, + help="Assign a fill color to the markers", + ) + pars.add_argument( + "--fill_color", + type=inkex.Color, + default=inkex.Color(1364325887), + help="Choose a custom fill color", + ) + pars.add_argument( + "--assign_stroke", + type=inkex.Boolean, + default=True, + help="Assign a stroke color to the markers", + ) + pars.add_argument( + "--stroke_color", + type=inkex.Color, + default=inkex.Color(1364325887), + help="Choose a custom fill color", + ) + pars.add_argument( + "--tab", + type=self.arg_method("method"), + default=self.method_custom, + help="The selected UI-tab when OK was pressed", + ) + pars.add_argument( + "--colortab", help="The selected custom color tab when OK was pressed" + ) + + def method_custom(self, _): + """Choose custom colors""" + fill = self.options.fill_color if self.options.assign_fill else None + stroke = self.options.stroke_color if self.options.assign_stroke else None + return fill, stroke + + def method_object(self, style): + """Use object colors""" + fill = style.get_color("fill") + stroke = style.get_color("stroke") + + if self.options.fill_type == "solid": + fill = stroke + elif self.options.fill_type == "filled": + stroke = None + elif self.options.invert: + fill, stroke = stroke, fill + + if not self.options.assign_alpha: + # Remove alpha values + fill = fill.to_rgb() + stroke = stroke.to_rgb() + + return fill, stroke + + def effect(self): + for node in self.svg.selection.values(): + fill, stroke = self.options.tab(node.style) + + for attr in MARKERS: + marker_node = node.style(attr) + if not isinstance(marker_node, inkex.Marker): + continue + + if marker_node is None and attr in node.style: + inkex.errormsg(_("unable to locate marker: %s") % node.style[attr]) + continue + + marker_id = marker_node.get_id() + + if not self.options.modify: + marker_node = marker_node.copy() + self.svg.defs.append(marker_node) + marker_id = self.svg.get_unique_id(marker_id) + marker_node.set("id", marker_id) + marker_node.set("inkscape:stockid", marker_id) + + node.style[attr] = marker_node + + for child in marker_node: + if stroke is not None: + child.style.set_color(stroke, "stroke") + if fill is not None: + child.style.set_color(fill, "fill") + + +if __name__ == "__main__": + MarkersStrokePaint().run() diff --git a/share/extensions/measure.inx b/share/extensions/measure.inx new file mode 100644 index 0000000..498236f --- /dev/null +++ b/share/extensions/measure.inx @@ -0,0 +1,73 @@ + + + Measure Path + org.inkscape.visualise.measure_length + + + + + + + + + + + + + + + + + + + custom + 50 + + + + + + + + + + + + + 0 + + + + + + 12 + -6 + 2 + 1 + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/measure.py b/share/extensions/measure.py new file mode 100755 index 0000000..2e9d8f5 --- /dev/null +++ b/share/extensions/measure.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2015 ~suv +# Copyright (C) 2010 Alvin Penner +# Copyright (C) 2006 Georg Wiora +# Copyright (C) 2006 Nathan Hurst +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +""" +This extension module can measure arbitrary path and object length +It adds text to the selected path containing the length in a given unit. +Area and Center of Mass calculated using Green's Theorem: +http://mathworld.wolfram.com/GreensTheorem.html +""" + +import inkex + +from inkex import TextElement, TextPath, Tspan +from inkex.bezier import csparea, cspcofm, csplength +from inkex.localization import inkex_gettext as _ + + +class MeasureLength(inkex.EffectExtension): + """Measure the length of selected paths""" + + def add_arguments(self, pars): + pars.add_argument( + "--type", dest="mtype", default="length", help="Type of measurement" + ) + pars.add_argument( + "--method", + type=self.arg_method(), + default=self.method_textonpath, + help="Text Orientation method", + ) + pars.add_argument( + "--presetFormat", default="default", help="Preset text layout" + ) + pars.add_argument( + "--startOffset", default="custom", help="Text Offset along Path" + ) + pars.add_argument( + "--startOffsetCustom", type=int, default=50, help="Text Offset along Path" + ) + pars.add_argument("--anchor", default="start", help="Text Anchor") + pars.add_argument("--position", default="start", help="Text Position") + pars.add_argument("--angle", type=float, default=0, help="Angle") + pars.add_argument( + "-f", + "--fontsize", + type=int, + default=12, + help="Size of length label text in px", + ) + pars.add_argument( + "-o", + "--offset", + type=float, + default=-6, + help="The distance above the curve", + ) + pars.add_argument( + "-u", "--unit", default="px", help="The unit of the measurement" + ) + pars.add_argument( + "-p", + "--precision", + type=int, + default=2, + help="Number of significant digits after decimal point", + ) + pars.add_argument( + "-s", + "--scale", + type=float, + default=1.0, + help="Scale Factor (Drawing:Real Length)", + ) + + def effect(self): + # get number of digits + prec = int(self.options.precision) + scale = self.svg.viewport_to_unit( + "1" + self.svg.document_unit + ) # convert to document units + self.options.offset *= scale + + factor = self.svg.unit_to_viewport(1, self.options.unit) + + # loop over all selected paths + filtered = self.svg.selection.filter(inkex.PathElement) + if not filtered: + raise inkex.AbortExtension(_("Please select at least one path object.")) + for node in filtered: + csp = node.path.transform(node.composed_transform()).to_superpath() + inverse_parent_transform = -node.getparent().composed_transform() + if self.options.mtype == "length": + slengths, stotal = csplength(csp) + self.group = node.getparent().add(TextElement()) + elif self.options.mtype == "area": + stotal = abs(csparea(csp) * factor * self.options.scale) + self.group = node.getparent().add(TextElement()) + else: + try: + xc, yc = cspcofm(csp) + except ValueError as err: + raise inkex.AbortExtension(str(err)) + self.group = node.getparent().add(inkex.PathElement()) + self.group.set("id", "MassCenter_" + node.get("id")) + self.add_cross(self.group, xc, yc, scale) + self.group.transform = inverse_parent_transform + continue + # Format the length as string + val = round(stotal * factor * self.options.scale, prec) + # Transform the result back + self.options.method(node, str(val)) + + def method_textonpath(self, node, lenstr): + startOffset = self.options.startOffset + if startOffset == "custom": + startOffset = str(self.options.startOffsetCustom) + "%" + if self.options.mtype == "length": + self.add_textonpath( + self.group, + 0, + 0, + lenstr + " " + self.options.unit, + node, + self.options.anchor, + startOffset, + self.options.offset, + ) + else: + self.add_textonpath( + self.group, + 0, + 0, + lenstr + " " + self.options.unit + "^2", + node, + self.options.anchor, + startOffset, + self.options.offset, + ) + + def method_fixedtext(self, node, lenstr): + _id = node.get("id") + csp = node.path.transform(node.composed_transform()).to_superpath() + if self.options.position == "mass": + tx, ty = cspcofm(csp) + anchor = "middle" + elif self.options.position == "center": + bbox = node.bounding_box(True) + tx, ty = bbox.center + anchor = "middle" + else: # default + tx = csp[0][0][1][0] + ty = csp[0][0][1][1] + anchor = "start" + if self.options.mtype == "length": + self.add_fixedtext( + self.group, + tx, + ty, + lenstr + " " + self.options.unit, + anchor, + -int(self.options.angle), + self.options.offset + self.options.fontsize / 2, + ) + else: + self.add_fixedtext( + self.group, + tx, + ty, + lenstr + " " + self.options.unit + "^2", + anchor, + -int(self.options.angle), + -self.options.offset + self.options.fontsize / 2, + ) + + def method_presets(self, node, lenstr): + """A preset option for alignments""" + preset_dict = { + "default_cofm": [None, None, None, None, None], + "default_length": [self.method_textonpath, "50%", "start", None, None], + "TaP_start": [self.method_textonpath, "0%", "start", None, None], + "TaP_middle": [self.method_textonpath, "50%", "middle", None, None], + "TaP_end": [self.method_textonpath, "100%", "end", None, None], + "default_area": [self.method_fixedtext, None, None, "start", 0.0], + "FT_start": [self.method_fixedtext, None, None, "start", 0.0], + "FT_bbox": [self.method_fixedtext, None, None, "center", 0.0], + "FT_mass": [self.method_fixedtext, None, None, "mass", 0.0], + } + + if self.options.presetFormat == "default": + current_preset = "default_" + self.options.mtype + else: + current_preset = self.options.presetFormat + + self.options.startOffset = preset_dict[current_preset][1] + self.options.anchor = preset_dict[current_preset][2] + self.options.position = preset_dict[current_preset][3] + self.options.angle = preset_dict[current_preset][4] + method = preset_dict[current_preset][0] + if method is not None: + return method(node, lenstr) + + def add_cross(self, node, x, y, scale): + l = 3 * scale # 3 pixels in document units + node.set( + "d", + "m %s,%s %s,0 %s,0 m %s,%s 0,%s 0,%s" + % (str(x - l), str(y), str(l), str(l), str(-l), str(-l), str(l), str(l)), + ) + node.set("style", "stroke:#000000;fill:none;stroke-width:%s" % str(0.5 * scale)) + + def add_textonpath(self, node, x, y, text, _node, anchor, startOffset, dy=0): + new = node.add(TextPath()) + s = { + "text-align": "center", + "vertical-align": "bottom", + "text-anchor": anchor, + "font-size": str(self.options.fontsize), + "fill-opacity": "1.0", + "stroke": "none", + "font-weight": "normal", + "font-style": "normal", + "fill": "#000000", + } + new.style = s + new.href = _node + new.set("startOffset", startOffset) + new.set("dy", str(dy)) # dubious merit + # new.append(tp) + if text[-2:] == "^2": + new.append(Tspan.superscript("2")) + new.text = str(text)[:-2] + else: + new.text = str(text) + # node.set('transform','rotate(180,'+str(-x)+','+str(-y)+')') + node.set("x", str(x)) + node.set("y", str(y)) + + def add_fixedtext(self, node, x, y, text, anchor, angle, dy=0): + new = node.add(Tspan()) + new.set("sodipodi:role", "line") + s = { + "text-align": "center", + "vertical-align": "bottom", + "text-anchor": anchor, + "font-size": self.svg.viewport_to_unit(self.options.fontsize), + "fill-opacity": "1.0", + "stroke": "none", + "font-weight": "normal", + "font-style": "normal", + "fill": "#000000", + } + new.style = s + new.set("dy", str(dy)) + if text[-2:] == "^2": + new.append(Tspan.superscript("2")) + new.text = str(text)[:-2] + else: + new.text = str(text) + node.set("x", str(x)) + node.set("y", str(y)) + node.set("transform", "rotate(%s, %s, %s)" % (angle, x, y)) + node.transform = -node.getparent().composed_transform() @ node.transform + + +if __name__ == "__main__": + MeasureLength().run() diff --git a/share/extensions/media_zip.inx b/share/extensions/media_zip.inx new file mode 100644 index 0000000..ac8be03 --- /dev/null +++ b/share/extensions/media_zip.inx @@ -0,0 +1,19 @@ + + + Compressed Inkscape SVG with media export + org.inkscape.output.compressed_media + org.inkscape.output.svg.inkscape + images + false + + .zip + application/x-zip + Compressed Inkscape SVG with media (*.zip) + Inkscape's native file format compressed with Zip and including all media files + false + + + diff --git a/share/extensions/media_zip.py b/share/extensions/media_zip.py new file mode 100755 index 0000000..82fb25d --- /dev/null +++ b/share/extensions/media_zip.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Pim Snel, pim@lingewoud.com +# Copyright (C) 2008 Aaron Spike, aaron@ekips.org +# Copyright (C) 2011 Nicolas Dufour, nicoduf@yahoo.fr +# +# * Fix for a bug related to special characters in the path (LP #456248). +# * Fix for Windows support (LP #391307 ). +# * Font list and image directory features. +# +# this is the first Python script ever created +# its based on embedimage.py +# +# 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. +# +# TODOs +# - fix bug: not saving existing .zip after a Collect for Output is run +# this bug occurs because after running an effect extension the inkscape:output_extension is reset to svg.inkscape +# the file name is still xxx.zip. after saving again the file xxx.zip is written with a plain .svg which +# looks like a corrupt zip +# - maybe add better extension +# - consider switching to lzma in order to allow cross platform compression with no encoding problem... +# +""" +An extension which collects all images to the documents directory and +creates a zip archive containing all images and the document +""" + +import os +import tempfile +import zipfile + +from typing import List, Tuple +from urllib.parse import urlparse +from urllib.request import url2pathname + +import inkex +from inkex import TextElement, Tspan, FlowRoot, FlowPara, FlowSpan +from inkex.localization import inkex_gettext as _ + + +class CompressedMedia(inkex.OutputExtension): + """Output a compressed file""" + + def __init__(self): + super().__init__() + self.path_dict = {} + + def add_arguments(self, pars): + pars.add_argument("--image_dir", help="Image directory", default="images") + pars.add_argument("--font_list", type=inkex.Boolean, help="Add font list") + + def process_path(self, path: str) -> Tuple[str, bool]: + """Processes an absolute path and returns + (unique filename, exists).""" + + if path in self.path_dict: + return os.path.split(path)[1], True + + index = 0 + pth, ext = os.path.splitext(path) + _, filename = os.path.split(pth) + trypath = filename + ext + while True: + if trypath in list(self.path_dict.values()): + index += 1 + trypath = f"{filename}{index}{ext}" + else: + self.path_dict[path] = trypath + return trypath, False + + def collect_images(self, docname, z: zipfile.ZipFile): + """ + Collects all images in the document + and copy them to the temporary directory. + """ + imgdir = self.options.image_dir + + for node in self.svg.xpath("//svg:image"): + xlink = node.get("xlink:href") + if xlink[:4] != "data": + url = urlparse(xlink) + href = url2pathname(url.path) + + image_path = self.absolute_href(href or "") + + # Backup directory where we can find the image + if not os.path.isfile(image_path): + image_path = node.get("sodipodi:absref", image_path) + + if not os.path.isfile(image_path): + inkex.errormsg( + _('File not found "{}". Unable to embed image.').format( + image_path + ) + ) + continue + else: + zippath, exists = self.process_path(image_path) + if not exists: + z.write(image_path, os.path.join(imgdir, zippath)) + + node.set("xlink:href", f"{imgdir}/{zippath}") + + def collect_svg(self, docstripped, z: zipfile.ZipFile): + """ + Copy SVG document to the temporary directory + and add it to the temporary compressed file + """ + dst_file = os.path.join(self.tmp_dir, docstripped) + with open(dst_file, "wb") as stream: + self.document.write(stream) + z.write(dst_file, docstripped + ".svg") + + def is_text(self, node): + """ + Returns true if the tag in question is an element that + can hold text. + """ + return isinstance(node, (TextElement, Tspan, FlowRoot, FlowPara, FlowSpan)) + + def get_fonts(self, node): + """ + Given a node, returns a list containing all the fonts that + the node is using. + """ + fonts = [] + s = "" + if "style" in node.attrib: + s = dict(inkex.Style.parse_str(node.attrib["style"])) + if not s: + return fonts + + if "font-family" in s: + if "font-weight" in s: + fonts.append(s["font-family"] + " " + s["font-weight"]) + else: + fonts.append(s["font-family"]) + elif "-inkscape-font-specification" in s: + fonts.append(s["-inkscape-font-specification"]) + return fonts + + def list_fonts(self, z: zipfile.ZipFile): + """ + Walks through nodes, building a list of all fonts found, then + reports to the user with that list. + Based on Craig Marshall's replace_font.py + """ + nodes: List[inkex.BaseElement] = [] + items = self.svg.iterdescendants() + nodes.extend(filter(self.is_text, items)) + fonts_found = [] + for node in nodes: + for f in self.get_fonts(node): + if not f in fonts_found: + fonts_found.append(f) + findings = sorted(fonts_found) + # Write list to the temporary compressed file + filename = "fontlist.txt" + dst_file = os.path.join(self.tmp_dir, filename) + with open(dst_file, "w") as stream: + if len(findings) == 0: + stream.write(_("Didn't find any fonts in this document/selection.")) + else: + if len(findings) == 1: + stream.write(_("Found the following font only: %s") % findings[0]) + else: + stream.write( + _("Found the following fonts:\n%s") % "\n".join(findings) + ) + z.write(dst_file, filename) + + def save(self, stream): + docname = self.svg.get("sodipodi:docname") + + if docname is None: + docname = self.options.input_file + + # TODO: replace whatever extension + docstripped = os.path.basename(docname.replace(".zip", "")) + docstripped = docstripped.replace(".svg", "") + docstripped = docstripped.replace(".svgz", "") + + # Create os temp dir + self.tmp_dir = tempfile.mkdtemp() + + # Create destination zip in same directory as the document + with zipfile.ZipFile(stream, "w") as z: + self.collect_images(docname, z) + self.collect_svg(docstripped, z) + if self.options.font_list: + self.list_fonts(z) + + +if __name__ == "__main__": + CompressedMedia().run() diff --git a/share/extensions/merge_styles.inx b/share/extensions/merge_styles.inx new file mode 100644 index 0000000..a8b76c2 --- /dev/null +++ b/share/extensions/merge_styles.inx @@ -0,0 +1,19 @@ + + + Merge Styles into CSS + org.inkscape.stylesheet.merge_styles + + + + class1 + + + all + + + + + + diff --git a/share/extensions/merge_styles.py b/share/extensions/merge_styles.py new file mode 100755 index 0000000..0076f2c --- /dev/null +++ b/share/extensions/merge_styles.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2014-2019 Martin Owens +# +# 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. +# +""" +Merges styles into class based styles and removes. +""" + +import inkex +from inkex.localization import inkex_gettext as _ + + +class MergeStyles(inkex.EffectExtension): + """Merge any styles which are the same for CSS""" + + def add_arguments(self, pars): + self.arg_parser.add_argument( + "-n", + "--name", + type=str, + dest="name", + help="Name of selected element's common class", + ) + + def effect(self): + """Apply the style effect""" + newclass = self.options.name + if not newclass: + newclass = self.svg.get_unique_id("css") + + elements = self.svg.selection.values() + common = None + + for elem in elements: + style = set(elem.style.items()) + if common is not None: + common &= style + else: + common = style + + if not common: + return inkex.errormsg( + _("There are no common styles between these elements.") + ) + + self.svg.stylesheet.add("." + newclass, inkex.Style(sorted(common))) + + for elem in elements: + elem.style -= dict(common).keys() + elem.classes.append(newclass) + return True + + +if __name__ == "__main__": + MergeStyles().run() diff --git a/share/extensions/motion.inx b/share/extensions/motion.inx new file mode 100644 index 0000000..4570afb --- /dev/null +++ b/share/extensions/motion.inx @@ -0,0 +1,18 @@ + + + Motion + org.ekips.filter.motion + 100 + 45 + false + + path + + + + + + diff --git a/share/extensions/motion.py b/share/extensions/motion.py new file mode 100755 index 0000000..9ceab4a --- /dev/null +++ b/share/extensions/motion.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +"""Adds a "drop shadow" to any selected number of path objects. Optionally, the stroke +color can be used for the shadow""" + +import math + +import inkex +from inkex.paths import ( + Move, + Line, + Curve, + ZoneClose, + Arc, + Path, + Vert, + Horz, + TepidQuadratic, + Quadratic, + Smooth, +) +from inkex.transforms import Vector2d +from inkex.bezier import beziertatslope, beziersplitatt + + +class Motion(inkex.EffectExtension): + """Generate a motion path""" + + def add_arguments(self, pars): + pars.add_argument( + "-a", + "--angle", + type=float, + default=45.0, + help="direction of the motion vector", + ) + pars.add_argument( + "-m", + "--magnitude", + type=float, + default=100.0, + help="magnitude of the motion vector", + ) + pars.add_argument( + "-f", + "--fillwithstroke", + type=inkex.Boolean, + default=False, + help="fill shadow with stroke color if set", + ) + + @staticmethod + def makeface(last, segment, facegroup, delx, dely): + """translate path segment along vector""" + elem = facegroup.add(inkex.PathElement()) + + npt = segment.translate([delx, dely]) + + # reverse direction of path segment + if isinstance(segment, Curve): + rev = Curve(npt.x3, npt.y3, npt.x2, npt.y2, last[0] + delx, last[1] + dely) + elif isinstance(segment, Line): + rev = Line(last[0] + delx, last[1] + dely) + else: + raise RuntimeError("Unexpected segment type {}".format(type(segment))) + + elem.path = inkex.Path( + [ + Move(last[0], last[1]), + segment, + npt.to_line(Vector2d()), + rev, + ZoneClose(), + ] + ) + + def effect(self): + delx = math.cos(math.radians(self.options.angle)) * self.options.magnitude + dely = math.sin(math.radians(self.options.angle)) * self.options.magnitude + for node in self.svg.selection.filter_nonzero(inkex.PathElement): + group = node.getparent().add(inkex.Group()) + facegroup = group.add(inkex.Group()) + group.append(node) + + # we want delx and dely values to be correct even for the transformed path, + # so transform them back, but ignore the translate of the transform + trans = -node.transform + local_delx = trans.a * delx + trans.c * dely + local_dely = trans.b * delx + trans.d * dely + + if node.transform: + group.transform = node.transform + node.transform = None + + facegroup.style = node.style + if self.options.fillwithstroke: + stroke = facegroup.style("stroke") + if stroke is not None and isinstance(stroke, inkex.Color): + facegroup.style["fill"] = stroke + facegroup.style["fill-opacity"] = facegroup.style("stroke-opacity") + reset_origin = True + for cmd_proxy in node.path.to_absolute().proxy_iterator(): + # for each subpath, reset the origin of the following computations to the first + # node of the subpath -> i.e. after a Z command, move the origin to the end point + # of the next command + if reset_origin: + first_point = cmd_proxy.end_point + reset_origin = False + if isinstance(cmd_proxy.command, ZoneClose): + reset_origin = True + self.process_segment( + cmd_proxy, facegroup, local_delx, local_dely, first_point + ) + + @staticmethod + def process_segment(cmd_proxy, facegroup, delx, dely, first_point): + """Process each segments""" + + segments = [] + if isinstance( + cmd_proxy.command, (Curve, Smooth, TepidQuadratic, Quadratic, Arc) + ): + prev = cmd_proxy.previous_end_point + for curve in cmd_proxy.to_curves(): + bez = [prev] + curve.to_bez() + prev = curve.end_point(cmd_proxy.first_point, prev) + tees = [t for t in beziertatslope(bez, (dely, delx)) if 0 < t < 1] + tees.sort() + if len(tees) == 1: + one, two = beziersplitatt(bez, tees[0]) + segments.append(Curve(*(one[1] + one[2] + one[3]))) + segments.append(Curve(*(two[1] + two[2] + two[3]))) + elif len(tees) == 2: + one, two = beziersplitatt(bez, tees[0]) + two, three = beziersplitatt(two, tees[1]) + segments.append(Curve(*(one[1] + one[2] + one[3]))) + segments.append(Curve(*(two[1] + two[2] + two[3]))) + segments.append(Curve(*(three[1] + three[2] + three[3]))) + else: + segments.append(curve) + elif isinstance(cmd_proxy.command, (Line, Curve)): + segments.append(cmd_proxy.command) + elif isinstance(cmd_proxy.command, ZoneClose): + segments.append(Line(*first_point)) + elif isinstance(cmd_proxy.command, (Vert, Horz)): + segments.append(cmd_proxy.command.to_line(cmd_proxy.end_point)) + + for seg in Path( + [Move(*cmd_proxy.previous_end_point)] + segments + ).proxy_iterator(): + if isinstance(seg.command, Move): + continue + Motion.makeface(seg.previous_end_point, seg.command, facegroup, delx, dely) + + +if __name__ == "__main__": + Motion().run() diff --git a/share/extensions/new_glyph_layer.inx b/share/extensions/new_glyph_layer.inx new file mode 100644 index 0000000..cec7639 --- /dev/null +++ b/share/extensions/new_glyph_layer.inx @@ -0,0 +1,15 @@ + + + 2 - Add Glyph Layer + org.inkscape.typography.new_glyph_layer + + + all + + + + + + diff --git a/share/extensions/new_glyph_layer.py b/share/extensions/new_glyph_layer.py new file mode 100755 index 0000000..3e12ada --- /dev/null +++ b/share/extensions/new_glyph_layer.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# + +import locale +import sys + +import inkex + + +class NewGlyphLayer(inkex.EffectExtension): + def add_arguments(self, pars): + self.arg_parser.add_argument("--text", default="", help="Unicode chars") + + self.encoding = sys.stdin.encoding + if self.encoding == "cp0" or self.encoding is None: + self.encoding = locale.getpreferredencoding() + + def effect(self): + # Get all the options + unicode_chars = self.options.text + if isinstance(unicode_chars, bytes): + unicode_chars = unicode_chars.decode(self.encoding) + + # TODO: remove duplicate chars + + for char in unicode_chars: + # Create a new layer. + layer = self.svg.add(inkex.Layer.new("GlyphLayer-" + char)) + layer.set("style", "display:none") # initially not visible + + # TODO: make it optional ("Use current selection as template glyph") + # Move selection to the newly created layer + for node in self.svg.selection.values(): + layer.append(node) + + +if __name__ == "__main__": + NewGlyphLayer().run() diff --git a/share/extensions/next_glyph_layer.inx b/share/extensions/next_glyph_layer.inx new file mode 100644 index 0000000..81353d1 --- /dev/null +++ b/share/extensions/next_glyph_layer.inx @@ -0,0 +1,14 @@ + + + View Next Glyph + org.inkscape.typography.next_layer + + all + + + + + + diff --git a/share/extensions/next_glyph_layer.py b/share/extensions/next_glyph_layer.py new file mode 100755 index 0000000..2fc8c3b --- /dev/null +++ b/share/extensions/next_glyph_layer.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# + +import inkex + + +class NextLayer(inkex.EffectExtension): + """Show the next glyph layer""" + + def effect(self): + count = 0 + glyphs = [] + for group in self.svg.findall("svg:g"): + if "GlyphLayer-" in group.label: + glyphs.append(group) + if group.style.get("display", "") == "inline": + count += 1 + current = len(glyphs) - 1 + + if count != 1 or len(glyphs) < 2: + return + + self.process_glyphs(glyphs, current) + + @staticmethod + def process_glyphs(glyphs, current): + """Process the glyphs""" + glyphs[current].set("style", "display:none") + glyphs[(current + 1) % len(glyphs)].set("style", "display:inline") + + +if __name__ == "__main__": + NextLayer().run() diff --git a/share/extensions/nicechart.inx b/share/extensions/nicechart.inx new file mode 100644 index 0000000..e37cd42 --- /dev/null +++ b/share/extensions/nicechart.inx @@ -0,0 +1,102 @@ + + + + + + NiceCharts + org.inkscape.filter.nice_chart + + + + + + + ; + 0 + 1 + utf-8 + false + + + + + apples:3,bananas:5,oranges:10,pears:4 + + + + + sans-serif + 10 + #000000 + + + false + 100 + 10 + 100 + 5 + 1 + 5 + 50 + false + + + + + + + + + + + + false + false + + + false + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/nicechart.py b/share/extensions/nicechart.py new file mode 100755 index 0000000..e25865f --- /dev/null +++ b/share/extensions/nicechart.py @@ -0,0 +1,654 @@ +#!/usr/bin/env python +# coding=utf-8 +# nicechart.py +# +# Copyright 2011-2016 +# +# Christoph Sterz +# Florian Weber +# Maren Hachmann +# +# 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 3 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. +# +# pylint: disable=attribute-defined-outside-init + +# TODO / Ideas: +# allow negative values for bar charts +# show values for stacked bar charts +# don't create a new layer for each chart, but a normal group +# correct bar height for stacked bars (it's only half as high as it should be, double) +# adjust position of heading +# use aliasing workaround for stacked bars (e.g. let the rectangles overlap) + +# The extension creates one chart for a single value column in one go, +# e.g. chart all temperatures for all months of the year 1978 into one chart. +# (for this, select column 0 for labels and column 1 for values). +# "1978" etc. can be used as heading (Need not be numeric. If not used delete the heading line.) +# Month names can be used as labels +# Values can be shown, in addition to labels (doesn't work with stacked bar charts) +# Values can contain commas as decimal separator, as long as delimiter isn't comma +# Negative values are not yet supported. + +# See tests/data/nicechart_01.csv for example data + +import re +import csv +import math + +from argparse import ArgumentTypeError + +import inkex +from inkex.utils import filename_arg +from inkex import Filter, TextElement, Circle, Rectangle +from inkex.paths import Move, line +from inkex.localization import inkex_gettext as _ + +# www.sapdesignguild.org/goodies/diagram_guidelines/color_palettes.html#mss +COLOUR_TABLE = { + "red": [ + "#460101", + "#980101", + "#d40000", + "#f44800", + "#fb8b00", + "#eec73e", + "#d9bb7a", + "#fdd99b", + ], + "blue": ["#000442", "#0F1781", "#252FB7", "#3A45E1", "#656DDE", "#8A91EC"], + "gray": [ + "#222222", + "#444444", + "#666666", + "#888888", + "#aaaaaa", + "#cccccc", + "#eeeeee", + ], + "contrast": ["#0000FF", "#FF0000", "#00FF00", "#CF9100", "#FF00FF", "#00FFFF"], + "sap": [ + "#f8d753", + "#5c9746", + "#3e75a7", + "#7a653e", + "#e1662a", + "#74796f", + "#c4384f", + "#fff8a3", + "#a9cc8f", + "#b2c8d9", + "#bea37a", + "#f3aa79", + "#b5b5a9", + "#e6a5a5", + ], +} + + +class NiceChart(inkex.GenerateExtension): + """ + Inkscape extension that can draw pie charts and bar charts + (stacked, single, horizontally or vertically) + with optional drop shadow, from a csv file or from pasted text + """ + + container_layer = True + + @property + def container_label(self): + """Layer title/label""" + return _("Chart-Layer: {}").format(self.options.what) + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--encoding", default="utf-8") + pars.add_argument( + "-w", + "--what", + default="apples:3,bananas:5,oranges:10,pears:4", + help="Chart Values", + ) + pars.add_argument( + "-t", + "--type", + type=self.arg_method("render"), + default=self.render_bar, + help="Chart Type", + ) + pars.add_argument( + "-b", "--blur", type=inkex.Boolean, default=False, help="Blur Type" + ) + pars.add_argument("-f", "--filename", type=filename_arg, help="Name of File") + pars.add_argument("-i", "--input_type", default="file", help="Chart Type") + pars.add_argument("-d", "--delimiter", default=";", help="delimiter") + pars.add_argument("-c", "--colors", default="default", help="color-scheme") + pars.add_argument("--colors_override", help="color-scheme-override") + pars.add_argument( + "--reverse_colors", + type=inkex.Boolean, + default=False, + help="reverse color-scheme", + ) + pars.add_argument( + "-k", "--col_key", type=int, default=0, help="column that contains the keys" + ) + pars.add_argument( + "-v", + "--col_val", + type=int, + default=1, + help="column that contains the values", + ) + pars.add_argument( + "--headings", + type=inkex.Boolean, + default=False, + help="first line of the CSV file consists of headings for the columns", + ) + pars.add_argument( + "-r", + "--rotate", + type=inkex.Boolean, + default=False, + help="Draw barchart horizontally", + ) + pars.add_argument( + "-W", "--bar-width", type=int, default=10, help="width of bars" + ) + pars.add_argument( + "-p", "--pie-radius", type=int, default=100, help="radius of pie-charts" + ) + pars.add_argument( + "-H", "--bar-height", type=int, default=100, help="height of bars" + ) + pars.add_argument( + "-O", "--bar-offset", type=int, default=5, help="distance between bars" + ) + pars.add_argument("--stroke-width", type=float, default=1.0) + pars.add_argument( + "-o", + "--text-offset", + type=int, + default=5, + help="distance between bar and descriptions", + ) + pars.add_argument( + "--heading-offset", + type=int, + default=50, + help="distance between chart and chart title", + ) + pars.add_argument( + "--segment-overlap", + type=inkex.Boolean, + default=False, + help="Remove aliasing effects by letting pie chart segments overlap", + ) + pars.add_argument( + "-F", "--font", default="sans-serif", help="font of description" + ) + pars.add_argument( + "-S", "--font-size", type=int, default=10, help="font size of description" + ) + pars.add_argument( + "-C", "--font-color", default="#000000", help="font color of description" + ) + + pars.add_argument( + "-V", + "--show_values", + type=inkex.Boolean, + default=False, + help="Show values in chart", + ) + + def get_data(self): + """Process the data""" + col_key = self.options.col_key + col_val = self.options.col_val + + def process_value(val): + """Confirm the values from files or direct""" + val = float(val) + if val < 0: + raise inkex.AbortExtension( + _("Negative values are currently not supported!") + ) + return val + + if self.options.input_type == "file": + if self.options.filename is None: + raise inkex.AbortExtension(_("Filename not specified!")) + + # Future: use encoding when opening the file here (if ever needed) + with open(self.options.filename, "r") as fhl: + reader = csv.reader(fhl, delimiter=self.options.delimiter) + title = col_val + + if self.options.headings: + header = next(reader) + title = header[col_val] + + values = [ + (line[col_key], process_value(line[col_val])) for line in reader + ] + return (title,) + tuple(zip(*values)) + + elif self.options.input_type == "direct_input": + (keys, values) = zip( + *[l.split(":", 1) for l in self.options.what.split(",")] + ) + return ("Direct Input", keys, [process_value(val) for val in values]) + + raise inkex.AbortExtension(_("Unknown input type")) + + def get_blur(self): + """Add blur to the svg and return if needed""" + if self.options.blur: + defs = self.svg.defs + # Create new Filter + filt = defs.add(Filter(height="3", width="3", x="-0.5", y="-0.5")) + # Append Gaussian Blur to that Filter + filt.add_primitive("feGaussianBlur", stdDeviation="1.1") + return inkex.Style(filter=filt.get_id(as_url=2)) + return inkex.Style() + + def get_color(self): + """Get the next available color""" + if not hasattr(self, "_colors"): + # Generate list of available colours + if self.options.colors_override: + colors = self.options.colors_override.strip() + else: + colors = self.options.colors + + if colors[0].isalpha(): + colors = COLOUR_TABLE.get(colors.lower(), COLOUR_TABLE["red"]) + + else: + colors = re.findall("(#[0-9a-fA-F]{6})", colors) + # to be sure we create a fallback: + if not colors: + colors = COLOUR_TABLE["red"] + + if self.options.reverse_colors: + colors.reverse() + # Cache the list of colours for later use + self._colors = colors + self._color_index = 0 + + color = self._colors[self._color_index] + # Increase index to the next available color + self._color_index = (self._color_index + 1) % len(self._colors) + return color + + def generate(self): + """Generates a nice looking chart into SVG document.""" + + # Process the data from a file or text box + (self.title, keys, values) = self.get_data() + if not values: + raise inkex.AbortExtension(_("No data to render into a chart.")) + + # Get the page attributes: + self.width = self.svg.unittouu(self.svg.get("width")) + self.height = self.svg.unittouu(self.svg.attrib["height"]) + self.fontoff = float(self.options.font_size) / 3 + + # Check if a drop shadow should be drawn: + self.blur = self.get_blur() + + # Draw the right type of chart + for elem in self.options.type(keys, values): + yield elem + + def draw_header(self, heading_x): + """Draw an optional header text""" + if self.options.headings and self.title: + headingtext = self.draw_text(self.title, 4, anchor="end") + headingtext.set("y", str(self.height / 2 + self.options.heading_offset)) + headingtext.set("x", str(heading_x)) + return headingtext + return None + + def render_bar(self, keys, values): + """Draw bar chart""" + bar_height = self.options.bar_height + bar_width = self.options.bar_width + bar_offset = self.options.bar_offset + + # Normalize the bars to the largest value + value_max = max(list(values) + [0.0]) + + # Draw Single bars with their shadows + for cnt, value in enumerate(values): + # Draw each bar a set amount offset + offset = cnt * (bar_width + bar_offset) + bar_value = (value / value_max) * bar_height + + # Calculate the location of the bar + x = self.width / 2 + offset + y = self.height / 2 - int(bar_value) + width = bar_width + height = int(bar_value) + + if self.options.rotate: + # Rotate the bar and align to the left + x, y, width, height = y, x, height, width + x += width + + for elem in self.draw_rectangle(x, y, width, height): + yield elem + + # If keys are given, create text elements + if keys: + text = self.draw_text(keys[cnt], anchor="end") + if not self.options.rotate: # =vertical + text.set("transform", "rotate(-90)") + # y after rotation: + text.set("x", "-" + str(self.height / 2 + self.options.text_offset)) + # x after rotation: + text.set( + "y", str(self.width / 2 + offset + bar_width / 2 + self.fontoff) + ) + else: # =horizontal + text.set( + "y", str(self.width / 2 + offset + bar_width / 2 + self.fontoff) + ) + text.set("x", str(self.height / 2 - self.options.text_offset)) + + yield text + + if self.options.show_values: + vtext = self.draw_text(int(value)) + if not self.options.rotate: # =vertical + vtext.set("transform", "rotate(-90)") + # y after rotation: + vtext.set( + "x", + "-" + str(self.height / 2 + value - self.options.text_offset), + ) + # x after rotation: + vtext.set( + "y", str(self.width / 2 + offset + bar_width / 2 + self.fontoff) + ) + else: # =horizontal + vtext.set( + "y", str(self.width / 2 + offset + bar_width / 2 + self.fontoff) + ) + vtext.set( + "x", str(self.height / 2 + value + self.options.text_offset) + ) + yield vtext + + yield self.draw_header(self.width / 2) + + def draw_rectangle(self, x, y, width, height): + """Draw a rectangle bar with optional shadow""" + if self.blur: + shadow = Rectangle( + x=str(x + 1), y=str(y + 1), width=str(width), height=str(height) + ) + shadow.style = self.blur + yield shadow + + rect = Rectangle(x=str(x), y=str(y), width=str(width), height=str(height)) + rect.set("style", "fill:" + self.get_color()) + yield rect + + def draw_text(self, text, add_size=0, anchor="start", **kwargs): + """Draw a textual label""" + vtext = TextElement(**kwargs) + vtext.style = { + "fill": self.options.font_color, + "font-family": self.options.font, + "font-size": str(self.options.font_size + add_size) + "px", + "font-style": "normal", + "font-variant": "normal", + "font-weight": "normal", + "font-stretch": "normal", + "-inkscape-font-specification": "Bitstream Charter", + "text-align": anchor, + "text-anchor": anchor, + } + vtext.text = str(text) + return vtext + + def render_pie_abs(self, keys, values): + """Draw a pie chart, with absolute values""" + # pie_abs = True + for elem in self.render_pie(keys, values, True): + yield elem + + def render_pie(self, keys, values, pie_abs=False): + """Draw pie chart""" + pie_radius = self.options.pie_radius + + # Iterate all values to draw the different slices + color = 0 + x = float(self.width) / 2 + y = float(self.height) / 2 + + # Create the shadow first (if it should be created): + if self.blur: + shadow = Circle(cx=str(x), cy=str(y)) + shadow.set("r", str(pie_radius)) + shadow.style = self.blur + inkex.Style(fill="#000000") + yield shadow + + # Add a grey background circle with a light stroke + background = Circle(cx=str(x), cy=str(y)) + background.set("r", str(pie_radius)) + background.set("style", "stroke:#ececec;fill:#f9f9f9") + yield background + + # create value sum in order to divide the slices + try: + valuesum = sum(values) + except ValueError: + valuesum = 0 + + if pie_abs: + valuesum = 100 + + # Set an offsetangle + offset = 0 + + # Draw single slices + for cnt, value in enumerate(values): + # Calculate the PI-angles for start and end + angle = (2 * 3.141592) / valuesum * float(value) + start = offset + end = offset + angle + + # proper overlapping + if self.options.segment_overlap: + if cnt != len(values) - 1: + end += 0.09 # add a 5° overlap + if cnt == 0: + start -= ( + 0.09 # let the first element overlap into the other direction + ) + + # then add the slice + pieslice = inkex.PathElement.arc( + [x, y], pie_radius, pie_radius, start=start, end=end + ) + pieslice.set( + "style", "fill:" + self.get_color() + ";stroke:none;fill-opacity:1" + ) + ang = angle / 2 + offset + + # If text is given, draw short paths and add the text + if keys: + elem = inkex.PathElement() + elem.path = [ + Move( + (self.width / 2) + pie_radius * math.cos(ang), + (self.height / 2) + pie_radius * math.sin(ang), + ), + line( + (self.options.text_offset - 2) * math.cos(ang), + (self.options.text_offset - 2) * math.sin(ang), + ), + ] + + elem.style = { + "fill": "none", + "stroke": self.options.font_color, + "stroke-width": self.options.stroke_width, + "stroke-linecap": "butt", + } + yield elem + + label = keys[cnt] + if self.options.show_values: + label += " ({}{})".format(str(value), ("", "%")[pie_abs]) + + # check if it is right or left of the Pie + anchor = "start" if math.cos(ang) > 0 else "end" + text = self.draw_text(label, anchor=anchor) + + off = pie_radius + self.options.text_offset + text.set("x", (self.width / 2) + off * math.cos(ang)) + text.set("y", (self.height / 2) + off * math.sin(ang) + self.fontoff) + yield text + + # increase the rotation-offset and the colorcycle-position + offset = offset + angle + color = (color + 1) % 8 + + # append the objects to the extension-layer + yield pieslice + + yield self.draw_header(self.width / 2 - pie_radius) + + def render_stbar(self, keys, values): + """Draw stacked bar chart""" + + # Iterate over all values to draw the different slices + color = 0 + + # create value sum in order to divide the bars + try: + valuesum = sum(values) + except ValueError: + valuesum = 0.0 + + # Init offset + offset = 0 + width = self.options.bar_width + height = self.options.bar_height + x = self.width / 2 + y = self.height / 2 + + if self.blur: + if self.options.rotate: + width, height = height, width + shy = y + else: + shy = str(y - self.options.bar_height) + + # Create rectangle element + shadow = Rectangle( + x=str(x), + y=str(shy), + width=str(width), + height=str(height), + ) + + # Set shadow blur (connect to filter object in xml path) + shadow.style = self.blur + yield shadow + + # Draw Single bars + for cnt, value in enumerate(values): + + # Calculate the individual heights normalized on 100units + normedvalue = (self.options.bar_height / valuesum) * float(value) + + # Create rectangle element + rect = Rectangle() + + # Set chart position to center of document. + if not self.options.rotate: + rect.set("x", str(self.width / 2)) + rect.set("y", str(self.height / 2 - offset - normedvalue)) + rect.set("width", str(self.options.bar_width)) + rect.set("height", str(normedvalue)) + else: + rect.set("x", str(self.width / 2 + offset)) + rect.set("y", str(self.height / 2)) + rect.set("height", str(self.options.bar_width)) + rect.set("width", str(normedvalue)) + + rect.set("style", "fill:" + self.get_color()) + + # If text is given, draw short paths and add the text + # TODO: apply overlap workaround for visible gaps in between + if keys: + if not self.options.rotate: + x1 = (self.width + self.options.bar_width) / 2 + y1 = y - offset - (normedvalue / 2) + x2 = self.options.bar_width / 2 + self.options.text_offset + y2 = 0 + txt = ( + self.width / 2 + + self.options.bar_width + + self.options.text_offset + + 1 + ) + tyt = y - offset + self.fontoff - (normedvalue / 2) + else: + x1 = x + offset + normedvalue / 2 + y1 = y + self.options.bar_width / 2 + x2 = 0 + y2 = ( + self.options.bar_width / 2 + + (self.options.font_size * cnt) + + self.options.text_offset + ) + txt = x + offset + normedvalue / 2 - self.fontoff + tyt = ( + (y) + + self.options.bar_width + + (self.options.font_size * (cnt + 1)) + + self.options.text_offset + ) + + elem = inkex.PathElement() + elem.path = [Move(x1, y1), line(x2, y2)] + elem.style = { + "fill": "none", + "stroke": self.options.font_color, + "stroke-width": self.options.stroke_width, + "stroke-linecap": "butt", + } + yield elem + yield self.draw_text(keys[cnt], x=str(txt), y=str(tyt)) + + # Increase Offset and Color + offset = offset + normedvalue + color = (color + 1) % 8 + + # Draw rectangle + yield rect + + yield self.draw_header(self.width / 2 + offset + normedvalue) + + +if __name__ == "__main__": + NiceChart().run() diff --git a/share/extensions/other/clipart/LICENSE.txt b/share/extensions/other/clipart/LICENSE.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/share/extensions/other/clipart/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/share/extensions/other/clipart/MANIFEST.in b/share/extensions/other/clipart/MANIFEST.in new file mode 100644 index 0000000..c1201be --- /dev/null +++ b/share/extensions/other/clipart/MANIFEST.in @@ -0,0 +1,9 @@ +include import_web_image.ui +include import_web_image.py +include import_web_image.inx +include import_web_image.svg +include import_sources.py +include README.md +include LICENSE.txt +include sources/*.py +include sources/*.svg diff --git a/share/extensions/other/clipart/README.md b/share/extensions/other/clipart/README.md new file mode 100644 index 0000000..5443006 --- /dev/null +++ b/share/extensions/other/clipart/README.md @@ -0,0 +1,12 @@ +# Import Web Image (inkscape extension) + +This Inkscape extension allows inkscape users to import graphics into Inkscape from a selection of internet sources. + +It is a graphical user interface which allows the searching for, and selection of both svg and raster images and these are then inserted into the current document. + +# Sources + +New sources can be added at any time. They should include an icon, and a python file with the same name and should allow the user to search and download resources from the target website or platform. + +Please see existing python files for examples. + diff --git a/share/extensions/other/clipart/import_sources.py b/share/extensions/other/clipart/import_sources.py new file mode 100644 index 0000000..d98aab3 --- /dev/null +++ b/share/extensions/other/clipart/import_sources.py @@ -0,0 +1,272 @@ +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# +# 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 3 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, see +# +""" +Base module for all import web search source modules. +""" + +import re +import os +import sys +import logging +import requests +import importlib + +from cachecontrol import CacheControl, CacheControlAdapter +from cachecontrol.caches.file_cache import FileCache +from cachecontrol.heuristics import ExpiresAfter + +from inkex.command import CommandNotFound, ProgramRunError, call +from collections import defaultdict + +LICENSE_ICONS = os.path.join(os.path.dirname(__file__), 'licenses') + +LICENSES = { + "cc-0": { + "name": "CC0", + "modules": ["nocopyright"], + "url": "https://creativecommons.org/publicdomain/zero/1.0/", + "overlay": "cc0.svg", + }, + "cc-by-3.0": { + "name": "CC-BY 3.0 Unported", + "modules": ["by"], + "url": "https://creativecommons.org/licenses/by/3.0/", + "overlay": "cc-by.svg", + }, + "cc-by-4.0": { + "name": "CC-BY 4.0 Unported", + "modules": ["by"], + "url": "https://creativecommons.org/licenses/by/4.0/", + "overlay": "cc-by.svg", + }, + "cc-by-sa-4.0": { + "name": "CC-BY SA 4.0", + "modules": ["by", "sa"], + "url": "https://creativecommons.org/licenses/by-sa/4.0/", + "overlay": "cc-by-sa.svg", + }, + "cc-by-sa-3.0": { + "name": "CC-BY SA 3.0", + "modules": ["by", "sa"], + "url": "https://creativecommons.org/licenses/by-sa/3.0/", + "overlay": "cc-by-sa.svg", + }, + "cc-by-nc-sa-4.0": { + "name": "CC-BY NC SA 4.0", + "modules": ["by", "sa", "nc"], + "url": "https://creativecommons.org/licenses/by-nc-sa/4.0/", + "overlay": "cc-by-nc-sa.svg", + }, + "cc-by-nc-sa-3.0": { + "name": "CC-BY NC SA 3.0", + "modules": ["by", "sa", "nc"], + "url": "https://creativecommons.org/licenses/by-nc-sa/3.0/", + "overlay": "cc-by-nc-sa.svg", + }, + "cc-by-nc-3.0": { + "name": "CC-BY NC 3.0", + "modules": ["by", "nc"], + "url": "https://creativecommons.org/licenses/by-nc/3.0/", + "overlay": "cc-by-nc.svg", + }, + "cc-by-nd-3.0": { + "name": "CC-BY ND 3.0", + "modules": ["by", "nd"], + "url": "https://creativecommons.org/licenses/by-nd/3.0/", + "overlay": "cc-by-nd.svg", + }, + "gpl-2": { + "name": "GPLv2", + "modules": ["retaincopyrightnotice", "sa"], + "url": "https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt", + "overlay": "gpl.svg", + }, + "gpl-3": { + "name": "GPLv3", + "modules": ["retaincopyrightnotice", "sa"], + "url": "https://www.gnu.org/licenses/gpl-3.0.txt", + "overlay": "gpl.svg", + }, + "agpl-3": { + "name": "AGPLv3", + "modules": ["retaincopyrightnotice", "sa"], + "url": "https://www.gnu.org/licenses/agpl-3.0.txt", + "overlay": "gpl.svg", + }, + "mit": { + "name": "MIT", + "modules": ["retaincopyrightnotice"], + "url": "https://mit-license.org/", + "overlay": "mit.svg", + }, + "asl": { + "name": "Apache License", + "modules": ["retaincopyrightnotice"], + "url": "https://www.apache.org/licenses/LICENSE-2.0.txt", + "overlay": "asl.svg", + }, + "bsd": { + "name": "BSD", + "modules": ["retaincopyrightnotice", "noendorsement"], + "url": "https://opensource.org/licenses/BSD-3-Clause", + "overlay": "bsd.svg", + }, +} + + +class RemotePage: + """Lazy access to paging systems""" + + icon = "sources/next_page.svg" + string = property(lambda self: "Next Page") + + def __init__(self, remote, func): + self.func = func + self.remote = remote + + def get_next_page(self): + for info in self.func(): + yield self.remote.result_to_cls(info) + + +class RemoteFile: + """Lazy access to remote files""" + + icon = property(lambda self: self.remote.to_local_file(self.info["thumbnail"])) + get_file = lambda self: self.remote.to_local_file(self.info["file"]) + + def __init__(self, remote, info): + for field in ("name", "thumbnail", "license", "file"): + if field not in info: + raise ValueError(f"Field {field} not provided in RemoteFile package") + self.info = info + self.remote = remote + + @property + def string(self): + return self.info["name"] + + @property + def license(self): + return self.info["license"] + + def get_overlay(self): + return self.license_info["overlay"] + + @property + def license_info(self): + return LICENSES.get(self.license, { + "name": "Unknown", + "url": self.info.get("descriptionurl", ""), + "modules": [], + "overlay": "unknown.svg", + }) + + @property + def author(self): + return self.info["author"] + + +class RemoteSource: + """A remote source of svg images which can be searched and downloaded""" + + # These are the properties that should be overridden in your class + name = None + icon = None + file_cls = RemoteFile + page_cls = RemotePage + is_default = False + is_enabled = True + + @classmethod + def load(cls, name): + """Load the file or directory of remote sources""" + if os.path.isfile(name): + sys.path, sys_path = [os.path.dirname(name)] + sys.path, sys.path + try: + importlib.import_module(os.path.basename(name).rsplit(".", 1)[0]) + except ImportError: + logging.error(f"Failed to load module: {name}") + sys.path = sys_path + elif os.path.isdir(name): + for child in os.listdir(name): + if not child.startswith("_") and child.endswith(".py"): + cls.load(os.path.join(name, child)) + + def search(self, query, tags=[]): + """ + Search for the given query and yield basic informational blocks t hand to file_cls. + + Required fields per yielded object are: name, license, thumbnail and file. + Optional fields are: id, summary, author, created, popularity + """ + raise NotImplementedError( + "You must implement a search function for this remote source!" + ) + + sources = {} + + def __init_subclass__(cls): + if cls != RemoteSource: + cls.sources[cls.__name__] = cls + + def __init__(self, cache_dir): + self.session = requests.session() + self.cache_dir = cache_dir + self.session.mount( + "https://", + CacheControlAdapter( + cache=FileCache(cache_dir), + heuristic=ExpiresAfter(days=5), + ), + ) + + def __del__(self): + self.session.close() + + def file_search(self, query): + """Search for extension packages""" + for info in self.search(query): + yield self.result_to_cls(info) + + def result_to_cls(self, info): + if callable(info): + return self.page_cls(self, info) + return self.file_cls(self, info) + + def to_local_file(self, url): + """Get a remote url and turn it into a local file""" + filepath = os.path.join(self.cache_dir, url.split("/")[-1]) + headers = {"User-Agent": "Inkscape"} + try: + remote = self.session.get( + url, headers=headers + ) # needs UserAgent otherwise many 403 or 429 for wiki commons + except requests.exceptions.RequestException as err: + return None + except ConnectionError as err: + return None + except requests.exceptions.RequestsWarning: + pass + + if remote and remote.status_code == 200: + with open(filepath, "wb") as fhl: + # If we don't have data, return None (instead of empty file) + if fhl.write(remote.content): + return filepath + return None diff --git a/share/extensions/other/clipart/import_web_image.inx b/share/extensions/other/clipart/import_web_image.inx new file mode 100644 index 0000000..53bea25 --- /dev/null +++ b/share/extensions/other/clipart/import_web_image.inx @@ -0,0 +1,12 @@ + + + Import Web Image... + org.inkscape.import_web_image + + all + + + + diff --git a/share/extensions/other/clipart/import_web_image.py b/share/extensions/other/clipart/import_web_image.py new file mode 100755 index 0000000..5c8c8d8 --- /dev/null +++ b/share/extensions/other/clipart/import_web_image.py @@ -0,0 +1,395 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# +# 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 3 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, see +# +""" +Import images from the internet, inkscape extension (GUI) +""" + +__version__ = '1.0' +__pkgname__ = 'inkscape-import-web-image' + +import os +import sys +import logging +import warnings +warnings.filterwarnings("ignore") + +from collections import defaultdict +from base64 import encodebytes +from appdirs import user_cache_dir + +import inkex +from inkex import Style +from inkex.gui import GtkApp, Window, IconView, asyncme +from inkex.gui.pixmap import PixmapManager, SizeFilter, PadFilter, OverlayFilter +from inkex.elements import ( + load_svg, Image, Defs, NamedView, Metadata, + SvgDocumentElement, StyleElement +) +from gi.repository import Gtk + +from import_sources import RemoteSource, RemoteFile, RemotePage + +SOURCES = os.path.join(os.path.dirname(__file__), 'sources') +LICENSES = os.path.join(os.path.dirname(__file__), 'licenses') +CACHE_DIR = user_cache_dir('inkscape-import-web-image', 'Inkscape') + +class LicenseOverlay(OverlayFilter): + pixmaps = PixmapManager(LICENSES) + + def get_overlay(self, item=None, manager=None): + if item is None: # Default image + return None + return self.pixmaps.get(item.get_overlay()) + + +class ResultsIconView(IconView): + """The search results shown as icons""" + def get_markup(self, item): + return item.string + + def get_icon(self, item): + return item.icon + + def setup(self): + self._list.set_markup_column(1) + self._list.set_pixbuf_column(2) + crt, crp = self._list.get_cells() + self.crt_notify = crt.connect('notify', self.keep_size) + super().setup() + + def keep_size(self, crt, *args): + """Hack Gtk to keep cells smaller""" + crt.handler_block(self.crt_notify) + crt.set_property('width', 150) + crt.handler_unblock(self.crt_notify) + + +class ImporterWindow(Window): + """The window that is in the glade file""" + name = 'import_web_image' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.widget('dl-searching').hide() + + # Add each of the source services from their plug-in modules + self.source = self.widget('service_list') + self.source_model = self.source.get_model() + self.source_model.clear() + + RemoteSource.load(SOURCES) + pix = PixmapManager(SOURCES, size=150) + for x, (key, source) in enumerate(RemoteSource.sources.items()): + if not source.is_enabled: + continue + # We add them in GdkPixbuf, string, string format (see glade file) + self.source_model.append([pix.get(source.icon), source.name, key]) + if source.is_default: + self.source.set_active(x) + + pixmaps = PixmapManager(CACHE_DIR, filters=[ + SizeFilter(size=150), + PadFilter(size=(0, 150)), + LicenseOverlay(position=(0.5, 1)) + ]) + self.select_func = self.gapp.kwargs['select'] + self.results = ResultsIconView(self.widget('results'), pixmaps) + self.pool = ResultsIconView(self.widget('pool'), pixmaps) + self.multiple = False + + self.widget("perm-nocopyright").set_message_type(Gtk.MessageType.WARNING) + + def select_image(self, widget): + """Callback when clicking on an image in the result list""" + for item_path in self.widget("results").get_selected_items(): + item_iter = self.results._model.get_iter(item_path) + item = self.results._model[item_iter][0] + self.show_license(item) + self.update_btn_import() + + def show_license(self, item): + """Display the current item's license information""" + self.widget("perms").foreach(lambda w: w.hide()) + info = item.license_info + for mod in info['modules']: + self.widget("perm-" + mod).show() + + def get_selected_source(self): + """Return the selected source class""" + _iter = self.source.get_active_iter() + key = self.source_model[_iter][2] + return RemoteSource.sources[key](CACHE_DIR) + + def img_multiple(self, widget): + """Enable multi-selection""" + widget.hide() + self.widget('btn-single').show() + self.widget('multiple-box').show() + self.widget('multiple-buttons').show() + self.multiple = True + self.update_btn_import() + + def img_single(self, widget): + """Enable single-selection""" + widget.hide() + self.widget('btn-multiple').show() + self.widget('multiple-box').hide() + self.widget('multiple-buttons').hide() + is_selected = bool(list(self.results.get_selected_items())) + self.pool.clear() + self.multiple = False + self.update_btn_import() + + def img_add(self, widget=None): + """Add an item from the search to the multi-pool""" + self.pool.add(self.results.get_selected_items()) + self.update_btn_import() + + def img_remove(self, widget=None): + """Remove any selected items from the multi-pool""" + for item in self.pool.get_selected_items(): + self.pool.remove_item(item) + self.update_btn_import() + + def update_btn_import(self): + """Set the import button to enabled or disabled""" + enabled = False + if self.multiple: + enabled = bool(list(self.pool)) + else: + enabled = bool(list(self.results.get_selected_items())) + self.widget('btn-import').set_sensitive(enabled) + + def result_activate(self, widget=None): + """Search results double click""" + if self.multiple: + self.img_add() + else: + self.img_import() + + def img_import(self, widget=None): + """Apply the selected image and quit""" + items = [] + if not self.multiple: + items.extend(self.results.get_selected_items()) + else: + items.extend([item for item,*_ in self.pool]) + + to_exit = True + for item in items: + self.select_func(item.get_file()) + # XXX This pagination control is not good. Replace it with normal controls. + #elif isinstance(item, RemotePage): + if to_exit: + self.exit() + + def search(self, widget): + """Remote search activation""" + query = widget.get_text() + if len(query) > 2: + self.search_clear() + self.search_started() + self.async_search(query) + + @asyncme.run_or_none + def async_search(self, query): + """Asyncronous searching in PyPI""" + for resource in self.get_selected_source().file_search(query): + self.add_search_result(resource) + self.search_finished() + + @asyncme.mainloop_only + def add_search_result(self, resource): + """Adding things to Gtk must be done in mainloop""" + if isinstance(resource, RemotePage): + return self.set_next_page(resource) + + self.results.add_item(resource) + + def search_clear(self, widget=None): + """Remove previous search""" + self.results.clear() + self.update_btn_import() + self.next_page_item = None + self.widget('btn-next-page').hide() + + def search_started(self): + """Set widgets to stun""" + self.widget('dl-search').set_sensitive(False) + self.widget('dl-searching').start() + self.widget('dl-searching').show() + + @asyncme.mainloop_only + def search_finished(self): + """After everything, finish the search""" + self.widget('dl-search').set_sensitive(True) + self.widget('dl-searching').hide() + self.widget('dl-searching').stop() + + def set_next_page(self, item): + self.next_page_item = item + self.widget('btn-next-page').show() + + def show_next_page(self, widget=None): + item = self.next_page_item + if item: + self.search_clear() + self.search_started() + self.async_next_page(item) + + @asyncme.run_or_none + def async_next_page(self, item): + for resource in item.get_next_page(): + self.add_search_result(resource) + self.search_finished() + + +class App(GtkApp): + """Load the inkscape extensions glade file and attach to window""" + glade_dir = os.path.join(os.path.dirname(__file__)) + app_name = 'inkscape-import-web-image' + windows = [ImporterWindow] + +class ImportWebImage(inkex.EffectExtension): + """Import an svg from the internet""" + selected_filename = None + + def merge_defs(self, defs): + """Add all the items in defs to the self.svg.defs""" + target = self.svg.defs + for child in defs: + if isinstance(child, StyleElement): + continue # Already appled in merge_stylesheets() + target.append(child) + + def merge_stylesheets(self, svg): + """Because we don't want conflicting style-sheets (classes, ids, etc) we scrub them""" + elems = defaultdict(list) + # 1. Find all styles, and all elements that apply to them + for sheet in svg.getroot().stylesheets: + for style in sheet: + xpath = style.to_xpath() + for elem in svg.xpath(xpath): + elems[elem].append(style) + # 1b. Clear possibly conflicting attributes + if '@id' in xpath: + elem.set_random_id() + if '@class' in xpath: + elem.set('class', None) + # 2. Apply each style cascade sequentially + for elem, styles in elems.items(): + output = Style() + for style in styles: + output += style + elem.style = output + elem.style + + def import_svg(self, new_svg): + """Import an svg file into the current document""" + self.merge_stylesheets(new_svg) + for child in new_svg.getroot(): + if isinstance(child, SvgDocumentElement): + yield from self.import_svg(child) + elif isinstance(child, StyleElement): + continue # Already applied in merge_stylesheets() + elif isinstance(child, Defs): + self.merge_defs(child) + elif isinstance(child, (NamedView, Metadata)): + pass + else: + yield child + + def import_from_file(self, filename): + if not filename or not os.path.isfile(filename): + return + with open(filename, 'rb') as fhl: + head = fhl.read(100) + if b' + + Import Web Image Icon + + + + + + + + + + + + + + + image/svg+xml + + + Import Web Image Icon + + + Olibia Tsati + + + https://inkscape.org/~olibia/%E2%98%85inkscape-about-screen+6 + 2019-10-25 + + + Inkscape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/import_web_image.ui b/share/extensions/other/clipart/import_web_image.ui new file mode 100644 index 0000000..8d5b681 --- /dev/null +++ b/share/extensions/other/clipart/import_web_image.ui @@ -0,0 +1,934 @@ + + + + + + + + + + True + False + gtk-remove + + + True + False + gtk-cancel + + + True + False + gtk-go-down + + + True + False + gtk-add + + + True + False + gtk-apply + + + True + False + gtk-go-up + + + True + False + gtk-go-forward + + + + + + + + + + + + + import_web_image.svg + Test Icon + key + + + + + False + Import Web Image + center + 600 + 600 + import_web_image.svg + + + True + False + vertical + + + True + False + 4 + 4 + + + searcher + True + False + + 4 + 4 + + + False + True + 6 + 0 + + + + + True + True + center + edit-find-symbolic + False + False + + + + True + True + 1 + + + + + Next Page + True + True + start + center + 10 + image7 + right + True + + + + + False + True + 2 + + + + + True + False + 6 + service_items + 2 + + + + 48 + 48 + 3 + + + 0 + + + + + 8 + + + 1 + + + + + False + True + 3 + + + + + False + False + 4 + 0 + + + + + True + True + in + + + True + True + 6 + + + + + + + True + True + 1 + + + + + True + False + 4 + 4 + 4 + 4 + 2 + + + Import + True + True + True + image5 + True + + + + + True + True + 3 + True + + + + + Cancel + True + True + True + image2 + True + + + + + True + True + 0 + + + + + Multiple Images + True + True + True + image6 + none + True + + + + + True + True + 1 + True + + + + + Single Image + True + True + image3 + none + True + + + + + True + True + 2 + True + + + + + False + True + end + 1 + + + + + True + in + + + True + True + 6 + + + + + True + True + end + 3 + + + + + False + 4 + 4 + 4 + 4 + 2 + bottom + center + + + Remove + True + True + True + image1 + True + + + + + True + True + 0 + + + + + Add + True + True + True + image4 + True + + + + + True + True + 1 + + + + + False + True + end + 4 + + + + + + license_info + True + False + 4 + 3 + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-pd.svg + 6 + + + False + True + 0 + + + + + True + False + Public domain, no attribution or credit necessary. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 0 + 2 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-sa.svg + 6 + + + False + True + 0 + + + + + True + False + Any modifications must also be licensed under the same or a compatible license. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 2 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-nc.svg + 6 + + + False + True + 0 + + + + + True + False + Do not use the material for commercial purposes. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 3 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-nd.svg + 6 + + + False + True + 0 + + + + + True + False + If you remix, transform, or build upon the material, you may not distribute the modified material. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 4 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-ne.svg + 6 + + + False + True + 0 + + + + + True + False + Do not promote or endorse products using the name of the copyright holder. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 5 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-notice.svg + 6 + + + False + True + 0 + + + + + True + False + Include COPYRIGHT YEAR AUTHORNAME and include the software license file. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 6 + + + + + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + licenses/perm-by.svg + 6 + + + False + True + 0 + + + + + True + False + Give credit in the figure caption or acknowledgements, link the license and indicate changes. Do not suggest endorsement. + True + 0 + + + False + True + 1 + + + + + + + + False + False + 0 + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + False + True + 5 + + + + + + diff --git a/share/extensions/other/clipart/import_web_image_cli.py b/share/extensions/other/clipart/import_web_image_cli.py new file mode 100755 index 0000000..7b073cc --- /dev/null +++ b/share/extensions/other/clipart/import_web_image_cli.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +""" +Testing tool for running queries. +""" + +import sys +import json + +from import_sources import RemoteSource + +def run(): + RemoteSource.load('sources') + source = RemoteSource.sources[sys.argv[1]]('/tmp') + + for item in source.search(sys.argv[2]): + if callable(item): + print(f"Next Page {item}") + else: + print(json.dumps(item, indent=2)) + +if __name__ == '__main__': + run() diff --git a/share/extensions/other/clipart/licenses/asl.svg b/share/extensions/other/clipart/licenses/asl.svg new file mode 100644 index 0000000..a44a3ab --- /dev/null +++ b/share/extensions/other/clipart/licenses/asl.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/bsd.svg b/share/extensions/other/clipart/licenses/bsd.svg new file mode 100644 index 0000000..dbad70c --- /dev/null +++ b/share/extensions/other/clipart/licenses/bsd.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg b/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg new file mode 100644 index 0000000..2f20ee7 --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc-by-nc.svg b/share/extensions/other/clipart/licenses/cc-by-nc.svg new file mode 100644 index 0000000..80dd1f6 --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc-by-nc.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc-by-nd.svg b/share/extensions/other/clipart/licenses/cc-by-nd.svg new file mode 100644 index 0000000..ec255e6 --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc-by-nd.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc-by-sa.png b/share/extensions/other/clipart/licenses/cc-by-sa.png new file mode 100644 index 0000000..5dea2be Binary files /dev/null and b/share/extensions/other/clipart/licenses/cc-by-sa.png differ diff --git a/share/extensions/other/clipart/licenses/cc-by-sa.svg b/share/extensions/other/clipart/licenses/cc-by-sa.svg new file mode 100644 index 0000000..320531d --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc-by-sa.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc-by.svg b/share/extensions/other/clipart/licenses/cc-by.svg new file mode 100644 index 0000000..bec1d6c --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc-by.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/cc0.svg b/share/extensions/other/clipart/licenses/cc0.svg new file mode 100644 index 0000000..a0fafc4 --- /dev/null +++ b/share/extensions/other/clipart/licenses/cc0.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/gpl.svg b/share/extensions/other/clipart/licenses/gpl.svg new file mode 100644 index 0000000..1f9f083 --- /dev/null +++ b/share/extensions/other/clipart/licenses/gpl.svg @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/mit.svg b/share/extensions/other/clipart/licenses/mit.svg new file mode 100644 index 0000000..5f6c855 --- /dev/null +++ b/share/extensions/other/clipart/licenses/mit.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-by.svg b/share/extensions/other/clipart/licenses/perm-by.svg new file mode 100644 index 0000000..b474dd4 --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-by.svg @@ -0,0 +1,93 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-nc.svg b/share/extensions/other/clipart/licenses/perm-nc.svg new file mode 100644 index 0000000..3bca9e2 --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-nc.svg @@ -0,0 +1,100 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-nd.svg b/share/extensions/other/clipart/licenses/perm-nd.svg new file mode 100644 index 0000000..aa89ad2 --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-nd.svg @@ -0,0 +1,92 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-ne.svg b/share/extensions/other/clipart/licenses/perm-ne.svg new file mode 100644 index 0000000..5d16f83 --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-ne.svg @@ -0,0 +1,90 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-notice.svg b/share/extensions/other/clipart/licenses/perm-notice.svg new file mode 100644 index 0000000..55043a9 --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-notice.svg @@ -0,0 +1,82 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-pd.svg b/share/extensions/other/clipart/licenses/perm-pd.svg new file mode 100644 index 0000000..e8e25ce --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-pd.svg @@ -0,0 +1,87 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/perm-sa.svg b/share/extensions/other/clipart/licenses/perm-sa.svg new file mode 100644 index 0000000..c5a308c --- /dev/null +++ b/share/extensions/other/clipart/licenses/perm-sa.svg @@ -0,0 +1,84 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/licenses/unknown.svg b/share/extensions/other/clipart/licenses/unknown.svg new file mode 100644 index 0000000..2a96487 --- /dev/null +++ b/share/extensions/other/clipart/licenses/unknown.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + ? + + + diff --git a/share/extensions/other/clipart/pyproject.toml b/share/extensions/other/clipart/pyproject.toml new file mode 100644 index 0000000..fd36dc6 --- /dev/null +++ b/share/extensions/other/clipart/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "import-web-image" +version = "1.0.0" +description = "A GTK3 based web image importer." +authors = ["Martin Owens "] +maintainers = ["Martin Owens "] +license = "GPL-3.0-or-later" + +# The dependencies below are NOT used for packaging, they are abstract. +# They are merely for packagers' convenience and are used in CI for extensions. +[tool.poetry.dependencies] +python = ">=3.7" +appdirs = "1.4.4" +requests = "*" +CacheControl = {extras = ["filecache"], version = "*"} + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/share/extensions/other/clipart/sources/bioicons.py b/share/extensions/other/clipart/sources/bioicons.py new file mode 100644 index 0000000..232f024 --- /dev/null +++ b/share/extensions/other/clipart/sources/bioicons.py @@ -0,0 +1,97 @@ +# +# Copyright 2022 Simon Duerr dev@simonduerr.eu +# +# 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 3 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, see +# +""" +Access Bioicons. + +Downloads the database to cache and uses it locally for searching. +""" + +import json +import requests +from datetime import datetime +import os + + +from cachecontrol import CacheControl, CacheControlAdapter +from cachecontrol.caches.file_cache import FileCache +from cachecontrol.heuristics import ExpiresAfter + +from import_sources import RemoteSource + + +def local_search(query, db): + for item in db: + if query.lower() in item["name"].lower(): + yield item + return + + +class Bioicons(RemoteSource): + name = "Bioicons" + icon = "sources/bioicons.svg" + db_url = "https://bioicons.com/icons/icons.json" + icon_url = "https://bioicons.com/icons/" + + def __init__(self, cache_dir): + self.session = requests.session() + self.cache_dir = cache_dir + self.session.mount( + "https://", + CacheControlAdapter( + cache=FileCache(cache_dir), + heuristic=ExpiresAfter(days=5), + ), + ) + # check if local db is up to date with Last Modified header + try: + response = requests.head(self.db_url) + except Exception: + response = None + + self._json = os.path.join(self.cache_dir, "icons.json") + if not os.path.isfile(self._json): + last_modified = 0 + else: + last_modified = os.path.getmtime(self._json) + + if response is not None: + last_update = datetime.strptime( + response.headers["Last-Modified"], "%a, %d %b %Y %H:%M:%S GMT" + ).timestamp() + # if icon db was modified download new database + if last_modified < last_update: + self.to_local_file(self.db_url) + + def search(self, query): + results = [] + if os.path.isfile(self._json): + with open(self._json, "r") as f: + db = json.load(f) + results = local_search(query, db) + + for item in results: + yield { + "id": item["name"], + "name": item["name"], + "summary": item["category"], + "created": None, + "popularity": 0, + "author": item["author"], + "thumbnail": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg", + "file": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg", + "license": item["license"], + } diff --git a/share/extensions/other/clipart/sources/bioicons.svg b/share/extensions/other/clipart/sources/bioicons.svg new file mode 100644 index 0000000..ad9c98c --- /dev/null +++ b/share/extensions/other/clipart/sources/bioicons.svg @@ -0,0 +1,145 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/inkscape-web.py b/share/extensions/other/clipart/sources/inkscape-web.py new file mode 100644 index 0000000..5960c3e --- /dev/null +++ b/share/extensions/other/clipart/sources/inkscape-web.py @@ -0,0 +1,74 @@ +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# 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 3 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, see +# + +from import_sources import RemoteSource + + +license_mapping = { + "PD": "cc-0", + "CC-0": "cc-0", + "CC-BY 3.0": "cc-by-3.0", + "CC-BY 4.0": "cc-by-4.0", + "CC-BY-SA 4.0": "cc-by-sa-4.0", + "CC-BY-NC 3.0": "cc-by-nc-3.0", + "CC-BY-NC-SA 3.0": "cc-by-nc-sa-3.0", + "CC-BY-NC-SA 4.0": "cc-by-nc-sa-4.0", + "CC-BY-SA 3.0": "cc-by-sa-3.0", + "CC-BY-ND 3.0": "cc-by-nd-3.0", + "ASL": "asl", + "nbsd": "bsd", + "GPLv2": "gpl-2", + "GPLv3": "gpl-3", + "AGPLv3": "agpl-3", + "MIT": "mit", +} + + +class InkscapeWebsite(RemoteSource): + name = "Inkscape Community" + icon = "sources/inkscape-web.svg" + is_default = True + + base_url = "https://inkscape.org/gallery/=artwork/json/" + + def search(self, query): + """Ask the inkscape website for some artwork""" + items = [] + try: + response = self.session.get(self.base_url, params={"q": query}) + items = response.json()["items"] + except Exception: + pass + + for item in items: + if "svg" not in item["type"]: + continue + if ( + item["license"] == "(C)" + ): # ignore copyrighted items because they cannot be reused + continue + yield { + "id": item["id"], + "name": item["name"], + "author": item["author"], + "license": license_mapping.get(item["license"], item["license"].lower()), + "summary": item["summary"], + "thumbnail": item["icon"] or item["links"]["file"], + "created": item["dates"]["created"], + "popularity": item["stats"]["liked"], + "file": item["links"]["file"], + } diff --git a/share/extensions/other/clipart/sources/inkscape-web.svg b/share/extensions/other/clipart/sources/inkscape-web.svg new file mode 100644 index 0000000..8e2ec3b --- /dev/null +++ b/share/extensions/other/clipart/sources/inkscape-web.svg @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/ocal.py b/share/extensions/other/clipart/sources/ocal.py new file mode 100644 index 0000000..2fe06db --- /dev/null +++ b/share/extensions/other/clipart/sources/ocal.py @@ -0,0 +1,97 @@ +# +# Copyright 2021 Martin Owens +# +# 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 3 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, see +# + +import sys +import json +import logging + +from import_sources import RemoteSource, RemoteFile +from urllib.parse import urljoin, parse_qs + +try: + from bs4 import BeautifulSoup +except ImportError: + BeautifulSoup = None + + +class OpenClipartFile(RemoteFile): + def get_file(self): + """Extract search result from html""" + response = self.remote.session.get(self.info["file"]) + soup = BeautifulSoup(response.text, features="lxml") + for script in soup.find_all("script"): + content = script.contents + if content and "image" in content[0]: + try: + data = json.loads(content[0]) + return self.remote.to_local_file(data["image"]["url"]) + except Exception: + continue + logging.error("Couldn't load svg from %s", self.info["file"]) + + +class OpenClipart(RemoteSource): + name = "Open Clipart Library" + icon = "sources/ocal.svg" + base_url = "https://openclipart.org/search/" + is_enabled = BeautifulSoup is not None + file_cls = OpenClipartFile + + def html_search(self, response): + """Extract search results from html""" + soup = BeautifulSoup(response.text, features="lxml") + for div in soup.find_all("div", {"class": "artwork"}): + if div.a and div.a.img: + link = urljoin(self.base_url, div.a.get("href")) + img = urljoin(self.base_url, div.a.img.get("src")) + + yield { + "file": link, # Not the actual file yet (see above) + "name": div.a.img.get("alt"), + "thumbnail": img, + "author": "OpenClipart", + "license": "cc-0", + } + + for page in soup.find_all("a", {"class": "page-link", "aria-label": "Next"}): + if "=" in page.get("href", ""): + yield lambda: self._search(**parse_qs(page.get("href").split("?")[-1])) + + def search(self, query): + """HTML searching for now""" + return self._search(query=query) + + def _search(self, **params): + try: + response = self.session.get(self.base_url, params=params) + except Exception: + return [] + + items = [] + next_page = None + for item in self.html_search(response): + if callable(item): + next_page = item + else: + items.append(item) + # Often ocal will have empty pages, weirdly. + if not items and next_page: + return next_page() + # None empty page, return all + if next_page: + items.append(next_page) + return items diff --git a/share/extensions/other/clipart/sources/ocal.svg b/share/extensions/other/clipart/sources/ocal.svg new file mode 100644 index 0000000..44eba39 --- /dev/null +++ b/share/extensions/other/clipart/sources/ocal.svg @@ -0,0 +1,132 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/reactome.py b/share/extensions/other/clipart/sources/reactome.py new file mode 100644 index 0000000..1a1c8b3 --- /dev/null +++ b/share/extensions/other/clipart/sources/reactome.py @@ -0,0 +1,64 @@ +# +# Copyright 2021 Martin Owens +# +# 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 3 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, see +# +""" +Access Reactome Content Services. +""" + +import re + +from import_sources import RemoteSource + +TAG_REX = re.compile(r'<[^<]+?>') + +class Reactome(RemoteSource): + name = 'Reactome (Bio)' + icon = 'sources/reactome.svg' + search_url = "https://reactome.org/ContentService/search/query" + file_url = "https://reactome.org/icon/{stId}.svg" + icon_url = "https://reactome.org/icon/{stId}.png" + all_licence = "cc-by-sa-4.0" + + def search(self, query): + params = { + "query": query, + "types": "Icon", + "cluster": "true", + "Start row": 0, + "rows": 100, + } + response = {} + try: + response = self.session.get(self.search_url, params=params).json() + except Exception: + pass + + if 'messages' in response and 'No entries' in response['messages'][0]: + return + for cats in response.get('results', []): + for entry in cats['entries']: + yield { + 'id': entry['dbId'], + 'name': TAG_REX.sub('', entry['name']), + 'author': 'Reactome/'+entry.get('iconDesignerName', "Unknown"), + 'summary': TAG_REX.sub('', entry.get('summation', '')), + 'created': None, # No data + 'popularity': 0, # No data + 'thumbnail': self.icon_url.format(**entry), + 'file': self.file_url.format(**entry), + 'license': self.all_licence, + } + diff --git a/share/extensions/other/clipart/sources/reactome.svg b/share/extensions/other/clipart/sources/reactome.svg new file mode 100644 index 0000000..3c6562c --- /dev/null +++ b/share/extensions/other/clipart/sources/reactome.svg @@ -0,0 +1,111 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + + + + + + diff --git a/share/extensions/other/clipart/sources/wikimedia.py b/share/extensions/other/clipart/sources/wikimedia.py new file mode 100644 index 0000000..f260bc8 --- /dev/null +++ b/share/extensions/other/clipart/sources/wikimedia.py @@ -0,0 +1,76 @@ +# +# Copyright 2021 Martin Owens +# Copyright 2022 Simon Duerr +# +# 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 3 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, see +# + +import hashlib +from import_sources import RemoteSource + + +class Wikimedia(RemoteSource): + name = "Wikimedia" + icon = "sources/wikimedia.svg" + base_url = "https://commons.wikimedia.org/w/api.php" + + def search(self, query): + params = { + "action": "query", + "format": "json", + "uselang": "en", + "generator": "search", + "gsrsearch": "filetype:bitmap|drawing filemime:svg " + query, + "gsrlimit": 40, + "gsroffset": 0, + "gsrinfo": "totalhits|suggestion", + "gsrprop": "size|wordcount", + "gsrnamespace": 6, + "prop": "info|imageinfo|entityterms", + "inprop": "url", + "iiprop": "url|size|mime|user|extmetadata", + "iiurlheight": 180, + "wbetterms": "label", + } + pages = [] + try: + response = self.session.get(self.base_url, params=params).json() + if "error" in response: + raise IOError(response["error"]["info"]) + pages = response["query"]["pages"].values() + except: + pass + + for item in pages: + img = item["imageinfo"][0] + # get standard licenses + # for non standard licenses we have to get the ShortName and provide the url to the resource + try: + license = img["extmetadata"]["License"]["value"] + if license in ["cc0", "pd"]: + license = "cc-0" + except KeyError: + license = img["extmetadata"]["LicenseShortName"]["value"] + yield { + "id": item.get("pageid", None), + "name": item["title"].split(":", 1)[-1], + "author": img["user"], + "license": license, + "summary": "", # No data + "thumbnail": img["thumburl"], + "created": item["touched"], + "descriptionurl": item["canonicalurl"], + "popularity": 0, # No data + "file": img["url"], + } diff --git a/share/extensions/other/clipart/sources/wikimedia.svg b/share/extensions/other/clipart/sources/wikimedia.svg new file mode 100644 index 0000000..23387ab --- /dev/null +++ b/share/extensions/other/clipart/sources/wikimedia.svg @@ -0,0 +1,92 @@ + + + + + + image/svg+xml + + Reactome_Imagotype_Positive + + + + + + + + + + + Reactome_Imagotype_Positive + + + + + + + + diff --git a/share/extensions/other/gcodetools/.darglint b/share/extensions/other/gcodetools/.darglint new file mode 100644 index 0000000..4447949 --- /dev/null +++ b/share/extensions/other/gcodetools/.darglint @@ -0,0 +1,3 @@ +[darglint] +docstring_style=google +strictness=short \ No newline at end of file diff --git a/share/extensions/other/gcodetools/.pylintrc b/share/extensions/other/gcodetools/.pylintrc new file mode 100644 index 0000000..a3903f9 --- /dev/null +++ b/share/extensions/other/gcodetools/.pylintrc @@ -0,0 +1,374 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +init-hook='import sys; sys.path.append("pythonenv/lib/python3.6/site-packages"); sys.path.append("../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../../pythonenv/lib/python3.6/site-packages");' + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist=lxml,numpy + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,superfluous-parens,missing-super-argument,model-missing-unicode + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=100 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,x,y,z,ex,Run,_,__,js,rx,x1,y1,x2,y2 + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[ELIF] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). This supports can work +# with qualified names. +ignored-classes=SQLObject,WSGIRequest + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/share/extensions/other/gcodetools/LICENSE.txt b/share/extensions/other/gcodetools/LICENSE.txt new file mode 100644 index 0000000..b83f24b --- /dev/null +++ b/share/extensions/other/gcodetools/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/share/extensions/other/gcodetools/MANIFEST.in b/share/extensions/other/gcodetools/MANIFEST.in new file mode 100644 index 0000000..2f29cde --- /dev/null +++ b/share/extensions/other/gcodetools/MANIFEST.in @@ -0,0 +1,2 @@ +include *.py +include *.inx diff --git a/share/extensions/other/gcodetools/README.md b/share/extensions/other/gcodetools/README.md new file mode 100644 index 0000000..faf25c9 --- /dev/null +++ b/share/extensions/other/gcodetools/README.md @@ -0,0 +1,45 @@ +# Gcodetools + +This folder contains gcodetools extension. They require the Inkscape extensions API inkex, see https://gitlab.com/inkscape/extensions. + +## Installation + +These scripts should be installed with an Inkscape package already (if you have +installed Inkscape). For packagers or people testing newer releases, you can +install the *.inx and *.py files into /usr/share/inkscape/extensions or +~/.config/inkscape/extensions . + +## Testing + +These extensions are designed to have good test coverage for python 3.6 and above. + +You must install the program `pytest` in order to run these tests. You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run. + + pytest + pytest tests/test_gcodetools.py + +See TESTING.md for further details. + +## Extension description + +Each *.inx file describes an extension, listing its name, purpose, +prerequisites, location within the menu, etc. These files are read by +Inkscape on launch. Other files are the scripts themselves (Perl, +Python, and Ruby are supported, as well as shell scripts). + +## Development + +Development of both the core inkex modules, tests and each of the extensions +contained within the core inkscape extensions repository should follow these +basic rules of quality assurance: + + * Use python3.6 or later, no python2 code would be used here. + * Use pylint to ensure code is written consistantly + * Have tests so that each line of an extension is covered in the coverage report + * Not cross streams between extensions, so your extension should import from + a module and not from another extension. + * Use translations on text for display to users using get text. + * Should not require external programs to work (with some exceptions) + +Also join the community on chat.inkscape.org channel #inkscape_extensions with any +doubts or problems. \ No newline at end of file diff --git a/share/extensions/other/gcodetools/TESTING.md b/share/extensions/other/gcodetools/TESTING.md new file mode 100644 index 0000000..07158a6 --- /dev/null +++ b/share/extensions/other/gcodetools/TESTING.md @@ -0,0 +1,104 @@ +# Why Test Extensions + +Previously, Inkscape extensions were not tested for quality or correctness. But since 1.0, the extensions repository is far more strict about requiring tests and requiring tests to pass before changes can be merged in. + +You may find yourself being frustrated by the tests, especially if at first it doesn't make sense why they are failing. But these tests are important and I ask that everyone be as kind as they can to make sure the quality of the repository is maintained. + +# Running Tests + +You must install the program `pytest` in order to run these tests. Both Pytest and Pytest-Coverage are required to run tests. + +Usually the best way to install it is: + +```shell +$ pip3 install pytest pytest-cov +``` + +You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run. + +```shell +$ pytest +$ pytest tests/test_my_extension.py +``` + +You can also run tests until the first time they fail, and ask pytest to run the previously failed tests first. This can cut down how long pytest takes to run before hitting a failure. + +```shell +$ pytest -x --ff +``` + +More info here: https://docs.pytest.org/en/latest/getting-started.html + +# Test Files + +Each extension should have its own test file in the tests directory. This test may be a series of function tests or "comparison" tests. The comparison tests will fail whenever the output of an extension changes, so often they will need to be updated to reflect your changes. + +Usually the test file will be named `tests/test_{name_of_extension}.py` using the same name as the extension file itself. For tests covering inkex and other modules you may find test files have the format `tests/test_{package}_{module}.py` or similar. + +Each test can be run independently as shown in the previous section. + +# Test Data + +As well as python test files, each test will normally depend on additional data. From source svg files, to output comparison tests and other such things. + +This data is always held in `tests/data`, when writing tests, please make sure your data goes into the right directory. If you are updating the comparison test, usually you just need to rename the `export` file generated and remove the `.export` suffix to enable it. + +See tests/data/README.md for further information. + +# Writing or Updating tests + +You need to read the documentation available inside the tester module to learn how to write tests, or what the test code means. From a python3 terminal type: + +```python +from inkex import tester +help(tester) +``` + +# Coverage + +Coverage reports tell us how much of an extension is being exercised when tests are run. + +The latest coverage report for master branch can be found at +https://inkscape.gitlab.io/extensions/coverage/. + +To run a complete coverage report, you can specify the `--cov=.` option like so: + +```shell +$ pytest --cov=. --cov-report term +``` + +For a single extension coverage report, you can limit it further with: + +```shell +$ pytest --cov=my_extension.py --cov-report term +``` + +## Testing Options + +Tests can be run with these options that are provided as environment variables: + + FAIL_ON_DEPRECATION=1 - Will instantly fail any use of deprecated APIs + EXPORT_COMPARE=1 - Generate output files from comparisons. This is useful for manually checking the output as well as updating the comparison data. + NO_MOCK_COMMANDS=1 - Instead of using the mock data, actually call commands. This will also generate the msg files similar to export compare. + INKSCAPE_COMMAND=/other/inkscape - Use a different Inkscape (for example development version) while running commands. Works outside of tests too. + XML_DIFF=1 - Attempt to output an XML diff file, this can be useful for debugging to see differences in context. + DEBUG_KEY=1 - Export mock file keys for debugging. This is a highly specialised option for debugging key generation. + +For example: + +```shell +$ EXPORT_COMPARE=1 pytest +``` + +or + +```shell +export EXPORT_COMPARE=1 +pytest +``` + +# Testing custom extensions + +The same testing framework can be used in your own extension repositories by requiring the inkex module and using the inkex.tester module set. It should be available with Inkscape or can be installed via pypi. + +This is a great way of ensuring you have access to the same tools Inkscape uses to test, and makes it easier for your external extension to make its way to the core repository without resistance. diff --git a/share/extensions/other/gcodetools/gcodetools.py b/share/extensions/other/gcodetools/gcodetools.py new file mode 100755 index 0000000..ef8bdd2 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools.py @@ -0,0 +1,5930 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org (super paths et al) +# 2007 hugomatic... (gcode.py) +# 2009 Nick Drobchenko, nick@cnc-club.ru (main developer) +# 2011 Chris Lusby Taylor, clusbytaylor@enterprise.net (engraving functions) +# +# 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. +# +""" +Comments starting "#LT" or "#CLT" are by Chris Lusby Taylor who rewrote the engraving function in 2011. +History of CLT changes to engraving and other functions it uses: +9 May 2011 Changed test of tool diameter to square it +10 May Note that there are many unused functions, including: + bound_to_bound_distance, csp_curvature_radius_at_t, + csp_special_points, csplength, rebuild_csp, csp_slope, + csp_simple_bound_to_point_distance, csp_bound_to_point_distance, + bez_at_t, bez_to_point_distance, bez_normalized_slope, matrix_mul, transpose + Fixed csp_point_inside_bound() to work if x outside bounds +20 May Now encoding the bisectors of angles. +23 May Using r/cos(a) instead of normalised normals for bisectors of angles. +23 May Note that Z values generated for engraving are in pixels, not mm. + Removed the biarc curves - straight lines are better. +24 May Changed Bezier slope calculation to be less sensitive to tiny differences in points. + Added use of self.options.engraving_newton_iterations to control accuracy +25 May Big restructure and new recursive function. + Changed the way I treat corners - I now find if the centre of a proposed circle is + within the area bounded by the line being tested and the two angle bisectors at + its ends. See get_radius_to_line(). +29 May Eliminating redundant points. If A,B,C colinear, drop B +30 May Eliminating redundant lines in divided Beziers. Changed subdivision of lines + 7Jun Try to show engraving in 3D + 8 Jun Displaying in stereo 3D. + Fixed a bug in bisect - it could go wrong due to rounding errors if + 1+x1.x2+y1.y2<0 which should never happen. BTW, I spotted a non-normalised normal + returned by csp_normalized_normal. Need to check for that. + 9 Jun Corrected spelling of 'definition' but still match previous 'defention' and 'defenition' if found in file + Changed get_tool to find 1.6.04 tools or new tools with corrected spelling +10 Jun Put 3D into a separate layer called 3D, created unless it already exists + Changed csp_normalized_slope to reject lines shorter than 1e-9. +10 Jun Changed all dimensions seen by user to be mm/inch, not pixels. This includes + tool diameter, maximum engraving distance, tool shape and all Z values. +12 Jun ver 208 Now scales correctly if orientation points moved or stretched. +12 Jun ver 209. Now detect if engraving toolshape not a function of radius + Graphics now indicate Gcode toolpath, limited by min(tool diameter/2,max-dist) +24 Jan 2017 Removed hard-coded scale values from orientation point calculation +TODO Change line division to be recursive, depending on what line is touched. See line_divide +""" + +__version__ = '1.7' + +import cmath +import copy +import math +import os +import re +import sys +import time +from functools import partial + +import numpy + +import inkex +from inkex.bezier import bezierlength, bezierparameterize, beziertatlength +from inkex import Transform, PathElement, TextElement, Tspan, Group, Layer, Marker, CubicSuperPath, Style + +if sys.version_info[0] > 2: + xrange = range + unicode = str + +def ireplace(self, old, new, count=0): + pattern = re.compile(re.escape(old), re.I) + return re.sub(pattern, new, self, count) + + +################################################################################ +# +# Styles and additional parameters +# +################################################################################ + +TAU = math.pi * 2 +STRAIGHT_TOLERANCE = 0.0001 +STRAIGHT_DISTANCE_TOLERANCE = 0.0001 +ENGRAVING_TOLERANCE = 0.0001 +LOFT_LENGTHS_TOLERANCE = 0.0000001 + +EMC_TOLERANCE_EQUAL = 0.00001 + +options = {} +defaults = { + 'header': """% +(Header) +(Generated by gcodetools from Inkscape.) +(Using default header. To add your own header create file "header" in the output dir.) +M3 +(Header end.) +""", + 'footer': """ +(Footer) +M5 +G00 X0.0000 Y0.0000 +M2 +(Using default footer. To add your own footer create file "footer" in the output dir.) +(end) +%""" +} + +INTERSECTION_RECURSION_DEPTH = 10 +INTERSECTION_TOLERANCE = 0.00001 + +def marker_style(stroke, marker='DrawCurveMarker', width=1): + """Set a marker style with some basic defaults""" + return Style(stroke=stroke, fill='none', stroke_width=width, + marker_end='url(#{})'.format(marker)) + +MARKER_STYLE = { + "in_out_path_style": marker_style('#0072a7', 'InOutPathMarker'), + "loft_style": { + 'main curve': marker_style('#88f', 'Arrow2Mend'), + }, + "biarc_style": { + 'biarc0': marker_style('#88f'), + 'biarc1': marker_style('#8f8'), + 'line': marker_style('#f88'), + 'area': marker_style('#777', width=0.1), + }, + "biarc_style_dark": { + 'biarc0': marker_style('#33a'), + 'biarc1': marker_style('#3a3'), + 'line': marker_style('#a33'), + 'area': marker_style('#222', width=0.3), + }, + "biarc_style_dark_area": { + 'biarc0': marker_style('#33a', width=0.1), + 'biarc1': marker_style('#3a3', width=0.1), + 'line': marker_style('#a33', width=0.1), + 'area': marker_style('#222', width=0.3), + }, + "biarc_style_i": { + 'biarc0': marker_style('#880'), + 'biarc1': marker_style('#808'), + 'line': marker_style('#088'), + 'area': marker_style('#999', width=0.3), + }, + "biarc_style_dark_i": { + 'biarc0': marker_style('#dd5'), + 'biarc1': marker_style('#d5d'), + 'line': marker_style('#5dd'), + 'area': marker_style('#aaa', width=0.3), + }, + "biarc_style_lathe_feed": { + 'biarc0': marker_style('#07f', width=0.4), + 'biarc1': marker_style('#0f7', width=0.4), + 'line': marker_style('#f44', width=0.4), + 'area': marker_style('#aaa', width=0.3), + }, + "biarc_style_lathe_passing feed": { + 'biarc0': marker_style('#07f', width=0.4), + 'biarc1': marker_style('#0f7', width=0.4), + 'line': marker_style('#f44', width=0.4), + 'area': marker_style('#aaa', width=0.3), + }, + "biarc_style_lathe_fine feed": { + 'biarc0': marker_style('#7f0', width=0.4), + 'biarc1': marker_style('#f70', width=0.4), + 'line': marker_style('#744', width=0.4), + 'area': marker_style('#aaa', width=0.3), + }, + "area artefact": Style(stroke='#ff0000', fill='#ffff00', stroke_width=1), + "area artefact arrow": Style(stroke='#ff0000', fill='#ffff00', stroke_width=1), + "dxf_points": Style(stroke="#ff0000", fill="#ff0000"), +} + + +################################################################################ +# Gcode additional functions +################################################################################ + +def gcode_comment_str(s, replace_new_line=False): + if replace_new_line: + s = re.sub(r"[\n\r]+", ".", s) + res = "" + if s[-1] == "\n": + s = s[:-1] + for a in s.split("\n"): + if a != "": + res += "(" + re.sub(r"[\(\)\\\n\r]", ".", a) + ")\n" + else: + res += "\n" + return res + + +################################################################################ +# Cubic Super Path additional functions +################################################################################ + + +def csp_from_polyline(line): + return [[[point[:] for _ in range(3)] for point in subline] for subline in line] + + +def csp_remove_zero_segments(csp, tolerance=1e-7): + res = [] + for subpath in csp: + if len(subpath) > 0: + res.append([subpath[0]]) + for sp1, sp2 in zip(subpath, subpath[1:]): + if point_to_point_d2(sp1[1], sp2[1]) <= tolerance and point_to_point_d2(sp1[2], sp2[1]) <= tolerance and point_to_point_d2(sp1[1], sp2[0]) <= tolerance: + res[-1][-1][2] = sp2[2] + else: + res[-1].append(sp2) + return res + + +def point_inside_csp(p, csp, on_the_path=True): + # we'll do the raytracing and see how many intersections are there on the ray's way. + # if number of intersections is even then point is outside. + # ray will be x=p.x and y=>p.y + # you can assign any value to on_the_path, by default if point is on the path + # function will return thai it's inside the path. + x, y = p + ray_intersections_count = 0 + for subpath in csp: + + for i in range(1, len(subpath)): + sp1 = subpath[i - 1] + sp2 = subpath[i] + ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2) + if ax == 0 and bx == 0 and cx == 0 and dx == x: + # we've got a special case here + b = csp_true_bounds([[sp1, sp2]]) + if b[1][1] <= y <= b[3][1]: + # points is on the path + return on_the_path + else: + # we can skip this segment because it won't influence the answer. + pass + else: + for t in csp_line_intersection([x, y], [x, y + 5], sp1, sp2): + if t == 0 or t == 1: + # we've got another special case here + x1, y1 = csp_at_t(sp1, sp2, t) + if y1 == y: + # the point is on the path + return on_the_path + # if t == 0 we should have considered this case previously. + if t == 1: + # we have to check the next segment if it is on the same side of the ray + st_d = csp_normalized_slope(sp1, sp2, 1)[0] + if st_d == 0: + st_d = csp_normalized_slope(sp1, sp2, 0.99)[0] + + for j in range(1, len(subpath) + 1): + if (i + j) % len(subpath) == 0: + continue # skip the closing segment + sp11 = subpath[(i - 1 + j) % len(subpath)] + sp22 = subpath[(i + j) % len(subpath)] + ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = csp_parameterize(sp1, sp2) + if ax1 == 0 and bx1 == 0 and cx1 == 0 and dx1 == x: + continue # this segment parallel to the ray, so skip it + en_d = csp_normalized_slope(sp11, sp22, 0)[0] + if en_d == 0: + en_d = csp_normalized_slope(sp11, sp22, 0.01)[0] + if st_d * en_d <= 0: + ray_intersections_count += 1 + break + else: + x1, y1 = csp_at_t(sp1, sp2, t) + if y1 == y: + # the point is on the path + return on_the_path + else: + if y1 > y and 3 * ax * t ** 2 + 2 * bx * t + cx != 0: # if it's 0 the path only touches the ray + ray_intersections_count += 1 + return ray_intersections_count % 2 == 1 + + +def csp_close_all_subpaths(csp, tolerance=0.000001): + for i in range(len(csp)): + if point_to_point_d2(csp[i][0][1], csp[i][-1][1]) > tolerance ** 2: + csp[i][-1][2] = csp[i][-1][1][:] + csp[i] += [[csp[i][0][1][:] for _ in range(3)]] + else: + if csp[i][0][1] != csp[i][-1][1]: + csp[i][-1][1] = csp[i][0][1][:] + return csp + + +def csp_simple_bound(csp): + minx = None + miny = None + maxx = None + maxy = None + + for subpath in csp: + for sp in subpath: + for p in sp: + minx = min(minx, p[0]) if minx is not None else p[0] + miny = min(miny, p[1]) if miny is not None else p[1] + maxx = max(maxx, p[0]) if maxx is not None else p[0] + maxy = max(maxy, p[1]) if maxy is not None else p[1] + return minx, miny, maxx, maxy + + +def csp_segment_to_bez(sp1, sp2): + return sp1[1:] + sp2[:2] + + +def csp_to_point_distance(csp, p, dist_bounds=(0, 1e100)): + min_dist = [1e100, 0, 0, 0] + for j in range(len(csp)): + for i in range(1, len(csp[j])): + d = csp_seg_to_point_distance(csp[j][i - 1], csp[j][i], p, sample_points=5) + if d[0] < dist_bounds[0]: + return [d[0], j, i, d[1]] + else: + if d[0] < min_dist[0]: + min_dist = [d[0], j, i, d[1]] + return min_dist + + +def csp_seg_to_point_distance(sp1, sp2, p, sample_points=5): + ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2) + dx = dx - p[0] + dy = dy - p[1] + if sample_points < 2: + sample_points = 2 + d = min([(p[0] - sp1[1][0]) ** 2 + (p[1] - sp1[1][1]) ** 2, 0.], [(p[0] - sp2[1][0]) ** 2 + (p[1] - sp2[1][1]) ** 2, 1.]) + for k in range(sample_points): + t = float(k) / (sample_points - 1) + i = 0 + while i == 0 or abs(f) > 0.000001 and i < 20: + t2 = t ** 2 + t3 = t ** 3 + f = (ax * t3 + bx * t2 + cx * t + dx) * (3 * ax * t2 + 2 * bx * t + cx) + (ay * t3 + by * t2 + cy * t + dy) * (3 * ay * t2 + 2 * by * t + cy) + df = (6 * ax * t + 2 * bx) * (ax * t3 + bx * t2 + cx * t + dx) + (3 * ax * t2 + 2 * bx * t + cx) ** 2 + (6 * ay * t + 2 * by) * (ay * t3 + by * t2 + cy * t + dy) + (3 * ay * t2 + 2 * by * t + cy) ** 2 + if df != 0: + t = t - f / df + else: + break + i += 1 + if 0 <= t <= 1: + p1 = csp_at_t(sp1, sp2, t) + d1 = (p1[0] - p[0]) ** 2 + (p1[1] - p[1]) ** 2 + if d1 < d[0]: + d = [d1, t] + return d + + +def csp_seg_to_csp_seg_distance(sp1, sp2, sp3, sp4, dist_bounds=(0, 1e100), sample_points=5, tolerance=.01): + # check the ending points first + dist = csp_seg_to_point_distance(sp1, sp2, sp3[1], sample_points) + dist += [0.] + if dist[0] <= dist_bounds[0]: + return dist + d = csp_seg_to_point_distance(sp1, sp2, sp4[1], sample_points) + if d[0] < dist[0]: + dist = d + [1.] + if dist[0] <= dist_bounds[0]: + return dist + d = csp_seg_to_point_distance(sp3, sp4, sp1[1], sample_points) + if d[0] < dist[0]: + dist = [d[0], 0., d[1]] + if dist[0] <= dist_bounds[0]: + return dist + d = csp_seg_to_point_distance(sp3, sp4, sp2[1], sample_points) + if d[0] < dist[0]: + dist = [d[0], 1., d[1]] + if dist[0] <= dist_bounds[0]: + return dist + sample_points -= 2 + if sample_points < 1: + sample_points = 1 + ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = csp_parameterize(sp1, sp2) + ax2, ay2, bx2, by2, cx2, cy2, dx2, dy2 = csp_parameterize(sp3, sp4) + # try to find closes points using Newtons method + for k in range(sample_points): + for j in range(sample_points): + t1 = float(k + 1) / (sample_points + 1) + t2 = float(j) / (sample_points + 1) + + t12 = t1 * t1 + t13 = t1 * t1 * t1 + t22 = t2 * t2 + t23 = t2 * t2 * t2 + i = 0 + + F1 = [0, 0] + F2 = [[0, 0], [0, 0]] + F = 1e100 + x = ax1 * t13 + bx1 * t12 + cx1 * t1 + dx1 - (ax2 * t23 + bx2 * t22 + cx2 * t2 + dx2) + y = ay1 * t13 + by1 * t12 + cy1 * t1 + dy1 - (ay2 * t23 + by2 * t22 + cy2 * t2 + dy2) + while i < 2 or abs(F - Flast) > tolerance and i < 30: + f1x = 3 * ax1 * t12 + 2 * bx1 * t1 + cx1 + f1y = 3 * ay1 * t12 + 2 * by1 * t1 + cy1 + f2x = 3 * ax2 * t22 + 2 * bx2 * t2 + cx2 + f2y = 3 * ay2 * t22 + 2 * by2 * t2 + cy2 + F1[0] = 2 * f1x * x + 2 * f1y * y + F1[1] = -2 * f2x * x - 2 * f2y * y + F2[0][0] = 2 * (6 * ax1 * t1 + 2 * bx1) * x + 2 * f1x * f1x + 2 * (6 * ay1 * t1 + 2 * by1) * y + 2 * f1y * f1y + F2[0][1] = -2 * f1x * f2x - 2 * f1y * f2y + F2[1][0] = -2 * f2x * f1x - 2 * f2y * f1y + F2[1][1] = -2 * (6 * ax2 * t2 + 2 * bx2) * x + 2 * f2x * f2x - 2 * (6 * ay2 * t2 + 2 * by2) * y + 2 * f2y * f2y + F2 = inv_2x2(F2) + if F2 is not None: + t1 -= (F2[0][0] * F1[0] + F2[0][1] * F1[1]) + t2 -= (F2[1][0] * F1[0] + F2[1][1] * F1[1]) + t12 = t1 * t1 + t13 = t1 * t1 * t1 + t22 = t2 * t2 + t23 = t2 * t2 * t2 + x = ax1 * t13 + bx1 * t12 + cx1 * t1 + dx1 - (ax2 * t23 + bx2 * t22 + cx2 * t2 + dx2) + y = ay1 * t13 + by1 * t12 + cy1 * t1 + dy1 - (ay2 * t23 + by2 * t22 + cy2 * t2 + dy2) + Flast = F + F = x * x + y * y + else: + break + i += 1 + if F < dist[0] and 0 <= t1 <= 1 and 0 <= t2 <= 1: + dist = [F, t1, t2] + if dist[0] <= dist_bounds[0]: + return dist + return dist + + +def csp_to_csp_distance(csp1, csp2, dist_bounds=(0, 1e100), tolerance=.01): + dist = [1e100, 0, 0, 0, 0, 0, 0] + for i1 in range(len(csp1)): + for j1 in range(1, len(csp1[i1])): + for i2 in range(len(csp2)): + for j2 in range(1, len(csp2[i2])): + d = csp_seg_bound_to_csp_seg_bound_max_min_distance(csp1[i1][j1 - 1], csp1[i1][j1], csp2[i2][j2 - 1], csp2[i2][j2]) + if d[0] >= dist_bounds[1]: + continue + if d[1] < dist_bounds[0]: + return [d[1], i1, j1, 1, i2, j2, 1] + d = csp_seg_to_csp_seg_distance(csp1[i1][j1 - 1], csp1[i1][j1], csp2[i2][j2 - 1], csp2[i2][j2], dist_bounds, tolerance=tolerance) + if d[0] < dist[0]: + dist = [d[0], i1, j1, d[1], i2, j2, d[2]] + if dist[0] <= dist_bounds[0]: + return dist + if dist[0] >= dist_bounds[1]: + return dist + return dist + + +def csp_split(sp1, sp2, t=.5): + [x1, y1] = sp1[1] + [x2, y2] = sp1[2] + [x3, y3] = sp2[0] + [x4, y4] = sp2[1] + x12 = x1 + (x2 - x1) * t + y12 = y1 + (y2 - y1) * t + x23 = x2 + (x3 - x2) * t + y23 = y2 + (y3 - y2) * t + x34 = x3 + (x4 - x3) * t + y34 = y3 + (y4 - y3) * t + x1223 = x12 + (x23 - x12) * t + y1223 = y12 + (y23 - y12) * t + x2334 = x23 + (x34 - x23) * t + y2334 = y23 + (y34 - y23) * t + x = x1223 + (x2334 - x1223) * t + y = y1223 + (y2334 - y1223) * t + return [sp1[0], sp1[1], [x12, y12]], [[x1223, y1223], [x, y], [x2334, y2334]], [[x34, y34], sp2[1], sp2[2]] + + +def csp_true_bounds(csp): + # Finds minx,miny,maxx,maxy of the csp and return their (x,y,i,j,t) + minx = [float("inf"), 0, 0, 0] + maxx = [float("-inf"), 0, 0, 0] + miny = [float("inf"), 0, 0, 0] + maxy = [float("-inf"), 0, 0, 0] + for i in range(len(csp)): + for j in range(1, len(csp[i])): + ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize((csp[i][j - 1][1], csp[i][j - 1][2], csp[i][j][0], csp[i][j][1])) + roots = cubic_solver(0, 3 * ax, 2 * bx, cx) + [0, 1] + for root in roots: + if type(root) is complex and abs(root.imag) < 1e-10: + root = root.real + if type(root) is not complex and 0 <= root <= 1: + y = ay * (root ** 3) + by * (root ** 2) + cy * root + y0 + x = ax * (root ** 3) + bx * (root ** 2) + cx * root + x0 + maxx = max([x, y, i, j, root], maxx) + minx = min([x, y, i, j, root], minx) + + roots = cubic_solver(0, 3 * ay, 2 * by, cy) + [0, 1] + for root in roots: + if type(root) is complex and root.imag == 0: + root = root.real + if type(root) is not complex and 0 <= root <= 1: + y = ay * (root ** 3) + by * (root ** 2) + cy * root + y0 + x = ax * (root ** 3) + bx * (root ** 2) + cx * root + x0 + maxy = max([y, x, i, j, root], maxy) + miny = min([y, x, i, j, root], miny) + maxy[0], maxy[1] = maxy[1], maxy[0] + miny[0], miny[1] = miny[1], miny[0] + + return minx, miny, maxx, maxy + + +############################################################################ +# csp_segments_intersection(sp1,sp2,sp3,sp4) +# +# Returns array containing all intersections between two segments of cubic +# super path. Results are [ta,tb], or [ta0, ta1, tb0, tb1, "Overlap"] +# where ta, tb are values of t for the intersection point. +############################################################################ +def csp_segments_intersection(sp1, sp2, sp3, sp4): + a = csp_segment_to_bez(sp1, sp2) + b = csp_segment_to_bez(sp3, sp4) + + def polish_intersection(a, b, ta, tb, tolerance=INTERSECTION_TOLERANCE): + ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize(a) + ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = bezierparameterize(b) + i = 0 + F = [.0, .0] + F1 = [[.0, .0], [.0, .0]] + while i == 0 or (abs(F[0]) ** 2 + abs(F[1]) ** 2 > tolerance and i < 10): + ta3 = ta ** 3 + ta2 = ta ** 2 + tb3 = tb ** 3 + tb2 = tb ** 2 + F[0] = ax * ta3 + bx * ta2 + cx * ta + dx - ax1 * tb3 - bx1 * tb2 - cx1 * tb - dx1 + F[1] = ay * ta3 + by * ta2 + cy * ta + dy - ay1 * tb3 - by1 * tb2 - cy1 * tb - dy1 + F1[0][0] = 3 * ax * ta2 + 2 * bx * ta + cx + F1[0][1] = -3 * ax1 * tb2 - 2 * bx1 * tb - cx1 + F1[1][0] = 3 * ay * ta2 + 2 * by * ta + cy + F1[1][1] = -3 * ay1 * tb2 - 2 * by1 * tb - cy1 + det = F1[0][0] * F1[1][1] - F1[0][1] * F1[1][0] + if det != 0: + F1 = [[F1[1][1] / det, -F1[0][1] / det], [-F1[1][0] / det, F1[0][0] / det]] + ta = ta - (F1[0][0] * F[0] + F1[0][1] * F[1]) + tb = tb - (F1[1][0] * F[0] + F1[1][1] * F[1]) + else: + break + i += 1 + + return ta, tb + + def recursion(a, b, ta0, ta1, tb0, tb1, depth_a, depth_b): + global bezier_intersection_recursive_result + if a == b: + bezier_intersection_recursive_result += [[ta0, tb0, ta1, tb1, "Overlap"]] + return + tam = (ta0 + ta1) / 2 + tbm = (tb0 + tb1) / 2 + if depth_a > 0 and depth_b > 0: + a1, a2 = bez_split(a, 0.5) + b1, b2 = bez_split(b, 0.5) + if bez_bounds_intersect(a1, b1): + recursion(a1, b1, ta0, tam, tb0, tbm, depth_a - 1, depth_b - 1) + if bez_bounds_intersect(a2, b1): + recursion(a2, b1, tam, ta1, tb0, tbm, depth_a - 1, depth_b - 1) + if bez_bounds_intersect(a1, b2): + recursion(a1, b2, ta0, tam, tbm, tb1, depth_a - 1, depth_b - 1) + if bez_bounds_intersect(a2, b2): + recursion(a2, b2, tam, ta1, tbm, tb1, depth_a - 1, depth_b - 1) + elif depth_a > 0: + a1, a2 = bez_split(a, 0.5) + if bez_bounds_intersect(a1, b): + recursion(a1, b, ta0, tam, tb0, tb1, depth_a - 1, depth_b) + if bez_bounds_intersect(a2, b): + recursion(a2, b, tam, ta1, tb0, tb1, depth_a - 1, depth_b) + elif depth_b > 0: + b1, b2 = bez_split(b, 0.5) + if bez_bounds_intersect(a, b1): + recursion(a, b1, ta0, ta1, tb0, tbm, depth_a, depth_b - 1) + if bez_bounds_intersect(a, b2): + recursion(a, b2, ta0, ta1, tbm, tb1, depth_a, depth_b - 1) + else: # Both segments have been subdivided enough. Let's get some intersections :). + intersection, t1, t2 = straight_segments_intersection([a[0]] + [a[3]], [b[0]] + [b[3]]) + if intersection: + if intersection == "Overlap": + t1 = (max(0, min(1, t1[0])) + max(0, min(1, t1[1]))) / 2 + t2 = (max(0, min(1, t2[0])) + max(0, min(1, t2[1]))) / 2 + bezier_intersection_recursive_result += [[ta0 + t1 * (ta1 - ta0), tb0 + t2 * (tb1 - tb0)]] + + global bezier_intersection_recursive_result + bezier_intersection_recursive_result = [] + recursion(a, b, 0., 1., 0., 1., INTERSECTION_RECURSION_DEPTH, INTERSECTION_RECURSION_DEPTH) + intersections = bezier_intersection_recursive_result + for i in range(len(intersections)): + if len(intersections[i]) < 5 or intersections[i][4] != "Overlap": + intersections[i] = polish_intersection(a, b, intersections[i][0], intersections[i][1]) + return intersections + + +def csp_segments_true_intersection(sp1, sp2, sp3, sp4): + intersections = csp_segments_intersection(sp1, sp2, sp3, sp4) + res = [] + for intersection in intersections: + if ( + (len(intersection) == 5 and intersection[4] == "Overlap" and (0 <= intersection[0] <= 1 or 0 <= intersection[1] <= 1) and (0 <= intersection[2] <= 1 or 0 <= intersection[3] <= 1)) + or (0 <= intersection[0] <= 1 and 0 <= intersection[1] <= 1) + ): + res += [intersection] + return res + + +def csp_get_t_at_curvature(sp1, sp2, c, sample_points=16): + # returns a list containing [t1,t2,t3,...,tn], 0<=ti<=1... + if sample_points < 2: + sample_points = 2 + tolerance = .0000000001 + res = [] + ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2) + for k in range(sample_points): + t = float(k) / (sample_points - 1) + i = 0 + F = 1e100 + while i < 2 or abs(F) > tolerance and i < 17: + try: # some numerical calculation could exceed the limits + t2 = t * t + # slopes... + f1x = 3 * ax * t2 + 2 * bx * t + cx + f1y = 3 * ay * t2 + 2 * by * t + cy + f2x = 6 * ax * t + 2 * bx + f2y = 6 * ay * t + 2 * by + f3x = 6 * ax + f3y = 6 * ay + d = (f1x ** 2 + f1y ** 2) ** 1.5 + F1 = ( + ((f1x * f3y - f3x * f1y) * d - (f1x * f2y - f2x * f1y) * 3. * (f2x * f1x + f2y * f1y) * ((f1x ** 2 + f1y ** 2) ** .5)) / + ((f1x ** 2 + f1y ** 2) ** 3) + ) + F = (f1x * f2y - f1y * f2x) / d - c + t -= F / F1 + except: + break + i += 1 + if 0 <= t <= 1 and F <= tolerance: + if len(res) == 0: + res.append(t) + for i in res: + if abs(t - i) <= 0.001: + break + if not abs(t - i) <= 0.001: + res.append(t) + return res + + +def csp_max_curvature(sp1, sp2): + ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2) + tolerance = .0001 + F = 0. + i = 0 + while i < 2 or F - Flast < tolerance and i < 10: + t = .5 + f1x = 3 * ax * t ** 2 + 2 * bx * t + cx + f1y = 3 * ay * t ** 2 + 2 * by * t + cy + f2x = 6 * ax * t + 2 * bx + f2y = 6 * ay * t + 2 * by + f3x = 6 * ax + f3y = 6 * ay + d = pow(f1x ** 2 + f1y ** 2, 1.5) + if d != 0: + Flast = F + F = (f1x * f2y - f1y * f2x) / d + F1 = ( + (d * (f1x * f3y - f3x * f1y) - (f1x * f2y - f2x * f1y) * 3. * (f2x * f1x + f2y * f1y) * pow(f1x ** 2 + f1y ** 2, .5)) / + (f1x ** 2 + f1y ** 2) ** 3 + ) + i += 1 + if F1 != 0: + t -= F / F1 + else: + break + else: + break + return t + + +def csp_curvature_at_t(sp1, sp2, t, depth=3): + ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize(csp_segment_to_bez(sp1, sp2)) + + # curvature = (x'y''-y'x'') / (x'^2+y'^2)^1.5 + + f1x = 3 * ax * t ** 2 + 2 * bx * t + cx + f1y = 3 * ay * t ** 2 + 2 * by * t + cy + f2x = 6 * ax * t + 2 * bx + f2y = 6 * ay * t + 2 * by + d = (f1x ** 2 + f1y ** 2) ** 1.5 + if d != 0: + return (f1x * f2y - f1y * f2x) / d + else: + t1 = f1x * f2y - f1y * f2x + if t1 > 0: + return 1e100 + if t1 < 0: + return -1e100 + # Use the Lapitals rule to solve 0/0 problem for 2 times... + t1 = 2 * (bx * ay - ax * by) * t + (ay * cx - ax * cy) + if t1 > 0: + return 1e100 + if t1 < 0: + return -1e100 + t1 = bx * ay - ax * by + if t1 > 0: + return 1e100 + if t1 < 0: + return -1e100 + if depth > 0: + # little hack ;^) hope it won't influence anything... + return csp_curvature_at_t(sp1, sp2, t * 1.004, depth - 1) + return 1e100 + + +def csp_subpath_ccw(subpath): + # Remove all zero length segments + s = 0 + if (P(subpath[-1][1]) - P(subpath[0][1])).l2() > 1e-10: + subpath[-1][2] = subpath[-1][1] + subpath[0][0] = subpath[0][1] + subpath += [[subpath[0][1], subpath[0][1], subpath[0][1]]] + pl = subpath[-1][2] + for sp1 in subpath: + for p in sp1: + s += (p[0] - pl[0]) * (p[1] + pl[1]) + pl = p + return s < 0 + + +def csp_at_t(sp1, sp2, t): + ax = sp1[1][0] + bx = sp1[2][0] + cx = sp2[0][0] + dx = sp2[1][0] + + ay = sp1[1][1] + by = sp1[2][1] + cy = sp2[0][1] + dy = sp2[1][1] + + x1 = ax + (bx - ax) * t + y1 = ay + (by - ay) * t + + x2 = bx + (cx - bx) * t + y2 = by + (cy - by) * t + + x3 = cx + (dx - cx) * t + y3 = cy + (dy - cy) * t + + x4 = x1 + (x2 - x1) * t + y4 = y1 + (y2 - y1) * t + + x5 = x2 + (x3 - x2) * t + y5 = y2 + (y3 - y2) * t + + x = x4 + (x5 - x4) * t + y = y4 + (y5 - y4) * t + + return [x, y] + + +def csp_at_length(sp1, sp2, l=0.5, tolerance=0.01): + bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]) + t = beziertatlength(bez, l, tolerance) + return csp_at_t(sp1, sp2, t) + + +def cspseglength(sp1, sp2, tolerance=0.01): + bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]) + return bezierlength(bez, tolerance) + + +def csp_line_intersection(l1, l2, sp1, sp2): + dd = l1[0] + cc = l2[0] - l1[0] + bb = l1[1] + aa = l2[1] - l1[1] + if aa == cc == 0: + return [] + if aa: + coef1 = cc / aa + coef2 = 1 + else: + coef1 = 1 + coef2 = aa / cc + bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]) + ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize(bez) + a = coef1 * ay - coef2 * ax + b = coef1 * by - coef2 * bx + c = coef1 * cy - coef2 * cx + d = coef1 * (y0 - bb) - coef2 * (x0 - dd) + roots = cubic_solver(a, b, c, d) + retval = [] + for i in roots: + if type(i) is complex and abs(i.imag) < 1e-7: + i = i.real + if type(i) is not complex and -1e-10 <= i <= 1. + 1e-10: + retval.append(i) + return retval + + +def csp_split_by_two_points(sp1, sp2, t1, t2): + if t1 > t2: + t1, t2 = t2, t1 + if t1 == t2: + sp1, sp2, sp3 = csp_split(sp1, sp2, t1) + return [sp1, sp2, sp2, sp3] + elif t1 <= 1e-10 and t2 >= 1. - 1e-10: + return [sp1, sp1, sp2, sp2] + elif t1 <= 1e-10: + sp1, sp2, sp3 = csp_split(sp1, sp2, t2) + return [sp1, sp1, sp2, sp3] + elif t2 >= 1. - 1e-10: + sp1, sp2, sp3 = csp_split(sp1, sp2, t1) + return [sp1, sp2, sp3, sp3] + else: + sp1, sp2, sp3 = csp_split(sp1, sp2, t1) + sp2, sp3, sp4 = csp_split(sp2, sp3, (t2 - t1) / (1 - t1)) + return [sp1, sp2, sp3, sp4] + + +def csp_seg_split(sp1, sp2, points): + # points is float=t or list [t1, t2, ..., tn] + if type(points) is float: + points = [points] + points.sort() + res = [sp1, sp2] + last_t = 0 + for t in points: + if 1e-10 < t < 1. - 1e-10: + sp3, sp4, sp5 = csp_split(res[-2], res[-1], (t - last_t) / (1 - last_t)) + last_t = t + res[-2:] = [sp3, sp4, sp5] + return res + + +def csp_subpath_split_by_points(subpath, points): + # points are [[i,t]...] where i-segment's number + points.sort() + points = [[1, 0.]] + points + [[len(subpath) - 1, 1.]] + parts = [] + for int1, int2 in zip(points, points[1:]): + if int1 == int2: + continue + if int1[1] == 1.: + int1[0] += 1 + int1[1] = 0. + if int1 == int2: + continue + if int2[1] == 0.: + int2[0] -= 1 + int2[1] = 1. + if int1[0] == 0 and int2[0] == len(subpath) - 1: # and small(int1[1]) and small(int2[1]-1) : + continue + if int1[0] == int2[0]: # same segment + sp = csp_split_by_two_points(subpath[int1[0] - 1], subpath[int1[0]], int1[1], int2[1]) + if sp[1] != sp[2]: + parts += [[sp[1], sp[2]]] + else: + sp5, sp1, sp2 = csp_split(subpath[int1[0] - 1], subpath[int1[0]], int1[1]) + sp3, sp4, sp5 = csp_split(subpath[int2[0] - 1], subpath[int2[0]], int2[1]) + if int1[0] == int2[0] - 1: + parts += [[sp1, [sp2[0], sp2[1], sp3[2]], sp4]] + else: + parts += [[sp1, sp2] + subpath[int1[0] + 1:int2[0] - 1] + [sp3, sp4]] + return parts + + +def arc_from_s_r_n_l(s, r, n, l): + if abs(n[0] ** 2 + n[1] ** 2 - 1) > 1e-10: + n = normalize(n) + return arc_from_c_s_l([s[0] + n[0] * r, s[1] + n[1] * r], s, l) + + +def arc_from_c_s_l(c, s, l): + r = point_to_point_d(c, s) + if r == 0: + return [] + alpha = l / r + cos_ = math.cos(alpha) + sin_ = math.sin(alpha) + e = [c[0] + (s[0] - c[0]) * cos_ - (s[1] - c[1]) * sin_, c[1] + (s[0] - c[0]) * sin_ + (s[1] - c[1]) * cos_] + n = [c[0] - s[0], c[1] - s[1]] + slope = rotate_cw(n) if l > 0 else rotate_ccw(n) + return csp_from_arc(s, e, c, r, slope) + + +def csp_from_arc(start, end, center, r, slope_st): + # Creates csp that approximise specified arc + r = abs(r) + alpha = (atan2(end[0] - center[0], end[1] - center[1]) - atan2(start[0] - center[0], start[1] - center[1])) % TAU + + sectors = int(abs(alpha) * 2 / math.pi) + 1 + alpha_start = atan2(start[0] - center[0], start[1] - center[1]) + cos_ = math.cos(alpha_start) + sin_ = math.sin(alpha_start) + k = (4. * math.tan(alpha / sectors / 4.) / 3.) + if dot(slope_st, [- sin_ * k * r, cos_ * k * r]) < 0: + if alpha > 0: + alpha -= TAU + else: + alpha += TAU + if abs(alpha * r) < 0.001: + return [] + + sectors = int(abs(alpha) * 2 / math.pi) + 1 + k = (4. * math.tan(alpha / sectors / 4.) / 3.) + result = [] + for i in range(sectors + 1): + cos_ = math.cos(alpha_start + alpha * i / sectors) + sin_ = math.sin(alpha_start + alpha * i / sectors) + sp = [[], [center[0] + cos_ * r, center[1] + sin_ * r], []] + sp[0] = [sp[1][0] + sin_ * k * r, sp[1][1] - cos_ * k * r] + sp[2] = [sp[1][0] - sin_ * k * r, sp[1][1] + cos_ * k * r] + result += [sp] + result[0][0] = result[0][1][:] + result[-1][2] = result[-1][1] + + return result + + +def point_to_arc_distance(p, arc): + # Distance calculattion from point to arc + P0, P2, c, a = arc + p = P(p) + r = (P0 - c).mag() + if r > 0: + i = c + (p - c).unit() * r + alpha = ((i - c).angle() - (P0 - c).angle()) + if a * alpha < 0: + if alpha > 0: + alpha = alpha - TAU + else: + alpha = TAU + alpha + if between(alpha, 0, a) or min(abs(alpha), abs(alpha - a)) < STRAIGHT_TOLERANCE: + return (p - i).mag(), [i.x, i.y] + else: + d1 = (p - P0).mag() + d2 = (p - P2).mag() + if d1 < d2: + return d1, [P0.x, P0.y] + else: + return d2, [P2.x, P2.y] + + +def csp_to_arc_distance(sp1, sp2, arc1, arc2, tolerance=0.01): # arc = [start,end,center,alpha] + n = 10 + i = 0 + d = (0, [0, 0]) + d1 = (0, [0, 0]) + dl = 0 + while i < 1 or (abs(d1[0] - dl[0]) > tolerance and i < 4): + i += 1 + dl = d1 * 1 + for j in range(n + 1): + t = float(j) / n + p = csp_at_t(sp1, sp2, t) + d = min(point_to_arc_distance(p, arc1), point_to_arc_distance(p, arc2)) + d1 = max(d1, d) + n = n * 2 + return d1[0] + + +def csp_point_inside_bound(sp1, sp2, p): + bez = [sp1[1], sp1[2], sp2[0], sp2[1]] + x, y = p + c = 0 + # CLT added test of x in range + xmin = 1e100 + xmax = -1e100 + for i in range(4): + [x0, y0] = bez[i - 1] + [x1, y1] = bez[i] + xmin = min(xmin, x0) + xmax = max(xmax, x0) + if x0 - x1 != 0 and (y - y0) * (x1 - x0) >= (x - x0) * (y1 - y0) and x > min(x0, x1) and x <= max(x0, x1): + c += 1 + return xmin <= x <= xmax and c % 2 == 0 + + +def line_line_intersect(p1, p2, p3, p4): # Return only true intersection. + if (p1[0] == p2[0] and p1[1] == p2[1]) or (p3[0] == p4[0] and p3[1] == p4[1]): + return False + x = (p2[0] - p1[0]) * (p4[1] - p3[1]) - (p2[1] - p1[1]) * (p4[0] - p3[0]) + if x == 0: # Lines are parallel + if (p3[0] - p1[0]) * (p2[1] - p1[1]) == (p3[1] - p1[1]) * (p2[0] - p1[0]): + if p3[0] != p4[0]: + t11 = (p1[0] - p3[0]) / (p4[0] - p3[0]) + t12 = (p2[0] - p3[0]) / (p4[0] - p3[0]) + t21 = (p3[0] - p1[0]) / (p2[0] - p1[0]) + t22 = (p4[0] - p1[0]) / (p2[0] - p1[0]) + else: + t11 = (p1[1] - p3[1]) / (p4[1] - p3[1]) + t12 = (p2[1] - p3[1]) / (p4[1] - p3[1]) + t21 = (p3[1] - p1[1]) / (p2[1] - p1[1]) + t22 = (p4[1] - p1[1]) / (p2[1] - p1[1]) + return "Overlap" if (0 <= t11 <= 1 or 0 <= t12 <= 1) and (0 <= t21 <= 1 or 0 <= t22 <= 1) else False + else: + return False + else: + return ( + 0 <= ((p4[0] - p3[0]) * (p1[1] - p3[1]) - (p4[1] - p3[1]) * (p1[0] - p3[0])) / x <= 1 and + 0 <= ((p2[0] - p1[0]) * (p1[1] - p3[1]) - (p2[1] - p1[1]) * (p1[0] - p3[0])) / x <= 1) + + +def line_line_intersection_points(p1, p2, p3, p4): # Return only points [ (x,y) ] + if (p1[0] == p2[0] and p1[1] == p2[1]) or (p3[0] == p4[0] and p3[1] == p4[1]): + return [] + x = (p2[0] - p1[0]) * (p4[1] - p3[1]) - (p2[1] - p1[1]) * (p4[0] - p3[0]) + if x == 0: # Lines are parallel + if (p3[0] - p1[0]) * (p2[1] - p1[1]) == (p3[1] - p1[1]) * (p2[0] - p1[0]): + if p3[0] != p4[0]: + t11 = (p1[0] - p3[0]) / (p4[0] - p3[0]) + t12 = (p2[0] - p3[0]) / (p4[0] - p3[0]) + t21 = (p3[0] - p1[0]) / (p2[0] - p1[0]) + t22 = (p4[0] - p1[0]) / (p2[0] - p1[0]) + else: + t11 = (p1[1] - p3[1]) / (p4[1] - p3[1]) + t12 = (p2[1] - p3[1]) / (p4[1] - p3[1]) + t21 = (p3[1] - p1[1]) / (p2[1] - p1[1]) + t22 = (p4[1] - p1[1]) / (p2[1] - p1[1]) + res = [] + if (0 <= t11 <= 1 or 0 <= t12 <= 1) and (0 <= t21 <= 1 or 0 <= t22 <= 1): + if 0 <= t11 <= 1: + res += [p1] + if 0 <= t12 <= 1: + res += [p2] + if 0 <= t21 <= 1: + res += [p3] + if 0 <= t22 <= 1: + res += [p4] + return res + else: + return [] + else: + t1 = ((p4[0] - p3[0]) * (p1[1] - p3[1]) - (p4[1] - p3[1]) * (p1[0] - p3[0])) / x + t2 = ((p2[0] - p1[0]) * (p1[1] - p3[1]) - (p2[1] - p1[1]) * (p1[0] - p3[0])) / x + if 0 <= t1 <= 1 and 0 <= t2 <= 1: + return [[p1[0] * (1 - t1) + p2[0] * t1, p1[1] * (1 - t1) + p2[1] * t1]] + else: + return [] + + +def point_to_point_d2(a, b): + return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + + +def point_to_point_d(a, b): + return math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) + + +def point_to_line_segment_distance_2(p1, p2, p3): + # p1 - point, p2,p3 - line segment + # draw_pointer(p1) + w0 = [p1[0] - p2[0], p1[1] - p2[1]] + v = [p3[0] - p2[0], p3[1] - p2[1]] + c1 = w0[0] * v[0] + w0[1] * v[1] + if c1 <= 0: + return w0[0] * w0[0] + w0[1] * w0[1] + c2 = v[0] * v[0] + v[1] * v[1] + if c2 <= c1: + return (p1[0] - p3[0]) ** 2 + (p1[1] - p3[1]) ** 2 + return (p1[0] - p2[0] - v[0] * c1 / c2) ** 2 + (p1[1] - p2[1] - v[1] * c1 / c2) + + +def line_to_line_distance_2(p1, p2, p3, p4): + if line_line_intersect(p1, p2, p3, p4): + return 0 + return min( + point_to_line_segment_distance_2(p1, p3, p4), + point_to_line_segment_distance_2(p2, p3, p4), + point_to_line_segment_distance_2(p3, p1, p2), + point_to_line_segment_distance_2(p4, p1, p2)) + + +def csp_seg_bound_to_csp_seg_bound_max_min_distance(sp1, sp2, sp3, sp4): + bez1 = csp_segment_to_bez(sp1, sp2) + bez2 = csp_segment_to_bez(sp3, sp4) + min_dist = 1e100 + max_dist = 0. + for i in range(4): + if csp_point_inside_bound(sp1, sp2, bez2[i]) or csp_point_inside_bound(sp3, sp4, bez1[i]): + min_dist = 0. + break + for i in range(4): + for j in range(4): + d = line_to_line_distance_2(bez1[i - 1], bez1[i], bez2[j - 1], bez2[j]) + if d < min_dist: + min_dist = d + d = (bez2[j][0] - bez1[i][0]) ** 2 + (bez2[j][1] - bez1[i][1]) ** 2 + if max_dist < d: + max_dist = d + return min_dist, max_dist + + +def csp_reverse(csp): + for i in range(len(csp)): + n = [] + for j in csp[i]: + n = [[j[2][:], j[1][:], j[0][:]]] + n + csp[i] = n[:] + return csp + + +def csp_normalized_slope(sp1, sp2, t): + ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize((sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:])) + if sp1[1] == sp2[1] == sp1[2] == sp2[0]: + return [1., 0.] + f1x = 3 * ax * t * t + 2 * bx * t + cx + f1y = 3 * ay * t * t + 2 * by * t + cy + if abs(f1x * f1x + f1y * f1y) > 1e-9: # LT changed this from 1e-20, which caused problems + l = math.sqrt(f1x * f1x + f1y * f1y) + return [f1x / l, f1y / l] + + if t == 0: + f1x = sp2[0][0] - sp1[1][0] + f1y = sp2[0][1] - sp1[1][1] + if abs(f1x * f1x + f1y * f1y) > 1e-9: # LT changed this from 1e-20, which caused problems + l = math.sqrt(f1x * f1x + f1y * f1y) + return [f1x / l, f1y / l] + else: + f1x = sp2[1][0] - sp1[1][0] + f1y = sp2[1][1] - sp1[1][1] + if f1x * f1x + f1y * f1y != 0: + l = math.sqrt(f1x * f1x + f1y * f1y) + return [f1x / l, f1y / l] + elif t == 1: + f1x = sp2[1][0] - sp1[2][0] + f1y = sp2[1][1] - sp1[2][1] + if abs(f1x * f1x + f1y * f1y) > 1e-9: + l = math.sqrt(f1x * f1x + f1y * f1y) + return [f1x / l, f1y / l] + else: + f1x = sp2[1][0] - sp1[1][0] + f1y = sp2[1][1] - sp1[1][1] + if f1x * f1x + f1y * f1y != 0: + l = math.sqrt(f1x * f1x + f1y * f1y) + return [f1x / l, f1y / l] + else: + return [1., 0.] + + +def csp_normalized_normal(sp1, sp2, t): + nx, ny = csp_normalized_slope(sp1, sp2, t) + return [-ny, nx] + + +def csp_parameterize(sp1, sp2): + return bezierparameterize(csp_segment_to_bez(sp1, sp2)) + + +def csp_concat_subpaths(*s): + def concat(s1, s2): + if not s1: + return s2 + if not s2: + return s1 + if (s1[-1][1][0] - s2[0][1][0]) ** 2 + (s1[-1][1][1] - s2[0][1][1]) ** 2 > 0.00001: + return s1[:-1] + [[s1[-1][0], s1[-1][1], s1[-1][1]], [s2[0][1], s2[0][1], s2[0][2]]] + s2[1:] + else: + return s1[:-1] + [[s1[-1][0], s2[0][1], s2[0][2]]] + s2[1:] + + if len(s) == 0: + return [] + if len(s) == 1: + return s[0] + result = s[0] + for s1 in s[1:]: + result = concat(result, s1) + return result + + +def csp_subpaths_end_to_start_distance2(s1, s2): + return (s1[-1][1][0] - s2[0][1][0]) ** 2 + (s1[-1][1][1] - s2[0][1][1]) ** 2 + + +def csp_clip_by_line(csp, l1, l2): + result = [] + for i in range(len(csp)): + s = csp[i] + intersections = [] + for j in range(1, len(s)): + intersections += [[j, int_] for int_ in csp_line_intersection(l1, l2, s[j - 1], s[j])] + splitted_s = csp_subpath_split_by_points(s, intersections) + for s in splitted_s[:]: + clip = False + for p in csp_true_bounds([s]): + if (l1[1] - l2[1]) * p[0] + (l2[0] - l1[0]) * p[1] + (l1[0] * l2[1] - l2[0] * l1[1]) < -0.01: + clip = True + break + if clip: + splitted_s.remove(s) + result += splitted_s + return result + + +def csp_subpath_line_to(subpath, points, prepend=False): + # Appends subpath with line or polyline. + if len(points) > 0: + if not prepend: + if len(subpath) > 0: + subpath[-1][2] = subpath[-1][1][:] + if type(points[0]) == type([1, 1]): + for p in points: + subpath += [[p[:], p[:], p[:]]] + else: + subpath += [[points, points, points]] + else: + if len(subpath) > 0: + subpath[0][0] = subpath[0][1][:] + if type(points[0]) == type([1, 1]): + for p in points: + subpath = [[p[:], p[:], p[:]]] + subpath + else: + subpath = [[points, points, points]] + subpath + return subpath + + +def csp_join_subpaths(csp): + result = csp[:] + done_smf = True + joined_result = [] + while done_smf: + done_smf = False + while len(result) > 0: + s1 = result[-1][:] + del (result[-1]) + j = 0 + joined_smf = False + while j < len(joined_result): + if csp_subpaths_end_to_start_distance2(joined_result[j], s1) < 0.000001: + joined_result[j] = csp_concat_subpaths(joined_result[j], s1) + done_smf = True + joined_smf = True + break + if csp_subpaths_end_to_start_distance2(s1, joined_result[j]) < 0.000001: + joined_result[j] = csp_concat_subpaths(s1, joined_result[j]) + done_smf = True + joined_smf = True + break + j += 1 + if not joined_smf: + joined_result += [s1[:]] + if done_smf: + result = joined_result[:] + joined_result = [] + return joined_result + + +def triangle_cross(a, b, c): + return (a[0] - b[0]) * (c[1] - b[1]) - (c[0] - b[0]) * (a[1] - b[1]) + + +def csp_segment_convex_hull(sp1, sp2): + a = sp1[1][:] + b = sp1[2][:] + c = sp2[0][:] + d = sp2[1][:] + + abc = triangle_cross(a, b, c) + abd = triangle_cross(a, b, d) + bcd = triangle_cross(b, c, d) + cad = triangle_cross(c, a, d) + if abc == 0 and abd == 0: + return [min(a, b, c, d), max(a, b, c, d)] + if abc == 0: + return [d, min(a, b, c), max(a, b, c)] + if abd == 0: + return [c, min(a, b, d), max(a, b, d)] + if bcd == 0: + return [a, min(b, c, d), max(b, c, d)] + if cad == 0: + return [b, min(c, a, d), max(c, a, d)] + + m1 = abc * abd > 0 + m2 = abc * bcd > 0 + m3 = abc * cad > 0 + + if m1 and m2 and m3: + return [a, b, c] + if m1 and m2 and not m3: + return [a, b, c, d] + if m1 and not m2 and m3: + return [a, b, d, c] + if not m1 and m2 and m3: + return [a, d, b, c] + if m1 and not (m2 and m3): + return [a, b, d] + if not (m1 and m2) and m3: + return [c, a, d] + if not (m1 and m3) and m2: + return [b, c, d] + + raise ValueError("csp_segment_convex_hull happened which is something that shouldn't happen!") + + +################################################################################ +# Bezier additional functions +################################################################################ + +def bez_bounds_intersect(bez1, bez2): + return bounds_intersect(bez_bound(bez2), bez_bound(bez1)) + + +def bez_bound(bez): + return [ + min(bez[0][0], bez[1][0], bez[2][0], bez[3][0]), + min(bez[0][1], bez[1][1], bez[2][1], bez[3][1]), + max(bez[0][0], bez[1][0], bez[2][0], bez[3][0]), + max(bez[0][1], bez[1][1], bez[2][1], bez[3][1]), + ] + + +def bounds_intersect(a, b): + return not ((a[0] > b[2]) or (b[0] > a[2]) or (a[1] > b[3]) or (b[1] > a[3])) + + +def tpoint(xy1, xy2, t): + (x1, y1) = xy1 + (x2, y2) = xy2 + return [x1 + t * (x2 - x1), y1 + t * (y2 - y1)] + + +def bez_split(a, t=0.5): + a1 = tpoint(a[0], a[1], t) + at = tpoint(a[1], a[2], t) + b2 = tpoint(a[2], a[3], t) + a2 = tpoint(a1, at, t) + b1 = tpoint(b2, at, t) + a3 = tpoint(a2, b1, t) + return [a[0], a1, a2, a3], [a3, b1, b2, a[3]] + + +################################################################################ +# Some vector functions +################################################################################ + +def normalize(xy): + (x, y) = xy + l = math.sqrt(x ** 2 + y ** 2) + if l == 0: + return [0., 0.] + else: + return [x / l, y / l] + + +def cross(a, b): + return a[1] * b[0] - a[0] * b[1] + + +def dot(a, b): + return a[0] * b[0] + a[1] * b[1] + + +def rotate_ccw(d): + return [-d[1], d[0]] + + +def rotate_cw(d): + return [d[1], -d[0]] + + +def vectors_ccw(a, b): + return a[0] * b[1] - b[0] * a[1] < 0 + + +################################################################################ +# Common functions +################################################################################ + +def inv_2x2(a): # invert matrix 2x2 + det = a[0][0] * a[1][1] - a[1][0] * a[0][1] + if det == 0: + return None + return [ + [a[1][1] / det, -a[0][1] / det], + [-a[1][0] / det, a[0][0] / det] + ] + + +def small(a): + global small_tolerance + return abs(a) < small_tolerance + + +def atan2(*arg): + if len(arg) == 1 and (type(arg[0]) == type([0., 0.]) or type(arg[0]) == type((0., 0.))): + return (math.pi / 2 - math.atan2(arg[0][0], arg[0][1])) % TAU + elif len(arg) == 2: + return (math.pi / 2 - math.atan2(arg[0], arg[1])) % TAU + else: + raise ValueError("Bad argumets for atan! ({})".format(*arg)) + + +def draw_text(text, x, y, group=None, style=None, font_size=10, gcodetools_tag=None): + if style is None: + style = "font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;fill:#000000;fill-opacity:1;stroke:none;" + style += "font-size:{:f}px;".format(font_size) + attributes = {'x': str(x), 'y': str(y), 'style': style} + if gcodetools_tag is not None: + attributes["gcodetools"] = str(gcodetools_tag) + + if group is None: + group = options.doc_root + + text_elem = group.add(TextElement(**attributes)) + text_elem.set("xml:space", "preserve") + text = str(text).split("\n") + for string in text: + span = text_elem.add(Tspan(x=str(x), y=str(y))) + span.set('sodipodi:role', 'line') + y += font_size + span.text = str(string) + + +def draw_csp(csp, stroke="#f00", fill="none", comment="", width=0.354, group=None, style=None): + if group is None: + group = options.doc_root + node = group.add(PathElement()) + + node.style = style if style is not None else \ + {'fill': fill, 'fill-opacity': 1, 'stroke': stroke, 'stroke-width': width} + + node.path = CubicSuperPath(csp) + + if comment != '': + node.set('comment', comment) + + return node + + +def draw_pointer(x, color="#f00", figure="cross", group=None, comment="", fill=None, width=.1, size=10., text=None, font_size=None, pointer_type=None, attrib=None): + size = size / 2 + if attrib is None: + attrib = {} + if pointer_type is None: + pointer_type = "Pointer" + attrib["gcodetools"] = pointer_type + if group is None: + group = options.self.svg.get_current_layer() + if text is not None: + if font_size is None: + font_size = 7 + group = group.add(Group(gcodetools=pointer_type + " group")) + draw_text(text, x[0] + size * 2.2, x[1] - size, group=group, font_size=font_size) + if figure == "line": + s = "" + for i in range(1, len(x) / 2): + s += " {}, {} ".format(x[i * 2], x[i * 2 + 1]) + attrib.update({"d": "M {},{} L {}".format(x[0], x[1], s), "style": "fill:none;stroke:{};stroke-width:{:f};".format(color, width), "comment": str(comment)}) + elif figure == "arrow": + if fill is None: + fill = "#12b3ff" + fill_opacity = "0.8" + d = "m {},{} ".format(x[0], x[1]) + re.sub("([0-9\\-.e]+)", (lambda match: str(float(match.group(1)) * size * 2.)), "0.88464,-0.40404 c -0.0987,-0.0162 -0.186549,-0.0589 -0.26147,-0.1173 l 0.357342,-0.35625 c 0.04631,-0.039 0.0031,-0.13174 -0.05665,-0.12164 -0.0029,-1.4e-4 -0.0058,-1.4e-4 -0.0087,0 l -2.2e-5,2e-5 c -0.01189,0.004 -0.02257,0.0119 -0.0305,0.0217 l -0.357342,0.35625 c -0.05818,-0.0743 -0.102813,-0.16338 -0.117662,-0.26067 l -0.409636,0.88193 z") + attrib.update({"d": d, "style": "fill:{};stroke:none;fill-opacity:{};".format(fill, fill_opacity), "comment": str(comment)}) + else: + attrib.update({"d": "m {},{} l {:f},{:f} {:f},{:f} {:f},{:f} {:f},{:f} , {:f},{:f}".format(x[0], x[1], size, size, -2 * size, -2 * size, size, size, size, -size, -2 * size, 2 * size), "style": "fill:none;stroke:{};stroke-width:{:f};".format(color, width), "comment": str(comment)}) + group.add(PathElement(**attrib)) + + +def straight_segments_intersection(a, b, true_intersection=True): # (True intersection means check ta and tb are in [0,1]) + ax = a[0][0] + bx = a[1][0] + cx = b[0][0] + dx = b[1][0] + ay = a[0][1] + by = a[1][1] + cy = b[0][1] + dy = b[1][1] + if (ax == bx and ay == by) or (cx == dx and cy == dy): + return False, 0, 0 + if (bx - ax) * (dy - cy) - (by - ay) * (dx - cx) == 0: # Lines are parallel + ta = (ax - cx) / (dx - cx) if cx != dx else (ay - cy) / (dy - cy) + tb = (bx - cx) / (dx - cx) if cx != dx else (by - cy) / (dy - cy) + tc = (cx - ax) / (bx - ax) if ax != bx else (cy - ay) / (by - ay) + td = (dx - ax) / (bx - ax) if ax != bx else (dy - ay) / (by - ay) + return ("Overlap" if 0 <= ta <= 1 or 0 <= tb <= 1 or 0 <= tc <= 1 or 0 <= td <= 1 or not true_intersection else False), (ta, tb), (tc, td) + else: + ta = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / ((bx - ax) * (dy - cy) - (by - ay) * (dx - cx)) + tb = (ax - cx + ta * (bx - ax)) / (dx - cx) if dx != cx else (ay - cy + ta * (by - ay)) / (dy - cy) + return (0 <= ta <= 1 and 0 <= tb <= 1 or not true_intersection), ta, tb + + +def between(c, x, y): + return x - STRAIGHT_TOLERANCE <= c <= y + STRAIGHT_TOLERANCE or y - STRAIGHT_TOLERANCE <= c <= x + STRAIGHT_TOLERANCE + + +def cubic_solver_real(a, b, c, d): + # returns only real roots of a cubic equation. + roots = cubic_solver(a, b, c, d) + res = [] + for root in roots: + if type(root) is complex: + if -1e-10 < root.imag < 1e-10: + res.append(root.real) + else: + res.append(root) + return res + + +def cubic_solver(a, b, c, d): + if a != 0: + # Monics formula see http://en.wikipedia.org/wiki/Cubic_function#Monic_formula_of_roots + a, b, c = (b / a, c / a, d / a) + m = 2 * a ** 3 - 9 * a * b + 27 * c + k = a ** 2 - 3 * b + n = m ** 2 - 4 * k ** 3 + w1 = -.5 + .5 * cmath.sqrt(3) * 1j + w2 = -.5 - .5 * cmath.sqrt(3) * 1j + if n >= 0: + t = m + math.sqrt(n) + m1 = pow(t / 2, 1. / 3) if t >= 0 else -pow(-t / 2, 1. / 3) + t = m - math.sqrt(n) + n1 = pow(t / 2, 1. / 3) if t >= 0 else -pow(-t / 2, 1. / 3) + else: + m1 = pow(complex((m + cmath.sqrt(n)) / 2), 1. / 3) + n1 = pow(complex((m - cmath.sqrt(n)) / 2), 1. / 3) + x1 = -1. / 3 * (a + m1 + n1) + x2 = -1. / 3 * (a + w1 * m1 + w2 * n1) + x3 = -1. / 3 * (a + w2 * m1 + w1 * n1) + return [x1, x2, x3] + elif b != 0: + det = c ** 2 - 4 * b * d + if det > 0: + return [(-c + math.sqrt(det)) / (2 * b), (-c - math.sqrt(det)) / (2 * b)] + elif d == 0: + return [-c / (b * b)] + else: + return [(-c + cmath.sqrt(det)) / (2 * b), (-c - cmath.sqrt(det)) / (2 * b)] + elif c != 0: + return [-d / c] + else: + return [] + + +################################################################################ +# print_ prints any arguments into specified log file +################################################################################ + +def print_(*arg): + with open(options.log_filename, "ab") as f: + for s in arg: + s = unicode(s).encode('unicode_escape') + b" " + f.write(s) + f.write(b"\n") + + +################################################################################ +# Point (x,y) operations +################################################################################ +class P(object): + def __init__(self, x, y=None): + if not y is None: + self.x = float(x) + self.y = float(y) + else: + self.x = float(x[0]) + self.y = float(x[1]) + + def __add__(self, other): + return P(self.x + other.x, self.y + other.y) + + def __sub__(self, other): + return P(self.x - other.x, self.y - other.y) + + def __neg__(self): + return P(-self.x, -self.y) + + def __mul__(self, other): + if isinstance(other, P): + return self.x * other.x + self.y * other.y + return P(self.x * other, self.y * other) + + __rmul__ = __mul__ + + def __div__(self, other): + return P(self.x / other, self.y / other) + + def __truediv__(self, other): + return self.__div__(other) + + def mag(self): + return math.hypot(self.x, self.y) + + def unit(self): + h_mag = self.mag() + if h_mag: + return self / h_mag + return P(0, 0) + + def dot(self, other): + return self.x * other.x + self.y * other.y + + def rot(self, theta): + c = math.cos(theta) + s = math.sin(theta) + return P(self.x * c - self.y * s, self.x * s + self.y * c) + + def angle(self): + return math.atan2(self.y, self.x) + + def __repr__(self): + return '{:f},{:f}'.format(self.x, self.y) + + def pr(self): + return "{:.2f},{:.2f}".format(self.x, self.y) + + def to_list(self): + return [self.x, self.y] + + def ccw(self): + return P(-self.y, self.x) + + def l2(self): + return self.x * self.x + self.y * self.y + + +class Line(object): + def __init__(self, st, end): + if st.__class__ == P: + st = st.to_list() + if end.__class__ == P: + end = end.to_list() + self.st = P(st) + self.end = P(end) + self.l = self.length() + if self.l != 0: + self.n = ((self.end - self.st) / self.l).ccw() + else: + self.n = [0, 1] + + def offset(self, r): + self.st -= self.n * r + self.end -= self.n * r + + def l2(self): + return (self.st - self.end).l2() + + def length(self): + return (self.st - self.end).mag() + + def draw(self, group, style, layer, transform, num=0, reverse_angle=1): + st = gcodetools.transform(self.st.to_list(), layer, True) + end = gcodetools.transform(self.end.to_list(), layer, True) + + attr = {'style': style['line'], + 'd': 'M {},{} L {},{}'.format(st[0], st[1], end[0], end[1]), + "gcodetools": "Preview", + } + if transform: + attr["transform"] = transform + group.add(PathElement(**attr)) + + def intersect(self, b): + if b.__class__ == Line: + if self.l < 10e-8 or b.l < 10e-8: + return [] + v1 = self.end - self.st + v2 = b.end - b.st + x = v1.x * v2.y - v2.x * v1.y + if x == 0: + # lines are parallel + res = [] + + if (self.st.x - b.st.x) * v1.y - (self.st.y - b.st.y) * v1.x == 0: + # lines are the same + if v1.x != 0: + if 0 <= (self.st.x - b.st.x) / v2.x <= 1: + res.append(self.st) + if 0 <= (self.end.x - b.st.x) / v2.x <= 1: + res.append(self.end) + if 0 <= (b.st.x - self.st.x) / v1.x <= 1: + res.append(b.st) + if 0 <= (b.end.x - b.st.x) / v1.x <= 1: + res.append(b.end) + else: + if 0 <= (self.st.y - b.st.y) / v2.y <= 1: + res.append(self.st) + if 0 <= (self.end.y - b.st.y) / v2.y <= 1: + res.append(self.end) + if 0 <= (b.st.y - self.st.y) / v1.y <= 1: + res.append(b.st) + if 0 <= (b.end.y - b.st.y) / v1.y <= 1: + res.append(b.end) + return res + else: + t1 = (-v1.x * (b.end.y - self.end.y) + v1.y * (b.end.x - self.end.x)) / x + t2 = (-v1.y * (self.st.x - b.st.x) + v1.x * (self.st.y - b.st.y)) / x + + gcodetools.error(str((x, t1, t2))) + if 0 <= t1 <= 1 and 0 <= t2 <= 1: + return [self.st + v1 * t1] + else: + return [] + else: + return [] + + +################################################################################ +# +# Offset function +# +# This function offsets given cubic super path. +# It's based on src/livarot/PathOutline.cpp from Inkscape's source code. +# +# +################################################################################ +def csp_offset(csp, r): + offset_tolerance = 0.05 + offset_subdivision_depth = 10 + time_ = time.time() + time_start = time_ + print_("Offset start at {}".format(time_)) + print_("Offset radius {}".format(r)) + + def csp_offset_segment(sp1, sp2, r): + result = [] + t = csp_get_t_at_curvature(sp1, sp2, 1 / r) + if len(t) == 0: + t = [0., 1.] + t.sort() + if t[0] > .00000001: + t = [0.] + t + if t[-1] < .99999999: + t.append(1.) + for st, end in zip(t, t[1:]): + c = csp_curvature_at_t(sp1, sp2, (st + end) / 2) + sp = csp_split_by_two_points(sp1, sp2, st, end) + if sp[1] != sp[2]: + if c > 1 / r and r < 0 or c < 1 / r and r > 0: + offset = offset_segment_recursion(sp[1], sp[2], r, offset_subdivision_depth, offset_tolerance) + else: # This part will be clipped for sure... TODO Optimize it... + offset = offset_segment_recursion(sp[1], sp[2], r, offset_subdivision_depth, offset_tolerance) + + if not result: + result = offset[:] + else: + if csp_subpaths_end_to_start_distance2(result, offset) < 0.0001: + result = csp_concat_subpaths(result, offset) + else: + + intersection = csp_get_subapths_last_first_intersection(result, offset) + if intersection: + i, t1, j, t2 = intersection + sp1_, sp2_, sp3_ = csp_split(result[i - 1], result[i], t1) + result = result[:i - 1] + [sp1_, sp2_] + sp1_, sp2_, sp3_ = csp_split(offset[j - 1], offset[j], t2) + result = csp_concat_subpaths(result, [sp2_, sp3_] + offset[j + 1:]) + else: + pass # ??? + return result + + def create_offset_segment(sp1, sp2, r): + # See Gernot Hoffmann "Bezier Curves" p.34 -> 7.1 Bezier Offset Curves + p0 = P(sp1[1]) + p1 = P(sp1[2]) + p2 = P(sp2[0]) + p3 = P(sp2[1]) + + s0 = p1 - p0 + s1 = p2 - p1 + s3 = p3 - p2 + + n0 = s0.ccw().unit() if s0.l2() != 0 else P(csp_normalized_normal(sp1, sp2, 0)) + n3 = s3.ccw().unit() if s3.l2() != 0 else P(csp_normalized_normal(sp1, sp2, 1)) + n1 = s1.ccw().unit() if s1.l2() != 0 else (n0.unit() + n3.unit()).unit() + + q0 = p0 + r * n0 + q3 = p3 + r * n3 + c = csp_curvature_at_t(sp1, sp2, 0) + q1 = q0 + (p1 - p0) * (1 - (r * c if abs(c) < 100 else 0)) + c = csp_curvature_at_t(sp1, sp2, 1) + q2 = q3 + (p2 - p3) * (1 - (r * c if abs(c) < 100 else 0)) + + return [[q0.to_list(), q0.to_list(), q1.to_list()], [q2.to_list(), q3.to_list(), q3.to_list()]] + + def csp_get_subapths_last_first_intersection(s1, s2): + _break = False + for i in range(1, len(s1)): + sp11 = s1[-i - 1] + sp12 = s1[-i] + for j in range(1, len(s2)): + sp21 = s2[j - 1] + sp22 = s2[j] + intersection = csp_segments_true_intersection(sp11, sp12, sp21, sp22) + if intersection: + _break = True + break + if _break: + break + if _break: + intersection = max(intersection) + return [len(s1) - i, intersection[0], j, intersection[1]] + else: + return [] + + def csp_join_offsets(prev, next, sp1, sp2, sp1_l, sp2_l, r): + if len(next) > 1: + if (P(prev[-1][1]) - P(next[0][1])).l2() < 0.001: + return prev, [], next + intersection = csp_get_subapths_last_first_intersection(prev, next) + if intersection: + i, t1, j, t2 = intersection + sp1_, sp2_, sp3_ = csp_split(prev[i - 1], prev[i], t1) + sp3_, sp4_, sp5_ = csp_split(next[j - 1], next[j], t2) + return prev[:i - 1] + [sp1_, sp2_], [], [sp4_, sp5_] + next[j + 1:] + + # Offsets do not intersect... will add an arc... + start = (P(csp_at_t(sp1_l, sp2_l, 1.)) + r * P(csp_normalized_normal(sp1_l, sp2_l, 1.))).to_list() + end = (P(csp_at_t(sp1, sp2, 0.)) + r * P(csp_normalized_normal(sp1, sp2, 0.))).to_list() + arc = csp_from_arc(start, end, sp1[1], r, csp_normalized_slope(sp1_l, sp2_l, 1.)) + if not arc: + return prev, [], next + else: + # Clip prev by arc + if csp_subpaths_end_to_start_distance2(prev, arc) > 0.00001: + intersection = csp_get_subapths_last_first_intersection(prev, arc) + if intersection: + i, t1, j, t2 = intersection + sp1_, sp2_, sp3_ = csp_split(prev[i - 1], prev[i], t1) + sp3_, sp4_, sp5_ = csp_split(arc[j - 1], arc[j], t2) + prev = prev[:i - 1] + [sp1_, sp2_] + arc = [sp4_, sp5_] + arc[j + 1:] + # Clip next by arc + if not next: + return prev, [], arc + if csp_subpaths_end_to_start_distance2(arc, next) > 0.00001: + intersection = csp_get_subapths_last_first_intersection(arc, next) + if intersection: + i, t1, j, t2 = intersection + sp1_, sp2_, sp3_ = csp_split(arc[i - 1], arc[i], t1) + sp3_, sp4_, sp5_ = csp_split(next[j - 1], next[j], t2) + arc = arc[:i - 1] + [sp1_, sp2_] + next = [sp4_, sp5_] + next[j + 1:] + + return prev, arc, next + + def offset_segment_recursion(sp1, sp2, r, depth, tolerance): + sp1_r, sp2_r = create_offset_segment(sp1, sp2, r) + err = max( + csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .25)) + P(csp_normalized_normal(sp1, sp2, .25)) * r).to_list())[0], + csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .50)) + P(csp_normalized_normal(sp1, sp2, .50)) * r).to_list())[0], + csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .75)) + P(csp_normalized_normal(sp1, sp2, .75)) * r).to_list())[0], + ) + + if err > tolerance ** 2 and depth > 0: + if depth > offset_subdivision_depth - 2: + t = csp_max_curvature(sp1, sp2) + t = max(.1, min(.9, t)) + else: + t = .5 + sp3, sp4, sp5 = csp_split(sp1, sp2, t) + r1 = offset_segment_recursion(sp3, sp4, r, depth - 1, tolerance) + r2 = offset_segment_recursion(sp4, sp5, r, depth - 1, tolerance) + return r1[:-1] + [[r1[-1][0], r1[-1][1], r2[0][2]]] + r2[1:] + else: + return [sp1_r, sp2_r] + + ############################################################################ + # Some small definitions + ############################################################################ + csp_len = len(csp) + + ############################################################################ + # Prepare the path + ############################################################################ + # Remove all small segments (segment length < 0.001) + + for i in xrange(len(csp)): + for j in xrange(len(csp[i])): + sp = csp[i][j] + if (P(sp[1]) - P(sp[0])).mag() < 0.001: + csp[i][j][0] = sp[1] + if (P(sp[2]) - P(sp[0])).mag() < 0.001: + csp[i][j][2] = sp[1] + for i in xrange(len(csp)): + for j in xrange(1, len(csp[i])): + if cspseglength(csp[i][j - 1], csp[i][j]) < 0.001: + csp[i] = csp[i][:j] + csp[i][j + 1:] + if cspseglength(csp[i][-1], csp[i][0]) > 0.001: + csp[i][-1][2] = csp[i][-1][1] + csp[i] += [[csp[i][0][1], csp[i][0][1], csp[i][0][1]]] + + # TODO Get rid of self intersections. + + original_csp = csp[:] + # Clip segments which has curvature>1/r. Because their offset will be self-intersecting and very nasty. + + print_("Offset prepared the path in {}".format(time.time() - time_)) + print_("Path length = {}".format(sum([len(i) for i in csp]))) + time_ = time.time() + + ############################################################################ + # Offset + ############################################################################ + # Create offsets for all segments in the path. And join them together inside each subpath. + unclipped_offset = [[] for i in xrange(csp_len)] + + intersection = [[] for i in xrange(csp_len)] + for i in xrange(csp_len): + subpath = csp[i] + subpath_offset = [] + for sp1, sp2 in zip(subpath, subpath[1:]): + segment_offset = csp_offset_segment(sp1, sp2, r) + if not subpath_offset: + subpath_offset = segment_offset + + prev_l = len(subpath_offset) + else: + prev, arc, next = csp_join_offsets(subpath_offset[-prev_l:], segment_offset, sp1, sp2, sp1_l, sp2_l, r) + + subpath_offset = csp_concat_subpaths(subpath_offset[:-prev_l + 1], prev, arc, next) + prev_l = len(next) + sp1_l = sp1[:] + sp2_l = sp2[:] + + # Join last and first offsets togother to close the curve + + prev, arc, next = csp_join_offsets(subpath_offset[-prev_l:], subpath_offset[:2], subpath[0], subpath[1], sp1_l, sp2_l, r) + subpath_offset[:2] = next[:] + subpath_offset = csp_concat_subpaths(subpath_offset[:-prev_l + 1], prev, arc) + + # Collect subpath's offset and save it to unclipped offset list. + unclipped_offset[i] = subpath_offset[:] + + print_("Offsetted path in {}".format(time.time() - time_)) + time_ = time.time() + + ############################################################################ + # Now to the clipping. + ############################################################################ + # First of all find all intersection's between all segments of all offset subpaths, including self intersections. + + # TODO define offset tolerance here + global small_tolerance + small_tolerance = 0.01 + summ = 0 + summ1 = 0 + for subpath_i in xrange(csp_len): + for subpath_j in xrange(subpath_i, csp_len): + subpath = unclipped_offset[subpath_i] + subpath1 = unclipped_offset[subpath_j] + for i in xrange(1, len(subpath)): + # If subpath_i==subpath_j we are looking for self intersections, so + # we'll need search intersections only for xrange(i,len(subpath1)) + for j in (xrange(i, len(subpath1)) if subpath_i == subpath_j else xrange(len(subpath1))): + if subpath_i == subpath_j and j == i: + # Find self intersections of a segment + sp1, sp2, sp3 = csp_split(subpath[i - 1], subpath[i], .5) + intersections = csp_segments_intersection(sp1, sp2, sp2, sp3) + summ += 1 + for t in intersections: + summ1 += 1 + if not (small(t[0] - 1) and small(t[1])) and 0 <= t[0] <= 1 and 0 <= t[1] <= 1: + intersection[subpath_i] += [[i, t[0] / 2], [j, t[1] / 2 + .5]] + else: + intersections = csp_segments_intersection(subpath[i - 1], subpath[i], subpath1[j - 1], subpath1[j]) + summ += 1 + for t in intersections: + summ1 += 1 + # TODO tolerance dependence to cpsp_length(t) + if len(t) == 2 and 0 <= t[0] <= 1 and 0 <= t[1] <= 1 and not ( + subpath_i == subpath_j and ( + (j - i - 1) % (len(subpath) - 1) == 0 and small(t[0] - 1) and small(t[1]) or + (i - j - 1) % (len(subpath) - 1) == 0 and small(t[1] - 1) and small(t[0]))): + intersection[subpath_i] += [[i, t[0]]] + intersection[subpath_j] += [[j, t[1]]] + + elif len(t) == 5 and t[4] == "Overlap": + intersection[subpath_i] += [[i, t[0]], [i, t[1]]] + intersection[subpath_j] += [[j, t[1]], [j, t[3]]] + + print_("Intersections found in {}".format(time.time() - time_)) + print_("Examined {} segments".format(summ)) + print_("found {} intersections".format(summ1)) + time_ = time.time() + + ######################################################################## + # Split unclipped offset by intersection points into splitted_offset + ######################################################################## + splitted_offset = [] + for i in xrange(csp_len): + subpath = unclipped_offset[i] + if len(intersection[i]) > 0: + parts = csp_subpath_split_by_points(subpath, intersection[i]) + # Close parts list to close path (The first and the last parts are joined together) + if [1, 0.] not in intersection[i]: + parts[0][0][0] = parts[-1][-1][0] + parts[0] = csp_concat_subpaths(parts[-1], parts[0]) + splitted_offset += parts[:-1] + else: + splitted_offset += parts[:] + else: + splitted_offset += [subpath[:]] + + print_("Split in {}".format(time.time() - time_)) + time_ = time.time() + + ######################################################################## + # Clipping + ######################################################################## + result = [] + for subpath_i in range(len(splitted_offset)): + clip = False + s1 = splitted_offset[subpath_i] + for subpath_j in range(len(splitted_offset)): + s2 = splitted_offset[subpath_j] + if (P(s1[0][1]) - P(s2[-1][1])).l2() < 0.0001 and ((subpath_i + 1) % len(splitted_offset) != subpath_j): + if dot(csp_normalized_normal(s2[-2], s2[-1], 1.), csp_normalized_slope(s1[0], s1[1], 0.)) * r < -0.0001: + clip = True + break + if (P(s2[0][1]) - P(s1[-1][1])).l2() < 0.0001 and ((subpath_j + 1) % len(splitted_offset) != subpath_i): + if dot(csp_normalized_normal(s2[0], s2[1], 0.), csp_normalized_slope(s1[-2], s1[-1], 1.)) * r > 0.0001: + clip = True + break + + if not clip: + result += [s1[:]] + elif options.offset_draw_clippend_path: + draw_csp([s1], width=.1) + draw_pointer(csp_at_t(s2[-2], s2[-1], 1.) + + (P(csp_at_t(s2[-2], s2[-1], 1.)) + P(csp_normalized_normal(s2[-2], s2[-1], 1.)) * 10).to_list(), "Green", "line") + draw_pointer(csp_at_t(s1[0], s1[1], 0.) + + (P(csp_at_t(s1[0], s1[1], 0.)) + P(csp_normalized_slope(s1[0], s1[1], 0.)) * 10).to_list(), "Red", "line") + + # Now join all together and check closure and orientation of result + joined_result = csp_join_subpaths(result) + # Check if each subpath from joined_result is closed + + for s in joined_result[:]: + if csp_subpaths_end_to_start_distance2(s, s) > 0.001: + # Remove open parts + if options.offset_draw_clippend_path: + draw_csp([s], width=1) + draw_pointer(s[0][1], comment=csp_subpaths_end_to_start_distance2(s, s)) + draw_pointer(s[-1][1], comment=csp_subpaths_end_to_start_distance2(s, s)) + joined_result.remove(s) + else: + # Remove small parts + minx, miny, maxx, maxy = csp_true_bounds([s]) + if (minx[0] - maxx[0]) ** 2 + (miny[1] - maxy[1]) ** 2 < 0.1: + joined_result.remove(s) + print_("Clipped and joined path in {}".format(time.time() - time_)) + + ######################################################################## + # Now to the Dummy clipping: remove parts from split offset if their + # centers are closer to the original path than offset radius. + ######################################################################## + + if abs(r * .01) < 1: + r1 = (0.99 * r) ** 2 + r2 = (1.01 * r) ** 2 + else: + r1 = (abs(r) - 1) ** 2 + r2 = (abs(r) + 1) ** 2 + + for s in joined_result[:]: + dist = csp_to_point_distance(original_csp, s[int(len(s) / 2)][1], dist_bounds=[r1, r2]) + if not r1 < dist[0] < r2: + joined_result.remove(s) + if options.offset_draw_clippend_path: + draw_csp([s], comment=math.sqrt(dist[0])) + draw_pointer(csp_at_t(csp[dist[1]][dist[2] - 1], csp[dist[1]][dist[2]], dist[3]) + s[int(len(s) / 2)][1], "blue", "line", comment=[math.sqrt(dist[0]), i, j, sp]) + + print_("-----------------------------") + print_("Total offset time {}".format(time.time() - time_start)) + print_() + return joined_result + + +################################################################################ +# +# Biarc function +# +# Calculates biarc approximation of cubic super path segment +# splits segment if needed or approximates it with straight line +# +################################################################################ +def biarc(sp1, sp2, z1, z2, depth=0): + def biarc_split(sp1, sp2, z1, z2, depth): + if depth < options.biarc_max_split_depth: + sp1, sp2, sp3 = csp_split(sp1, sp2) + l1 = cspseglength(sp1, sp2) + l2 = cspseglength(sp2, sp3) + if l1 + l2 == 0: + zm = z1 + else: + zm = z1 + (z2 - z1) * l1 / (l1 + l2) + return biarc(sp1, sp2, z1, zm, depth + 1) + biarc(sp2, sp3, zm, z2, depth + 1) + else: + return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]] + + P0 = P(sp1[1]) + P4 = P(sp2[1]) + TS = (P(sp1[2]) - P0) + TE = -(P(sp2[0]) - P4) + v = P0 - P4 + tsa = TS.angle() + tea = TE.angle() + va = v.angle() + if TE.mag() < STRAIGHT_DISTANCE_TOLERANCE and TS.mag() < STRAIGHT_DISTANCE_TOLERANCE: + # Both tangents are zero - line straight + return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]] + if TE.mag() < STRAIGHT_DISTANCE_TOLERANCE: + TE = -(TS + v).unit() + r = TS.mag() / v.mag() * 2 + elif TS.mag() < STRAIGHT_DISTANCE_TOLERANCE: + TS = -(TE + v).unit() + r = 1 / (TE.mag() / v.mag() * 2) + else: + r = TS.mag() / TE.mag() + TS = TS.unit() + TE = TE.unit() + tang_are_parallel = ((tsa - tea) % math.pi < STRAIGHT_TOLERANCE or math.pi - (tsa - tea) % math.pi < STRAIGHT_TOLERANCE) + if (tang_are_parallel and + ((v.mag() < STRAIGHT_DISTANCE_TOLERANCE or TE.mag() < STRAIGHT_DISTANCE_TOLERANCE or TS.mag() < STRAIGHT_DISTANCE_TOLERANCE) or + 1 - abs(TS * v / (TS.mag() * v.mag())) < STRAIGHT_TOLERANCE)): + # Both tangents are parallel and start and end are the same - line straight + # or one of tangents still smaller then tolerance + + # Both tangents and v are parallel - line straight + return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]] + + c = v * v + b = 2 * v * (r * TS + TE) + a = 2 * r * (TS * TE - 1) + if v.mag() == 0: + return biarc_split(sp1, sp2, z1, z2, depth) + asmall = abs(a) < 10 ** -10 + bsmall = abs(b) < 10 ** -10 + csmall = abs(c) < 10 ** -10 + if asmall and b != 0: + beta = -c / b + elif csmall and a != 0: + beta = -b / a + elif not asmall: + discr = b * b - 4 * a * c + if discr < 0: + raise ValueError(a, b, c, discr) + disq = discr ** .5 + beta1 = (-b - disq) / 2 / a + beta2 = (-b + disq) / 2 / a + if beta1 * beta2 > 0: + raise ValueError(a, b, c, disq, beta1, beta2) + beta = max(beta1, beta2) + elif asmall and bsmall: + return biarc_split(sp1, sp2, z1, z2, depth) + alpha = beta * r + ab = alpha + beta + P1 = P0 + alpha * TS + P3 = P4 - beta * TE + P2 = (beta / ab) * P1 + (alpha / ab) * P3 + + def calculate_arc_params(P0, P1, P2): + D = (P0 + P2) / 2 + if (D - P1).mag() == 0: + return None, None + R = D - ((D - P0).mag() ** 2 / (D - P1).mag()) * (P1 - D).unit() + p0a = (P0 - R).angle() % (2 * math.pi) + p1a = (P1 - R).angle() % (2 * math.pi) + p2a = (P2 - R).angle() % (2 * math.pi) + alpha = (p2a - p0a) % (2 * math.pi) + if (p0a < p2a and (p1a < p0a or p2a < p1a)) or (p2a < p1a < p0a): + alpha = -2 * math.pi + alpha + if abs(R.x) > 1000000 or abs(R.y) > 1000000 or (R - P0).mag() < options.min_arc_radius ** 2: + return None, None + else: + return R, alpha + + R1, a1 = calculate_arc_params(P0, P1, P2) + R2, a2 = calculate_arc_params(P2, P3, P4) + if R1 is None or R2 is None or (R1 - P0).mag() < STRAIGHT_TOLERANCE or (R2 - P2).mag() < STRAIGHT_TOLERANCE: + return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]] + + d = csp_to_arc_distance(sp1, sp2, [P0, P2, R1, a1], [P2, P4, R2, a2]) + if d > options.biarc_tolerance and depth < options.biarc_max_split_depth: + return biarc_split(sp1, sp2, z1, z2, depth) + else: + if R2.mag() * a2 == 0: + zm = z2 + else: + zm = z1 + (z2 - z1) * (abs(R1.mag() * a1)) / (abs(R2.mag() * a2) + abs(R1.mag() * a1)) + + l = (P0 - P2).l2() + if l < EMC_TOLERANCE_EQUAL ** 2 or l < EMC_TOLERANCE_EQUAL ** 2 * R1.l2() / 100: + # arc should be straight otherwise it could be treated as full circle + arc1 = [sp1[1], 'line', 0, 0, [P2.x, P2.y], [z1, zm]] + else: + arc1 = [sp1[1], 'arc', [R1.x, R1.y], a1, [P2.x, P2.y], [z1, zm]] + + l = (P4 - P2).l2() + if l < EMC_TOLERANCE_EQUAL ** 2 or l < EMC_TOLERANCE_EQUAL ** 2 * R2.l2() / 100: + # arc should be straight otherwise it could be treated as full circle + arc2 = [[P2.x, P2.y], 'line', 0, 0, [P4.x, P4.y], [zm, z2]] + else: + arc2 = [[P2.x, P2.y], 'arc', [R2.x, R2.y], a2, [P4.x, P4.y], [zm, z2]] + + return [arc1, arc2] + + +class Postprocessor(object): + def __init__(self, error_function_handler): + self.error = error_function_handler + self.functions = { + "remap": self.remap, + "remapi": self.remapi, + "scale": self.scale, + "move": self.move, + "flip": self.flip_axis, + "flip_axis": self.flip_axis, + "round": self.round_coordinates, + "parameterize": self.parameterize, + "regex": self.re_sub_on_gcode_lines + } + + def process(self, command): + command = re.sub(r"\\\\", ":#:#:slash:#:#:", command) + command = re.sub(r"\\;", ":#:#:semicolon:#:#:", command) + command = command.split(";") + for s in command: + s = re.sub(":#:#:slash:#:#:", "\\\\", s) + s = re.sub(":#:#:semicolon:#:#:", "\\;", s) + s = s.strip() + if s != "": + self.parse_command(s) + + def parse_command(self, command): + r = re.match(r"([A-Za-z0-9_]+)\s*\(\s*(.*)\)", command) + if not r: + self.error("Parse error while postprocessing.\n(Command: '{}')".format(command), "error") + function = r.group(1).lower() + parameters = r.group(2) + if function in self.functions: + print_("Postprocessor: executing function {}({})".format(function, parameters)) + self.functions[function](parameters) + else: + self.error("Unrecognized function '{}' while postprocessing.\n(Command: '{}')".format(function, command), "error") + + def re_sub_on_gcode_lines(self, parameters): + gcode = self.gcode.split("\n") + self.gcode = "" + try: + for line in gcode: + self.gcode += eval("re.sub({},line)".format(parameters)) + "\n" + + except Exception as ex: + self.error("Bad parameters for regexp. " + "They should be as re.sub pattern and replacement parameters! " + "For example: r\"G0(\\d)\", r\"G\\1\" \n" + "(Parameters: '{}')\n {}".format(parameters, ex), "error") + + def remapi(self, parameters): + self.remap(parameters, case_sensitive=True) + + def remap(self, parameters, case_sensitive=False): + # remap parameters should be like "x->y,y->x" + parameters = parameters.replace("\\,", ":#:#:coma:#:#:") + parameters = parameters.split(",") + pattern = [] + remap = [] + for s in parameters: + s = s.replace(":#:#:coma:#:#:", "\\,") + r = re.match("""\\s*(\'|\")(.*)\\1\\s*->\\s*(\'|\")(.*)\\3\\s*""", s) + if not r: + self.error("Bad parameters for remap.\n(Parameters: '{}')".format(parameters), "error") + pattern += [r.group(2)] + remap += [r.group(4)] + + for i in range(len(pattern)): + if case_sensitive: + self.gcode = ireplace(self.gcode, pattern[i], ":#:#:remap_pattern{}:#:#:".format(i)) + else: + self.gcode = self.gcode.replace(pattern[i], ":#:#:remap_pattern{}:#:#:".format(i)) + + for i in range(len(remap)): + self.gcode = self.gcode.replace(":#:#:remap_pattern{}:#:#:".format(i), remap[i]) + + def transform(self, move, scale): + axis = ["xi", "yj", "zk", "a"] + flip = scale[0] * scale[1] * scale[2] < 0 + gcode = "" + warned = [] + r_scale = scale[0] + plane = "g17" + for s in self.gcode.split("\n"): + # get plane selection: + s_wo_comments = re.sub(r"\([^\)]*\)", "", s) + r = re.search(r"(?i)(G17|G18|G19)", s_wo_comments) + if r: + plane = r.group(1).lower() + if plane == "g17": + r_scale = scale[0] # plane XY -> scale x + if plane == "g18": + r_scale = scale[0] # plane XZ -> scale x + if plane == "g19": + r_scale = scale[1] # plane YZ -> scale y + # Raise warning if scale factors are not the game for G02 and G03 + if plane not in warned: + r = re.search(r"(?i)(G02|G03)", s_wo_comments) + if r: + if plane == "g17" and scale[0] != scale[1]: + self.error("Post-processor: Scale factors for X and Y axis are not the same. G02 and G03 codes will be corrupted.") + if plane == "g18" and scale[0] != scale[2]: + self.error("Post-processor: Scale factors for X and Z axis are not the same. G02 and G03 codes will be corrupted.") + if plane == "g19" and scale[1] != scale[2]: + self.error("Post-processor: Scale factors for Y and Z axis are not the same. G02 and G03 codes will be corrupted.") + warned += [plane] + # Transform + for i in range(len(axis)): + if move[i] != 0 or scale[i] != 1: + for a in axis[i]: + r = re.search(r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)", s) + if r and r.group(3) != "": + s = re.sub(r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)", r"\1 {:f}".format(float(r.group(2) + r.group(3)) * scale[i] + (move[i] if a not in ["i", "j", "k"] else 0)), s) + # scale radius R + if r_scale != 1: + r = re.search(r"(?i)(r)\s*(-?\s*(\d*\.?\d*))", s) + if r and r.group(3) != "": + try: + s = re.sub(r"(?i)(r)\s*(-?)\s*(\d*\.?\d*)", r"\1 {:f}".format(float(r.group(2) + r.group(3)) * r_scale), s) + except: + pass + + gcode += s + "\n" + + self.gcode = gcode + if flip: + self.remapi("'G02'->'G03', 'G03'->'G02'") + + def parameterize(self, parameters): + planes = [] + feeds = {} + coords = [] + gcode = "" + coords_def = {"x": "x", "y": "y", "z": "z", "i": "x", "j": "y", "k": "z", "a": "a"} + for s in self.gcode.split("\n"): + s_wo_comments = re.sub(r"\([^\)]*\)", "", s) + # get Planes + r = re.search(r"(?i)(G17|G18|G19)", s_wo_comments) + if r: + plane = r.group(1).lower() + if plane not in planes: + planes += [plane] + # get Feeds + r = re.search(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", s_wo_comments) + if r: + feed = float(r.group(2) + r.group(3)) + if feed not in feeds: + feeds[feed] = "#" + str(len(feeds) + 20) + + # Coordinates + for c in "xyzijka": + r = re.search(r"(?i)(" + c + r")\s*(-?)\s*(\d*\.?\d*)", s_wo_comments) + if r: + c = coords_def[r.group(1).lower()] + if c not in coords: + coords += [c] + # Add offset parametrization + offset = {"x": "#6", "y": "#7", "z": "#8", "a": "#9"} + for c in coords: + gcode += "{} = 0 ({} axis offset)\n".format(offset[c], c.upper()) + + # Add scale parametrization + if not planes: + planes = ["g17"] + if len(planes) > 1: # have G02 and G03 in several planes scale_x = scale_y = scale_z required + gcode += "#10 = 1 (Scale factor)\n" + scale = {"x": "#10", "i": "#10", "y": "#10", "j": "#10", "z": "#10", "k": "#10", "r": "#10"} + else: + gcode += "#10 = 1 ({} Scale factor)\n".format({"g17": "XY", "g18": "XZ", "g19": "YZ"}[planes[0]]) + gcode += "#11 = 1 ({} Scale factor)\n".format({"g17": "Z", "g18": "Y", "g19": "X"}[planes[0]]) + scale = {"x": "#10", "i": "#10", "y": "#10", "j": "#10", "z": "#10", "k": "#10", "r": "#10"} + if "g17" in planes: + scale["z"] = "#11" + scale["k"] = "#11" + if "g18" in planes: + scale["y"] = "#11" + scale["j"] = "#11" + if "g19" in planes: + scale["x"] = "#11" + scale["i"] = "#11" + # Add a scale + if "a" in coords: + gcode += "#12 = 1 (A axis scale)\n" + scale["a"] = "#12" + + # Add feed parametrization + for f in feeds: + gcode += "{} = {:f} (Feed definition)\n".format(feeds[f], f) + + # Parameterize Gcode + for s in self.gcode.split("\n"): + # feed replace : + r = re.search(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", s) + if r and len(r.group(3)) > 0: + s = re.sub(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", "F [{}]".format(feeds[float(r.group(2) + r.group(3))]), s) + # Coords XYZA replace + for c in "xyza": + r = re.search(r"(?i)((" + c + r")\s*(-?)\s*(\d*\.?\d*))", s) + if r and len(r.group(4)) > 0: + s = re.sub(r"(?i)(" + c + r")\s*((-?)\s*(\d*\.?\d*))", r"\1[\2*{}+{}]".format(scale[c], offset[c]), s) + + # Coords IJKR replace + for c in "ijkr": + r = re.search(r"(?i)((" + c + r")\s*(-?)\s*(\d*\.?\d*))", s) + if r and len(r.group(4)) > 0: + s = re.sub(r"(?i)(" + c + r")\s*((-?)\s*(\d*\.?\d*))", r"\1[\2*{}]".format(scale[c]), s) + + gcode += s + "\n" + + self.gcode = gcode + + def round_coordinates(self, parameters): + try: + round_ = int(parameters) + except: + self.error("Bad parameters for round. Round should be an integer! \n(Parameters: '{}')".format(parameters), "error") + gcode = "" + for s in self.gcode.split("\n"): + for a in "xyzijkaf": + r = re.search(r"(?i)(" + a + r")\s*(-?\s*(\d*\.?\d*))", s) + if r: + + if r.group(2) != "": + s = re.sub( + r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)", + (r"\1 %0." + str(round_) + "f" if round_ > 0 else r"\1 %d") % round(float(r.group(2)), round_), + s) + gcode += s + "\n" + self.gcode = gcode + + def scale(self, parameters): + parameters = parameters.split(",") + scale = [1., 1., 1., 1.] + try: + for i in range(len(parameters)): + if float(parameters[i]) == 0: + self.error("Bad parameters for scale. Scale should not be 0 at any axis! \n(Parameters: '{}')".format(parameters), "error") + scale[i] = float(parameters[i]) + except: + self.error("Bad parameters for scale.\n(Parameters: '{}')".format(parameters), "error") + self.transform([0, 0, 0, 0], scale) + + def move(self, parameters): + parameters = parameters.split(",") + move = [0., 0., 0., 0.] + try: + for i in range(len(parameters)): + move[i] = float(parameters[i]) + except: + self.error("Bad parameters for move.\n(Parameters: '{}')".format(parameters), "error") + self.transform(move, [1., 1., 1., 1.]) + + def flip_axis(self, parameters): + parameters = parameters.lower() + axis = {"x": 1., "y": 1., "z": 1., "a": 1.} + for p in parameters: + if p in [",", " ", " ", "\r", "'", '"']: + continue + if p not in ["x", "y", "z", "a"]: + self.error("Bad parameters for flip_axis. Parameter should be string consists of 'xyza' \n(Parameters: '{}')".format(parameters), "error") + axis[p] = -axis[p] + self.scale("{:f},{:f},{:f},{:f}".format(axis["x"], axis["y"], axis["z"], axis["a"])) + + +################################################################################ +# Polygon class +################################################################################ +class Polygon(object): + def __init__(self, polygon=None): + self.polygon = [] if polygon is None else polygon[:] + + def move(self, x, y): + for i in range(len(self.polygon)): + for j in range(len(self.polygon[i])): + self.polygon[i][j][0] += x + self.polygon[i][j][1] += y + + def bounds(self): + minx = 1e400 + miny = 1e400 + maxx = -1e400 + maxy = -1e400 + for poly in self.polygon: + for p in poly: + if minx > p[0]: + minx = p[0] + if miny > p[1]: + miny = p[1] + if maxx < p[0]: + maxx = p[0] + if maxy < p[1]: + maxy = p[1] + return minx * 1, miny * 1, maxx * 1, maxy * 1 + + def width(self): + b = self.bounds() + return b[2] - b[0] + + def rotate_(self, sin, cos): + self.polygon = [ + [ + [point[0] * cos - point[1] * sin, point[0] * sin + point[1] * cos] for point in subpoly + ] + for subpoly in self.polygon + ] + + def rotate(self, a): + cos = math.cos(a) + sin = math.sin(a) + self.rotate_(sin, cos) + + def drop_into_direction(self, direction, surface): + # Polygon is a list of simple polygons + # Surface is a polygon + line y = 0 + # Direction is [dx,dy] + if len(self.polygon) == 0 or len(self.polygon[0]) == 0: + return + if direction[0] ** 2 + direction[1] ** 2 < 1e-10: + return + direction = normalize(direction) + sin = direction[0] + cos = -direction[1] + self.rotate_(-sin, cos) + surface.rotate_(-sin, cos) + self.drop_down(surface, zerro_plane=False) + self.rotate_(sin, cos) + surface.rotate_(sin, cos) + + def centroid(self): + centroids = [] + sa = 0 + for poly in self.polygon: + cx = 0 + cy = 0 + a = 0 + for i in range(len(poly)): + [x1, y1] = poly[i - 1] + [x2, y2] = poly[i] + cx += (x1 + x2) * (x1 * y2 - x2 * y1) + cy += (y1 + y2) * (x1 * y2 - x2 * y1) + a += (x1 * y2 - x2 * y1) + a *= 3. + if abs(a) > 0: + cx /= a + cy /= a + sa += abs(a) + centroids += [[cx, cy, a]] + if sa == 0: + return [0., 0.] + cx = 0 + cy = 0 + for c in centroids: + cx += c[0] * c[2] + cy += c[1] * c[2] + cx /= sa + cy /= sa + return [cx, cy] + + def drop_down(self, surface, zerro_plane=True): + # Polygon is a list of simple polygons + # Surface is a polygon + line y = 0 + # Down means min y (0,-1) + if len(self.polygon) == 0 or len(self.polygon[0]) == 0: + return + # Get surface top point + top = surface.bounds()[3] + if zerro_plane: + top = max(0, top) + # Get polygon bottom point + bottom = self.bounds()[1] + self.move(0, top - bottom + 10) + # Now get shortest distance from surface to polygon in positive x=0 direction + # Such distance = min(distance(vertex, edge)...) where edge from surface and + # vertex from polygon and vice versa... + dist = 1e300 + for poly in surface.polygon: + for i in range(len(poly)): + for poly1 in self.polygon: + for i1 in range(len(poly1)): + st = poly[i - 1] + end = poly[i] + vertex = poly1[i1] + if st[0] <= vertex[0] <= end[0] or end[0] <= vertex[0] <= st[0]: + if st[0] == end[0]: + d = min(vertex[1] - st[1], vertex[1] - end[1]) + else: + d = vertex[1] - st[1] - (end[1] - st[1]) * (vertex[0] - st[0]) / (end[0] - st[0]) + if dist > d: + dist = d + # and vice versa just change the sign because vertex now under the edge + st = poly1[i1 - 1] + end = poly1[i1] + vertex = poly[i] + if st[0] <= vertex[0] <= end[0] or end[0] <= vertex[0] <= st[0]: + if st[0] == end[0]: + d = min(- vertex[1] + st[1], -vertex[1] + end[1]) + else: + d = - vertex[1] + st[1] + (end[1] - st[1]) * (vertex[0] - st[0]) / (end[0] - st[0]) + if dist > d: + dist = d + + if zerro_plane and dist > 10 + top: + dist = 10 + top + self.move(0, -dist) + + def draw(self, color="#075", width=.1, group=None): + csp = [csp_subpath_line_to([], poly + [poly[0]]) for poly in self.polygon] + draw_csp(csp, width=width, group=group) + + def add(self, add): + if type(add) == type([]): + self.polygon += add[:] + else: + self.polygon += add.polygon[:] + + def point_inside(self, p): + inside = False + for poly in self.polygon: + for i in range(len(poly)): + st = poly[i - 1] + end = poly[i] + if p == st or p == end: + return True # point is a vertex = point is on the edge + if st[0] > end[0]: + st, end = end, st # This will be needed to check that edge if open only at right end + c = (p[1] - st[1]) * (end[0] - st[0]) - (end[1] - st[1]) * (p[0] - st[0]) + if st[0] <= p[0] < end[0]: + if c < 0: + inside = not inside + elif c == 0: + return True # point is on the edge + elif st[0] == end[0] == p[0] and (st[1] <= p[1] <= end[1] or end[1] <= p[1] <= st[1]): # point is on the edge + return True + return inside + + def hull(self): + # Add vertices at all self intersection points. + hull = [] + for i1 in range(len(self.polygon)): + poly1 = self.polygon[i1] + poly_ = [] + for j1 in range(len(poly1)): + s = poly1[j1 - 1] + e = poly1[j1] + poly_ += [s] + + # Check self intersections + for j2 in range(j1 + 1, len(poly1)): + s1 = poly1[j2 - 1] + e1 = poly1[j2] + int_ = line_line_intersection_points(s, e, s1, e1) + for p in int_: + if point_to_point_d2(p, s) > 0.000001 and point_to_point_d2(p, e) > 0.000001: + poly_ += [p] + # Check self intersections with other polys + for i2 in range(len(self.polygon)): + if i1 == i2: + continue + poly2 = self.polygon[i2] + for j2 in range(len(poly2)): + s1 = poly2[j2 - 1] + e1 = poly2[j2] + int_ = line_line_intersection_points(s, e, s1, e1) + for p in int_: + if point_to_point_d2(p, s) > 0.000001 and point_to_point_d2(p, e) > 0.000001: + poly_ += [p] + hull += [poly_] + # Create the dictionary containing all edges in both directions + edges = {} + for poly in self.polygon: + for i in range(len(poly)): + s = tuple(poly[i - 1]) + e = tuple(poly[i]) + if point_to_point_d2(e, s) < 0.000001: + continue + break_s = False + break_e = False + for p in edges: + if point_to_point_d2(p, s) < 0.000001: + break_s = True + s = p + if point_to_point_d2(p, e) < 0.000001: + break_e = True + e = p + if break_s and break_e: + break + l = point_to_point_d(s, e) + if not break_s and not break_e: + edges[s] = [[s, e, l]] + edges[e] = [[e, s, l]] + else: + if e in edges: + for edge in edges[e]: + if point_to_point_d2(edge[1], s) < 0.000001: + break + if point_to_point_d2(edge[1], s) > 0.000001: + edges[e] += [[e, s, l]] + else: + edges[e] = [[e, s, l]] + if s in edges: + for edge in edges[s]: + if point_to_point_d2(edge[1], e) < 0.000001: + break + if point_to_point_d2(edge[1], e) > 0.000001: + edges[s] += [[s, e, l]] + else: + edges[s] = [[s, e, l]] + + def angle_quadrant(sin, cos): + # quadrants are (0,pi/2], (pi/2,pi], (pi,3*pi/2], (3*pi/2, 2*pi], i.e. 0 is in the 4-th quadrant + if sin > 0 and cos >= 0: + return 1 + if sin >= 0 and cos < 0: + return 2 + if sin < 0 and cos <= 0: + return 3 + if sin <= 0 and cos > 0: + return 4 + + def angle_is_less(sin, cos, sin1, cos1): + # 0 = 2*pi is the largest angle + if [sin1, cos1] == [0, 1]: + return True + if [sin, cos] == [0, 1]: + return False + if angle_quadrant(sin, cos) > angle_quadrant(sin1, cos1): + return False + if angle_quadrant(sin, cos) < angle_quadrant(sin1, cos1): + return True + if sin >= 0 and cos > 0: + return sin < sin1 + if sin > 0 and cos <= 0: + return sin > sin1 + if sin <= 0 and cos < 0: + return sin > sin1 + if sin < 0 and cos >= 0: + return sin < sin1 + + def get_closes_edge_by_angle(edges, last): + # Last edge is normalized vector of the last edge. + min_angle = [0, 1] + next = last + last_edge = [(last[0][0] - last[1][0]) / last[2], (last[0][1] - last[1][1]) / last[2]] + for p in edges: + + cur = [(p[1][0] - p[0][0]) / p[2], (p[1][1] - p[0][1]) / p[2]] + cos = dot(cur, last_edge) + sin = cross(cur, last_edge) + + if angle_is_less(sin, cos, min_angle[0], min_angle[1]): + min_angle = [sin, cos] + next = p + + return next + + # Join edges together into new polygon cutting the vertexes inside new polygon + self.polygon = [] + len_edges = sum([len(edges[p]) for p in edges]) + loops = 0 + + while len(edges) > 0: + poly = [] + if loops > len_edges: + raise ValueError("Hull error") + loops += 1 + # Find left most vertex. + start = (1e100, 1) + for edge in edges: + start = min(start, min(edges[edge])) + last = [(start[0][0] - 1, start[0][1]), start[0], 1] + first_run = True + loops1 = 0 + while last[1] != start[0] or first_run: + first_run = False + if loops1 > len_edges: + raise ValueError("Hull error") + loops1 += 1 + next = get_closes_edge_by_angle(edges[last[1]], last) + + last = next + poly += [list(last[0])] + self.polygon += [poly] + # Remove all edges that are intersects new poly (any vertex inside new poly) + poly_ = Polygon([poly]) + for p in edges.keys()[:]: + if poly_.point_inside(list(p)): + del edges[p] + self.draw(color="Green", width=1) + + +################################################################################ +# +# Gcodetools class +# +################################################################################ + +class Gcodetools(inkex.EffectExtension): + multi_inx = True # XXX Remove this after refactoring + + def export_gcode(self, gcode, no_headers=False): + if self.options.postprocessor != "" or self.options.postprocessor_custom != "": + postprocessor = Postprocessor(self.error) + postprocessor.gcode = gcode + if self.options.postprocessor != "": + postprocessor.process(self.options.postprocessor) + if self.options.postprocessor_custom != "": + postprocessor.process(self.options.postprocessor_custom) + + if not no_headers: + postprocessor.gcode = self.header + postprocessor.gcode + self.footer + + with open(os.path.join(self.options.directory, self.options.file), "w") as f: + f.write(postprocessor.gcode) + + ################################################################################ + # In/out paths: + # TODO move it to the bottom + ################################################################################ + def tab_plasma_prepare_path(self): + self.get_info_plus() + + def add_arc(sp1, sp2, end=False, l=10., r=10.): + if not end: + n = csp_normalized_normal(sp1, sp2, 0.) + return csp_reverse([arc_from_s_r_n_l(sp1[1], r, n, -l)])[0] + else: + n = csp_normalized_normal(sp1, sp2, 1.) + return arc_from_s_r_n_l(sp2[1], r, n, l) + + def add_normal(sp1, sp2, end=False, l=10., r=10.): + # r is needed only for be compatible with add_arc + if not end: + n = csp_normalized_normal(sp1, sp2, 0.) + p = [n[0] * l + sp1[1][0], n[1] * l + sp1[1][1]] + return csp_subpath_line_to([], [p, sp1[1]]) + else: + n = csp_normalized_normal(sp1, sp2, 1.) + p = [n[0] * l + sp2[1][0], n[1] * l + sp2[1][1]] + return csp_subpath_line_to([], [sp2[1], p]) + + def add_tangent(sp1, sp2, end=False, l=10., r=10.): + # r is needed only for be compatible with add_arc + if not end: + n = csp_normalized_slope(sp1, sp2, 0.) + p = [-n[0] * l + sp1[1][0], -n[1] * l + sp1[1][1]] + return csp_subpath_line_to([], [p, sp1[1]]) + else: + n = csp_normalized_slope(sp1, sp2, 1.) + p = [n[0] * l + sp2[1][0], n[1] * l + sp2[1][1]] + return csp_subpath_line_to([], [sp2[1], p]) + + if not self.options.in_out_path and not self.options.plasma_prepare_corners and self.options.in_out_path_do_not_add_reference_point: + self.error("Warning! Extension is not said to do anything! Enable one of Create in-out paths or Prepare corners checkboxes or disable Do not add in-out reference point!") + return + + # Add in-out-reference point if there is no one yet. + if ((len(self.in_out_reference_points) == 0 and self.options.in_out_path + or not self.options.in_out_path and not self.options.plasma_prepare_corners) + and not self.options.in_out_path_do_not_add_reference_point): + self.options.orientation_points_count = "in-out reference point" + #self.orientation() + + if self.options.in_out_path or self.options.plasma_prepare_corners: + self.set_markers() + add_func = {"Round": add_arc, "Perpendicular": add_normal, "Tangent": add_tangent}[self.options.in_out_path_type] + if self.options.in_out_path_type == "Round" and self.options.in_out_path_len > self.options.in_out_path_radius * 3 / 2 * math.pi: + self.error("In-out len is to big for in-out radius will cropp it to be r*3/2*pi!") + + if self.selected_paths == {} and self.options.auto_select_paths: + self.selected_paths = self.paths + self.error("No paths are selected! Trying to work on all available paths.") + + if self.selected_paths == {}: + self.error("Nothing is selected. Please select something.") + a = self.options.plasma_prepare_corners_tolerance + corner_tolerance = cross([1., 0.], [math.cos(a), math.sin(a)]) + + for layer in self.layers: + if layer in self.selected_paths: + max_dist = self.transform_scalar(self.options.in_out_path_point_max_dist, layer, reverse=True) + l = self.transform_scalar(self.options.in_out_path_len, layer, reverse=True) + plasma_l = self.transform_scalar(self.options.plasma_prepare_corners_distance, layer, reverse=True) + r = self.transform_scalar(self.options.in_out_path_radius, layer, reverse=True) + l = min(l, r * 3 / 2 * math.pi) + + for path in self.selected_paths[layer]: + csp = self.apply_transforms(path, path.path.to_superpath()) + csp = csp_remove_zero_segments(csp) + res = [] + + for subpath in csp: + # Find closes point to in-out reference point + # If subpath is open skip this step + if self.options.in_out_path: + # split and reverse path for further add in-out points + if point_to_point_d2(subpath[0][1], subpath[-1][1]) < 1.e-10: + d = [1e100, 1, 1, 1.] + for p in self.in_out_reference_points: + d1 = csp_to_point_distance([subpath], p, dist_bounds=[0, max_dist]) + if d1[0] < d[0]: + d = d1[:] + p_ = p + if d[0] < max_dist ** 2: + # Lets find is there any angles near this point to put in-out path in + # the angle if it's possible + # remove last node to make iterations easier + subpath[0][0] = subpath[-1][0] + del subpath[-1] + max_cross = [-1e100, None] + for j in range(len(subpath)): + sp1 = subpath[j - 2] + sp2 = subpath[j - 1] + sp3 = subpath[j] + if point_to_point_d2(sp2[1], p_) < max_dist ** 2: + s1 = csp_normalized_slope(sp1, sp2, 1.) + s2 = csp_normalized_slope(sp2, sp3, 0.) + max_cross = max(max_cross, [cross(s1, s2), j - 1]) + # return back last point + subpath.append(subpath[0]) + if max_cross[1] is not None and max_cross[0] > corner_tolerance: + # there's an angle near the point + j = max_cross[1] + if j < 0: + j -= 1 + if j != 0: + subpath = csp_concat_subpaths(subpath[j:], subpath[:j + 1]) + else: + # have to cut path's segment + d, i, j, t = d + sp1, sp2, sp3 = csp_split(subpath[j - 1], subpath[j], t) + subpath = csp_concat_subpaths([sp2, sp3], subpath[j:], subpath[:j], [sp1, sp2]) + + if self.options.plasma_prepare_corners: + # prepare corners + # find corners and add some nodes + # corner at path's start/end is ignored + res_ = [subpath[0]] + for sp2, sp3 in zip(subpath[1:], subpath[2:]): + sp1 = res_[-1] + s1 = csp_normalized_slope(sp1, sp2, 1.) + s2 = csp_normalized_slope(sp2, sp3, 0.) + if cross(s1, s2) > corner_tolerance: + # got a corner to process + S1 = P(s1) + S2 = P(s2) + N = (S1 - S2).unit() * plasma_l + SP2 = P(sp2[1]) + P1 = (SP2 + N) + res_ += [ + [sp2[0], sp2[1], (SP2 + S1 * plasma_l).to_list()], + [(P1 - N.ccw() / 2).to_list(), P1.to_list(), (P1 + N.ccw() / 2).to_list()], + [(SP2 - S2 * plasma_l).to_list(), sp2[1], sp2[2]] + ] + else: + res_ += [sp2] + res_ += [sp3] + subpath = res_ + if self.options.in_out_path: + # finally add let's add in-out paths... + subpath = csp_concat_subpaths( + add_func(subpath[0], subpath[1], False, l, r), + subpath, + add_func(subpath[-2], subpath[-1], True, l, r) + ) + + res += [subpath] + + if self.options.in_out_path_replace_original_path: + path.path = CubicSuperPath(self.apply_transforms(path, res, True)) + else: + draw_csp(res, width=1, style=MARKER_STYLE["in_out_path_style"]) + + def add_arguments(self, pars): + add_argument = pars.add_argument + add_argument("-d", "--directory", default="/home/", help="Directory for gcode file") + add_argument("-f", "--filename", dest="file", default="-1.0", help="File name") + add_argument("--add-numeric-suffix-to-filename", type=inkex.Boolean, default=True, help="Add numeric suffix to filename") + add_argument("--Zscale", type=float, default="1.0", help="Scale factor Z") + add_argument("--Zoffset", type=float, default="0.0", help="Offset along Z") + add_argument("-s", "--Zsafe", type=float, default="0.5", help="Z above all obstacles") + add_argument("-z", "--Zsurface", type=float, default="0.0", help="Z of the surface") + add_argument("-c", "--Zdepth", type=float, default="-0.125", help="Z depth of cut") + add_argument("--Zstep", type=float, default="-0.125", help="Z step of cutting") + add_argument("-p", "--feed", type=float, default="4.0", help="Feed rate in unit/min") + + add_argument("--biarc-tolerance", type=float, default="1", help="Tolerance used when calculating biarc interpolation.") + add_argument("--biarc-max-split-depth", type=int, default="4", help="Defines maximum depth of splitting while approximating using biarcs.") + add_argument("--path-to-gcode-order", default="path by path", help="Defines cutting order path by path or layer by layer.") + add_argument("--path-to-gcode-depth-function", default="zd", help="Path to gcode depth function.") + add_argument("--path-to-gcode-sort-paths", type=inkex.Boolean, default=True, help="Sort paths to reduce rapid distance.") + add_argument("--comment-gcode", default="", help="Comment Gcode") + add_argument("--comment-gcode-from-properties", type=inkex.Boolean, default=False, help="Get additional comments from Object Properties") + + add_argument("--tool-diameter", type=float, default="3", help="Tool diameter used for area cutting") + add_argument("--max-area-curves", type=int, default="100", help="Maximum area curves for each area") + add_argument("--area-inkscape-radius", type=float, default="0", help="Area curves overlapping (depends on tool diameter [0, 0.9])") + add_argument("--area-tool-overlap", type=float, default="-10", help="Radius for preparing curves using inkscape") + add_argument("--unit", default="G21 (All units in mm)", help="Units") + add_argument("--active-tab", type=self.arg_method('tab'), default=self.tab_help, help="Defines which tab is active") + + add_argument("--area-fill-angle", type=float, default="0", help="Fill area with lines heading this angle") + add_argument("--area-fill-shift", type=float, default="0", help="Shift the lines by tool d * shift") + add_argument("--area-fill-method", default="zig-zag", help="Filling method either zig-zag or spiral") + + add_argument("--area-find-artefacts-diameter", type=float, default="1", help="Artefacts seeking radius") + add_argument("--area-find-artefacts-action", default="mark with an arrow", help="Artefacts action type") + + add_argument("--auto_select_paths", type=inkex.Boolean, default=True, help="Select all paths if nothing is selected.") + + add_argument("--loft-distances", default="10", help="Distances between paths.") + add_argument("--loft-direction", default="crosswise", help="Direction of loft's interpolation.") + add_argument("--loft-interpolation-degree", type=float, default="2", help="Which interpolation use to loft the paths smooth interpolation or staright.") + + add_argument("--min-arc-radius", type=float, default=".1", help="All arc having radius less than minimum will be considered as straight line") + + add_argument("--engraving-sharp-angle-tollerance", type=float, default="150", help="All angles thar are less than engraving-sharp-angle-tollerance will be thought sharp") + add_argument("--engraving-max-dist", type=float, default="10", help="Distance from original path where engraving is not needed (usually it's cutting tool diameter)") + add_argument("--engraving-newton-iterations", type=int, default="4", help="Number of sample points used to calculate distance") + add_argument("--engraving-draw-calculation-paths", type=inkex.Boolean, default=False, help="Draw additional graphics to debug engraving path") + add_argument("--engraving-cutter-shape-function", default="w", help="Cutter shape function z(w). Ex. cone: w. ") + + add_argument("--lathe-width", type=float, default=10., help="Lathe width") + add_argument("--lathe-fine-cut-width", type=float, default=1., help="Fine cut width") + add_argument("--lathe-fine-cut-count", type=int, default=1., help="Fine cut count") + add_argument("--lathe-create-fine-cut-using", default="Move path", help="Create fine cut using") + add_argument("--lathe-x-axis-remap", default="X", help="Lathe X axis remap") + add_argument("--lathe-z-axis-remap", default="Z", help="Lathe Z axis remap") + + add_argument("--lathe-rectangular-cutter-width", type=float, default="4", help="Rectangular cutter width") + + add_argument("--create-log", type=inkex.Boolean, dest="log_create_log", default=False, help="Create log files") + add_argument("--log-filename", default='', help="Create log files") + + add_argument("--orientation-points-count", default="2", help="Orientation points count") + add_argument("--tools-library-type", default='cylinder cutter', help="Create tools definition") + + add_argument("--dxfpoints-action", default='replace', help="dxfpoint sign toggle") + + add_argument("--help-language", default='http://www.cnc-club.ru/forum/viewtopic.php?f=33&t=35', help="Open help page in webbrowser.") + + add_argument("--offset-radius", type=float, default=10., help="Offset radius") + add_argument("--offset-step", type=float, default=10., help="Offset step") + add_argument("--offset-draw-clippend-path", type=inkex.Boolean, default=False, help="Draw clipped path") + add_argument("--offset-just-get-distance", type=inkex.Boolean, default=False, help="Don't do offset just get distance") + + add_argument("--postprocessor", default='', help="Postprocessor command.") + add_argument("--postprocessor-custom", default='', help="Postprocessor custom command.") + + add_argument("--graffiti-max-seg-length", type=float, default=1., help="Graffiti maximum segment length.") + add_argument("--graffiti-min-radius", type=float, default=10., help="Graffiti minimal connector's radius.") + add_argument("--graffiti-start-pos", default="(0;0)", help="Graffiti Start position (x;y).") + add_argument("--graffiti-create-linearization-preview", type=inkex.Boolean, default=True, help="Graffiti create linearization preview.") + add_argument("--graffiti-create-preview", type=inkex.Boolean, default=True, help="Graffiti create preview.") + add_argument("--graffiti-preview-size", type=int, default=800, help="Graffiti preview's size.") + add_argument("--graffiti-preview-emmit", type=int, default=800, help="Preview's paint emmit (pts/s).") + + add_argument("--in-out-path", type=inkex.Boolean, default=True, help="Create in-out paths") + add_argument("--in-out-path-do-not-add-reference-point", type=inkex.Boolean, default=False, help="Just add reference in-out point") + add_argument("--in-out-path-point-max-dist", type=float, default=10., help="In-out path max distance to reference point") + add_argument("--in-out-path-type", default="Round", help="In-out path type") + add_argument("--in-out-path-len", type=float, default=10., help="In-out path length") + add_argument("--in-out-path-replace-original-path", type=inkex.Boolean, default=False, help="Replace original path") + add_argument("--in-out-path-radius", type=float, default=10., help="In-out path radius for round path") + + add_argument("--plasma-prepare-corners", type=inkex.Boolean, default=True, help="Prepare corners") + add_argument("--plasma-prepare-corners-distance", type=float, default=10., help="Stepout distance for corners") + add_argument("--plasma-prepare-corners-tolerance", type=float, default=10., help="Maximum angle for corner (0-180 deg)") + + def __init__(self): + super(Gcodetools, self).__init__() + self.default_tool = { + "name": "Default tool", + "id": "default tool", + "diameter": 10., + "shape": "10", + "penetration angle": 90., + "penetration feed": 100., + "depth step": 1., + "feed": 400., + "in trajectotry": "", + "out trajectotry": "", + "gcode before path": "", + "gcode after path": "", + "sog": "", + "spinlde rpm": "", + "CW or CCW": "", + "tool change gcode": " ", + "4th axis meaning": " ", + "4th axis scale": 1., + "4th axis offset": 0., + "passing feed": "800", + "fine feed": "800", + } + self.tools_field_order = [ + 'name', + 'id', + 'diameter', + 'feed', + 'shape', + 'penetration angle', + 'penetration feed', + "passing feed", + 'depth step', + "in trajectotry", + "out trajectotry", + "gcode before path", + "gcode after path", + "sog", + "spinlde rpm", + "CW or CCW", + "tool change gcode", + ] + + def parse_curve(self, p, layer, w=None, f=None): + c = [] + if len(p) == 0: + return [] + p = self.transform_csp(p, layer) + + # Sort to reduce Rapid distance + k = list(range(1, len(p))) + keys = [0] + while len(k) > 0: + end = p[keys[-1]][-1][1] + dist = None + for i in range(len(k)): + start = p[k[i]][0][1] + dist = max((-((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2), i), dist) + keys += [k[dist[1]]] + del k[dist[1]] + for k in keys: + subpath = p[k] + c += [[[subpath[0][1][0], subpath[0][1][1]], 'move', 0, 0]] + for i in range(1, len(subpath)): + sp1 = [[subpath[i - 1][j][0], subpath[i - 1][j][1]] for j in range(3)] + sp2 = [[subpath[i][j][0], subpath[i][j][1]] for j in range(3)] + c += biarc(sp1, sp2, 0, 0) if w is None else biarc(sp1, sp2, -f(w[k][i - 1]), -f(w[k][i])) + c += [[[subpath[-1][1][0], subpath[-1][1][1]], 'end', 0, 0]] + return c + + ################################################################################ + # Draw csp + ################################################################################ + + def draw_csp(self, csp, layer=None, group=None, fill='none', stroke='#178ade', width=0.354, style=None): + if layer is not None: + csp = self.transform_csp(csp, layer, reverse=True) + if group is None and layer is None: + group = self.document.getroot() + elif group is None and layer is not None: + group = layer + csp = self.apply_transforms(group, csp, reverse=True) + if style is not None: + return draw_csp(csp, group=group, style=style) + else: + return draw_csp(csp, group=group, fill=fill, stroke=stroke, width=width) + + def draw_curve(self, curve, layer, group=None, style=MARKER_STYLE["biarc_style"]): + self.set_markers() + + for i in [0, 1]: + sid = 'biarc{}_r'.format(i) + style[sid] = style['biarc{}'.format(i)].copy() + style[sid]["marker-start"] = "url(#DrawCurveMarker_r)" + del style[sid]["marker-end"] + + if group is None: + group = self.layers[min(1, len(self.layers) - 1)].add(Group(gcodetools="Preview group")) + if not hasattr(self, "preview_groups"): + self.preview_groups = {layer: group} + elif layer not in self.preview_groups: + self.preview_groups[layer] = group + group = self.preview_groups[layer] + + s = '' + arcn = 0 + + transform = self.get_transforms(group) + if transform: + transform = self.reverse_transform(transform) + transform = str(Transform(transform)) + + a = [0., 0.] + b = [1., 0.] + c = [0., 1.] + k = (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]) + a = self.transform(a, layer, True) + b = self.transform(b, layer, True) + c = self.transform(c, layer, True) + if ((b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])) * k > 0: + reverse_angle = 1 + else: + reverse_angle = -1 + for sk in curve: + si = sk[:] + si[0] = self.transform(si[0], layer, True) + si[2] = self.transform(si[2], layer, True) if type(si[2]) == type([]) and len(si[2]) == 2 else si[2] + + if s != '': + if s[1] == 'line': + elem = group.add(PathElement(gcodetools="Preview")) + elem.transform = transform + elem.style = style['line'] + elem.path = 'M {},{} L {},{}'.format(s[0][0], s[0][1], si[0][0], si[0][1]) + elif s[1] == 'arc': + arcn += 1 + sp = s[0] + c = s[2] + s[3] = s[3] * reverse_angle + + a = ((P(si[0]) - P(c)).angle() - (P(s[0]) - P(c)).angle()) % TAU # s[3] + if s[3] * a < 0: + if a > 0: + a = a - TAU + else: + a = TAU + a + r = math.sqrt((sp[0] - c[0]) ** 2 + (sp[1] - c[1]) ** 2) + a_st = (math.atan2(sp[0] - c[0], - (sp[1] - c[1])) - math.pi / 2) % (math.pi * 2) + if a > 0: + a_end = a_st + a + st = style['biarc{}'.format(arcn % 2)] + else: + a_end = a_st * 1 + a_st = a_st + a + st = style['biarc{}_r'.format(arcn % 2)] + + elem = group.add(PathElement.arc(c, r, start=a_st, end=a_end, + open=True, gcodetools="Preview")) + elem.transform = transform + elem.style = st + + s = si + + def check_dir(self): + print_("Checking directory: '{}'".format(self.options.directory)) + if os.path.isdir(self.options.directory): + if os.path.isfile(os.path.join(self.options.directory, 'header')): + with open(os.path.join(self.options.directory, 'header')) as f: + self.header = f.read() + else: + self.header = defaults['header'] + if os.path.isfile(os.path.join(self.options.directory, 'footer')): + with open(os.path.join(self.options.directory, 'footer')) as f: + self.footer = f.read() + else: + self.footer = defaults['footer'] + self.header += self.options.unit + "\n" + else: + self.error("Directory does not exist! Please specify existing directory at Preferences tab!", "error") + return False + + if self.options.add_numeric_suffix_to_filename: + dir_list = os.listdir(self.options.directory) + if "." in self.options.file: + r = re.match(r"^(.*)(\..*)$", self.options.file) + ext = r.group(2) + name = r.group(1) + else: + ext = "" + name = self.options.file + max_n = 0 + for s in dir_list: + r = re.match(r"^{}_0*(\d+){}$".format(re.escape(name), re.escape(ext)), s) + if r: + max_n = max(max_n, int(r.group(1))) + filename = name + "_" + ("0" * (4 - len(str(max_n + 1))) + str(max_n + 1)) + ext + self.options.file = filename + + try: + with open(os.path.join(self.options.directory, self.options.file), "w") as f: + pass + except: + self.error("Can not write to specified file!\n{}".format(os.path.join(self.options.directory, self.options.file)), "error") + return False + return True + + ################################################################################ + # + # Generate Gcode + # Generates Gcode on given curve. + # + # Curve definition [start point, type = {'arc','line','move','end'}, arc center, arc angle, end point, [zstart, zend]] + # + ################################################################################ + def generate_gcode(self, curve, layer, depth): + Zauto_scale = self.Zauto_scale[layer] + tool = self.tools[layer][0] + g = "" + + def c(c): + c = [c[i] if i < len(c) else None for i in range(6)] + if c[5] == 0: + c[5] = None + s = [" X", " Y", " Z", " I", " J", " K"] + s1 = ["", "", "", "", "", ""] + m = [1, 1, self.options.Zscale * Zauto_scale, 1, 1, self.options.Zscale * Zauto_scale] + a = [0, 0, self.options.Zoffset, 0, 0, 0] + r = '' + for i in range(6): + if c[i] is not None: + r += s[i] + ("{:f}".format(c[i] * m[i] + a[i])) + s1[i] + return r + + def calculate_angle(a, current_a): + return min( + [abs(a - current_a % TAU + TAU), a + current_a - current_a % TAU + TAU], + [abs(a - current_a % TAU - TAU), a + current_a - current_a % TAU - TAU], + [abs(a - current_a % TAU), a + current_a - current_a % TAU])[1] + + if len(curve) == 0: + return "" + + try: + self.last_used_tool is None + except: + self.last_used_tool = None + print_("working on curve") + print_(curve) + + if tool != self.last_used_tool: + g += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", tool["name"]))) + tool["tool change gcode"] + "\n" + + lg = 'G00' + zs = self.options.Zsafe + f = " F{:f}".format(tool['feed']) + current_a = 0 + go_to_safe_distance = "G00" + c([None, None, zs]) + "\n" + penetration_feed = " F{}".format(tool['penetration feed']) + for i in range(1, len(curve)): + # Creating Gcode for curve between s=curve[i-1] and si=curve[i] start at s[0] end at s[4]=si[0] + s = curve[i - 1] + si = curve[i] + feed = f if lg not in ['G01', 'G02', 'G03'] else '' + if s[1] == 'move': + g += go_to_safe_distance + "G00" + c(si[0]) + "\n" + tool['gcode before path'] + "\n" + lg = 'G00' + elif s[1] == 'end': + g += go_to_safe_distance + tool['gcode after path'] + "\n" + lg = 'G00' + elif s[1] == 'line': + if tool['4th axis meaning'] == "tangent knife": + a = atan2(si[0][0] - s[0][0], si[0][1] - s[0][1]) + a = calculate_angle(a, current_a) + g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset']) + current_a = a + if lg == "G00": + g += "G01" + c([None, None, s[5][0] + depth]) + penetration_feed + "(Penetrate)\n" + g += "G01" + c(si[0] + [s[5][1] + depth]) + feed + "\n" + lg = 'G01' + elif s[1] == 'arc': + r = [(s[2][0] - s[0][0]), (s[2][1] - s[0][1])] + if tool['4th axis meaning'] == "tangent knife": + if s[3] < 0: # CW + a1 = atan2(s[2][1] - s[0][1], -s[2][0] + s[0][0]) + math.pi + else: # CCW + a1 = atan2(-s[2][1] + s[0][1], s[2][0] - s[0][0]) + math.pi + a = calculate_angle(a1, current_a) + g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset']) + current_a = a + axis4 = " A{}".format((current_a + s[3]) * tool['4th axis scale'] + tool['4th axis offset']) + current_a = current_a + s[3] + else: + axis4 = "" + if lg == "G00": + g += "G01" + c([None, None, s[5][0] + depth]) + penetration_feed + "(Penetrate)\n" + if (r[0] ** 2 + r[1] ** 2) > self.options.min_arc_radius ** 2: + r1 = (P(s[0]) - P(s[2])) + r2 = (P(si[0]) - P(s[2])) + if abs(r1.mag() - r2.mag()) < 0.001: + g += ("G02" if s[3] < 0 else "G03") + c(si[0] + [s[5][1] + depth, (s[2][0] - s[0][0]), (s[2][1] - s[0][1])]) + feed + axis4 + "\n" + else: + r = (r1.mag() + r2.mag()) / 2 + g += ("G02" if s[3] < 0 else "G03") + c(si[0] + [s[5][1] + depth]) + " R{:f}".format(r) + feed + axis4 + "\n" + lg = 'G02' + else: + if tool['4th axis meaning'] == "tangent knife": + a = atan2(si[0][0] - s[0][0], si[0][1] - s[0][1]) + math.pi + a = calculate_angle(a, current_a) + g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset']) + current_a = a + g += "G01" + c(si[0] + [s[5][1] + depth]) + feed + "\n" + lg = 'G01' + if si[1] == 'end': + g += go_to_safe_distance + tool['gcode after path'] + "\n" + return g + + def get_transforms(self, g): + root = self.document.getroot() + trans = [] + while g != root: + if 'transform' in g.keys(): + t = g.get('transform') + t = Transform(t).matrix + trans = (Transform(t) * Transform(trans)).matrix if trans != [] else t + + print_(trans) + g = g.getparent() + return trans + + def reverse_transform(self, transform): + trans = numpy.array(transform + ([0, 0, 1],)) + if numpy.linalg.det(trans) != 0: + trans = numpy.linalg.inv(trans).tolist()[:2] + return trans + else: + return transform + + def apply_transforms(self, g, csp, reverse=False): + trans = self.get_transforms(g) + if trans: + if not reverse: + # TODO: This was applyTransformToPath but was deprecated. Candidate for refactoring. + for comp in csp: + for ctl in comp: + for pt in ctl: + pt[0], pt[1] = Transform(trans).apply_to_point(pt) + + else: + # TODO: This was applyTransformToPath but was deprecated. Candidate for refactoring. + for comp in csp: + for ctl in comp: + for pt in ctl: + pt[0], pt[1] = Transform(self.reverse_transform(trans)).apply_to_point(pt) + return csp + + def transform_scalar(self, x, layer, reverse=False): + return self.transform([x, 0], layer, reverse)[0] - self.transform([0, 0], layer, reverse)[0] + + def transform(self, source_point, layer, reverse=False): + if layer not in self.transform_matrix: + for i in range(self.layers.index(layer), -1, -1): + if self.layers[i] in self.orientation_points: + break + if self.layers[i] not in self.orientation_points: + self.error(f"Orientation points for '{layer.label}' layer have not been found! Please add orientation points using Orientation tab!", "error") + elif self.layers[i] in self.transform_matrix: + self.transform_matrix[layer] = self.transform_matrix[self.layers[i]] + self.Zcoordinates[layer] = self.Zcoordinates[self.layers[i]] + else: + orientation_layer = self.layers[i] + if len(self.orientation_points[orientation_layer]) > 1: + self.error(f"There are more than one orientation point groups in '{orientation_layer.label}' layer") + points = self.orientation_points[orientation_layer][0] + if len(points) == 2: + points += [[[(points[1][0][1] - points[0][0][1]) + points[0][0][0], -(points[1][0][0] - points[0][0][0]) + points[0][0][1]], [-(points[1][1][1] - points[0][1][1]) + points[0][1][0], points[1][1][0] - points[0][1][0] + points[0][1][1]]]] + if len(points) == 3: + print_("Layer '{orientation_layer.label}' Orientation points: ") + for point in points: + print_(point) + # Zcoordinates definition taken from Orientatnion point 1 and 2 + self.Zcoordinates[layer] = [max(points[0][1][2], points[1][1][2]), min(points[0][1][2], points[1][1][2])] + matrix = numpy.array([ + [points[0][0][0], points[0][0][1], 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, points[0][0][0], points[0][0][1], 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, points[0][0][0], points[0][0][1], 1], + [points[1][0][0], points[1][0][1], 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, points[1][0][0], points[1][0][1], 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, points[1][0][0], points[1][0][1], 1], + [points[2][0][0], points[2][0][1], 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, points[2][0][0], points[2][0][1], 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, points[2][0][0], points[2][0][1], 1] + ]) + + if numpy.linalg.det(matrix) != 0: + m = numpy.linalg.solve(matrix, + numpy.array( + [[points[0][1][0]], [points[0][1][1]], [1], [points[1][1][0]], [points[1][1][1]], [1], [points[2][1][0]], [points[2][1][1]], [1]] + ) + ).tolist() + self.transform_matrix[layer] = [[m[j * 3 + i][0] for i in range(3)] for j in range(3)] + + else: + self.error("Orientation points are wrong! (if there are two orientation points they should not be the same. If there are three orientation points they should not be in a straight line.)", "error") + else: + self.error("Orientation points are wrong! (if there are two orientation points they should not be the same. If there are three orientation points they should not be in a straight line.)", "error") + + self.transform_matrix_reverse[layer] = numpy.linalg.inv(self.transform_matrix[layer]).tolist() + print_(f"\n Layer '{layer.label}' transformation matrixes:") + print_(self.transform_matrix) + print_(self.transform_matrix_reverse) + + # Zautoscale is obsolete + self.Zauto_scale[layer] = 1 + print_("Z automatic scale = {} (computed according orientation points)".format(self.Zauto_scale[layer])) + + x = source_point[0] + y = source_point[1] + if not reverse: + t = self.transform_matrix[layer] + else: + t = self.transform_matrix_reverse[layer] + return [t[0][0] * x + t[0][1] * y + t[0][2], t[1][0] * x + t[1][1] * y + t[1][2]] + + def transform_csp(self, csp_, layer, reverse=False): + csp = [[[csp_[i][j][0][:], csp_[i][j][1][:], csp_[i][j][2][:]] for j in range(len(csp_[i]))] for i in range(len(csp_))] + for i in xrange(len(csp)): + for j in xrange(len(csp[i])): + for k in xrange(len(csp[i][j])): + csp[i][j][k] = self.transform(csp[i][j][k], layer, reverse) + return csp + + def error(self, s, msg_type="warning"): + """ + Errors handling function + warnings are printed into log file and warning message is displayed but + extension continues working, + errors causes log and execution is halted + """ + if msg_type == "warning": + print_(s) + inkex.errormsg(s + "\n") + + elif msg_type == "error": + print_(s) + raise inkex.AbortExtension(s) + + else: + print_("Unknown message type: {}".format(msg_type)) + print_(s) + raise inkex.AbortExtension(s) + + ################################################################################ + # Set markers + ################################################################################ + def set_markers(self): + """Make sure all markers are available""" + def ensure_marker(elem_id, x=-4, polA='', polB='-', fill='#000044'): + if self.svg.getElementById(elem_id) is None: + marker = self.svg.defs.add(Marker( + id=elem_id, orient="auto", refX=str(x), refY="-1.687441", + style="overflow:visible")) + path = marker.add(PathElement( + d="m {0}4.588864,-1.687441 0.0,0.0 L {0}9.177728,0.0 "\ + "c {1}0.73311,-0.996261 {1}0.728882,-2.359329 0.0,-3.374882"\ + .format(polA, polB))) + path.style = "fill:{};fill-rule:evenodd;stroke:none;".format(fill) + + ensure_marker("CheckToolsAndOPMarker") + ensure_marker("DrawCurveMarker") + ensure_marker("DrawCurveMarker_r", x=4, polA='-', polB='') + ensure_marker("InOutPathMarker", fill='#0072a7') + + def get_info(self): + """Get Gcodetools info from the svg""" + self.selected_paths = {} + self.paths = {} + self.tools = {} + self.orientation_points = {} + self.graffiti_reference_points = {} + self.layers = [self.document.getroot()] + self.Zcoordinates = {} + self.transform_matrix = {} + self.transform_matrix_reverse = {} + self.Zauto_scale = {} + self.in_out_reference_points = [] + self.my3Dlayer = None + + def recursive_search(g, layer, selected=False): + items = g.getchildren() + items.reverse() + for i in items: + if selected: + self.svg.selected[i.get("id")] = i + if isinstance(i, Layer): + if i.label == '3D': + self.my3Dlayer = i + else: + self.layers += [i] + recursive_search(i, i) + + elif i.get('gcodetools') == "Gcodetools orientation group": + points = self.get_orientation_points(i) + if points is not None: + self.orientation_points[layer] = self.orientation_points[layer] + [points[:]] if layer in self.orientation_points else [points[:]] + print_(f"Found orientation points in '{layer.label}' layer: {points}") + else: + self.error(f"Warning! Found bad orientation points in '{layer.label}' layer. Resulting Gcode could be corrupt!") + + # Need to recognise old files ver 1.6.04 and earlier + elif i.get("gcodetools") == "Gcodetools tool definition" or i.get("gcodetools") == "Gcodetools tool definition": + tool = self.get_tool(i) + self.tools[layer] = self.tools[layer] + [tool.copy()] if layer in self.tools else [tool.copy()] + print_(f"Found tool in '{layer.label}' layer: {tool}") + + elif i.get("gcodetools") == "Gcodetools graffiti reference point": + point = self.get_graffiti_reference_points(i) + if point: + self.graffiti_reference_points[layer] = self.graffiti_reference_points[layer] + [point[:]] if layer in self.graffiti_reference_points else [point] + else: + self.error(f"Warning! Found bad graffiti reference point in '{layer.label}' layer. Resulting Gcode could be corrupt!") + + elif isinstance(i, inkex.PathElement): + if "gcodetools" not in i.keys(): + self.paths[layer] = self.paths[layer] + [i] if layer in self.paths else [i] + if i.get("id") in self.svg.selected.ids: + self.selected_paths[layer] = self.selected_paths[layer] + [i] if layer in self.selected_paths else [i] + + elif i.get("gcodetools") == "In-out reference point group": + items_ = i.getchildren() + items_.reverse() + for j in items_: + if j.get("gcodetools") == "In-out reference point": + self.in_out_reference_points.append(self.apply_transforms(j, j.path.to_superpath())[0][0][1]) + + elif isinstance(i, inkex.Group): + recursive_search(i, layer, (i.get("id") in self.svg.selected)) + + elif i.get("id") in self.svg.selected: + # xgettext:no-pango-format + self.error("This extension works with Paths and Dynamic Offsets and groups of them only! " + "All other objects will be ignored!\n" + "Solution 1: press Path->Object to path or Shift+Ctrl+C.\n" + "Solution 2: Path->Dynamic offset or Ctrl+J.\n" + "Solution 3: export all contours to PostScript level 2 (File->Save As->.ps) and File->Import this file.") + + recursive_search(self.document.getroot(), self.document.getroot()) + + if len(self.layers) == 1: + self.error("Document has no layers! Add at least one layer using layers panel (Ctrl+Shift+L)", "error") + root = self.document.getroot() + + if root in self.selected_paths or root in self.paths: + self.error("Warning! There are some paths in the root of the document, but not in any layer! Using bottom-most layer for them.") + + if root in self.selected_paths: + if self.layers[-1] in self.selected_paths: + self.selected_paths[self.layers[-1]] += self.selected_paths[root][:] + else: + self.selected_paths[self.layers[-1]] = self.selected_paths[root][:] + del self.selected_paths[root] + + if root in self.paths: + if self.layers[-1] in self.paths: + self.paths[self.layers[-1]] += self.paths[root][:] + else: + self.paths[self.layers[-1]] = self.paths[root][:] + del self.paths[root] + + def get_orientation_points(self, g): + items = g.getchildren() + items.reverse() + p2 = [] + p3 = [] + p = None + for i in items: + if isinstance(i, inkex.Group): + if i.get("gcodetools") == "Gcodetools orientation point (2 points)": + p2 += [i] + if i.get("gcodetools") == "Gcodetools orientation point (3 points)": + p3 += [i] + if len(p2) == 2: + p = p2 + elif len(p3) == 3: + p = p3 + if p is None: + return None + points = [] + for i in p: + point = [[], []] + for node in i: + if node.get('gcodetools') == "Gcodetools orientation point arrow": + csp = node.path.transform(node.composed_transform()).to_superpath() + point[0] = csp[0][0][1] + if node.get('gcodetools') == "Gcodetools orientation point text": + inkex.errormsg(node.get_text()) + r = re.match(r'(?i)\s*\(\s*(-?\s*\d*(?:,|\.)*\d*)\s*;\s*(-?\s*\d*(?:,|\.)*\d*)\s*;\s*(-?\s*\d*(?:,|\.)*\d*)\s*\)\s*', node.get_text()) + point[1] = [float(r.group(1)), float(r.group(2)), float(r.group(3))] + if point[0] != [] and point[1] != []: + points += [point] + if len(points) == len(p2) == 2 or len(points) == len(p3) == 3: + return points + else: + return None + + def get_graffiti_reference_points(self, g): + point = [[], ''] + for node in g: + if node.get('gcodetools') == "Gcodetools graffiti reference point arrow": + point[0] = self.apply_transforms(node, node.path.to_superpath())[0][0][1] + if node.get('gcodetools') == "Gcodetools graffiti reference point text": + point[1] = node.get_text() + if point[0] != [] and point[1] != '': + return point + else: + return [] + + def get_tool(self, g): + tool = self.default_tool.copy() + tool["self_group"] = g + for i in g: + # Get parameters + if i.get("gcodetools") == "Gcodetools tool background": + tool["style"] = dict(i.style) + elif i.get("gcodetools") == "Gcodetools tool parameter": + key = None + value = None + for j in i: + # need to recognise old tools from ver 1.6.04 + if j.get("gcodetools") == "Gcodetools tool definition field name" or j.get("gcodetools") == "Gcodetools tool defention field name": + key = j.get_text() + if j.get("gcodetools") == "Gcodetools tool definition field value" or j.get("gcodetools") == "Gcodetools tool defention field value": + value = j.get_text() + if value == "(None)": + value = "" + if value is None or key is None: + continue + if key in self.default_tool.keys(): + try: + tool[key] = type(self.default_tool[key])(value) + except: + tool[key] = self.default_tool[key] + self.error("Warning! Tool's and default tool's parameter's ({}) types are not the same ( type('{}') != type('{}') ).".format(key, value, self.default_tool[key])) + else: + tool[key] = value + self.error("Warning! Tool has parameter that default tool has not ( '{}': '{}' ).".format(key, value)) + return tool + + def set_tool(self, layer): + for i in range(self.layers.index(layer), -1, -1): + if self.layers[i] in self.tools: + break + if self.layers[i] in self.tools: + if self.layers[i] != layer: + self.tools[layer] = self.tools[self.layers[i]] + if len(self.tools[layer]) > 1: + label = self.layers[i].label + self.error(f"Layer '{label}' contains more than one tool!") + return self.tools[layer] + else: + self.error(f"Can not find tool for '{layer.label}' layer! Please add one with Tools library tab!", "error") + + ################################################################################ + # + # Path to Gcode + # + ################################################################################ + def tab_path_to_gcode(self): + self.get_info_plus() + def get_boundaries(points): + minx = None + miny = None + maxx = None + maxy = None + out = [[], [], [], []] + for p in points: + if minx == p[0]: + out[0] += [p] + if minx is None or p[0] < minx: + minx = p[0] + out[0] = [p] + + if miny == p[1]: + out[1] += [p] + if miny is None or p[1] < miny: + miny = p[1] + out[1] = [p] + + if maxx == p[0]: + out[2] += [p] + if maxx is None or p[0] > maxx: + maxx = p[0] + out[2] = [p] + + if maxy == p[1]: + out[3] += [p] + if maxy is None or p[1] > maxy: + maxy = p[1] + out[3] = [p] + return out + + def remove_duplicates(points): + i = 0 + out = [] + for p in points: + for j in xrange(i, len(points)): + if p == points[j]: + points[j] = [None, None] + if p != [None, None]: + out += [p] + i += 1 + return out + + def get_way_len(points): + l = 0 + for i in xrange(1, len(points)): + l += math.sqrt((points[i][0] - points[i - 1][0]) ** 2 + (points[i][1] - points[i - 1][1]) ** 2) + return l + + def sort_dxfpoints(points): + points = remove_duplicates(points) + ways = [ + # l=0, d=1, r=2, u=3 + [3, 0], # ul + [3, 2], # ur + [1, 0], # dl + [1, 2], # dr + [0, 3], # lu + [0, 1], # ld + [2, 3], # ru + [2, 1], # rd + ] + minimal_way = [] + minimal_len = None + for w in ways: + tpoints = points[:] + cw = [] + for j in xrange(0, len(points)): + p = get_boundaries(get_boundaries(tpoints)[w[0]])[w[1]] + tpoints.remove(p[0]) + cw += p + curlen = get_way_len(cw) + if minimal_len is None or curlen < minimal_len: + minimal_len = curlen + minimal_way = cw + + return minimal_way + + def sort_lines(lines): + if len(lines) == 0: + return [] + lines = [[key] + lines[key] for key in range(len(lines))] + keys = [0] + end_point = lines[0][3:] + print_("!!!", lines, "\n", end_point) + del lines[0] + while len(lines) > 0: + dist = [[point_to_point_d2(end_point, lines[i][1:3]), i] for i in range(len(lines))] + i = min(dist)[1] + keys.append(lines[i][0]) + end_point = lines[i][3:] + del lines[i] + return keys + + def sort_curves(curves): + lines = [] + for curve in curves: + lines += [curve[0][0][0] + curve[-1][-1][0]] + return sort_lines(lines) + + def print_dxfpoints(points): + gcode = "" + for point in points: + gcode += "(drilling dxfpoint)\nG00 Z{:f}\nG00 X{:f} Y{:f}\nG01 Z{:f} F{:f}\nG04 P{:f}\nG00 Z{:f}\n".format(self.options.Zsafe, point[0], point[1], self.Zcoordinates[layer][1], self.tools[layer][0]["penetration feed"], 0.2, self.options.Zsafe) + return gcode + + def get_path_properties(node): + res = {} + done = False + while not done and node != self.svg: + for i in node.getchildren(): + if isinstance(i, inkex.Desc): + res["Description"] = i.text + elif isinstance(i, inkex.Title): + res["Title"] = i.text + done = True + node = node.getparent() + return res + + if self.selected_paths == {} and self.options.auto_select_paths: + paths = self.paths + self.error("No paths are selected! Trying to work on all available paths.") + else: + paths = self.selected_paths + self.check_dir() + gcode = "" + + parent = list(self.selected_paths)[0] if self.selected_paths else self.layers[0] + biarc_group = parent.add(Group()) + print_(("self.layers=", self.layers)) + print_(("paths=", paths)) + colors = {} + for layer in self.layers: + if layer in paths: + print_(("layer", layer)) + # transform simple path to get all var about orientation + self.transform_csp([[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]], layer) + + self.set_tool(layer) + curves = [] + dxfpoints = [] + + try: + depth_func = eval('lambda c,d,s: ' + self.options.path_to_gcode_depth_function.strip('"')) + except: + self.error("Bad depth function! Enter correct function at Path to Gcode tab!") + + for path in paths[layer]: + if "d" not in path.keys(): + self.error("Warning: One or more paths do not have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!") + continue + csp = path.path.to_superpath() + csp = self.apply_transforms(path, csp) + id_ = path.get("id") + + def set_comment(match, path): + if match.group(1) in path.keys(): + return path.get(match.group(1)) + else: + return "None" + + if self.options.comment_gcode != "": + comment = re.sub("\\[([A-Za-z_\\-\\:]+)\\]", partial(set_comment, path=path), self.options.comment_gcode) + comment = comment.replace(":newline:", "\n") + comment = gcode_comment_str(comment) + else: + comment = "" + if self.options.comment_gcode_from_properties: + tags = get_path_properties(path) + for tag in tags: + comment += gcode_comment_str("{}: {}".format(tag, tags[tag])) + + stroke = path.style('stroke') + colors[id_] = inkex.Color(stroke if stroke != None else "#000").to_rgb() + if path.get("dxfpoint") == "1": + tmp_curve = self.transform_csp(csp, layer) + x = tmp_curve[0][0][0][0] + y = tmp_curve[0][0][0][1] + print_("got dxfpoint (scaled) at ({:f},{:f})".format(x, y)) + dxfpoints += [[x, y]] + else: + + zd = self.Zcoordinates[layer][1] + zs = self.Zcoordinates[layer][0] + c = 1. - float(sum(colors[id_])) / 255 / 3 + curves += [ + [ + [id_, depth_func(c, zd, zs), comment], + [self.parse_curve([subpath], layer) for subpath in csp] + ] + ] + dxfpoints = sort_dxfpoints(dxfpoints) + gcode += print_dxfpoints(dxfpoints) + + for curve in curves: + for subcurve in curve[1]: + self.draw_curve(subcurve, layer) + + if self.options.path_to_gcode_order == 'subpath by subpath': + curves_ = [] + for curve in curves: + curves_ += [[curve[0], [subcurve]] for subcurve in curve[1]] + curves = curves_ + + self.options.path_to_gcode_order = 'path by path' + + if self.options.path_to_gcode_order == 'path by path': + if self.options.path_to_gcode_sort_paths: + keys = sort_curves([curve[1] for curve in curves]) + else: + keys = range(len(curves)) + for key in keys: + d = curves[key][0][1] + for step in range(0, int(math.ceil(abs((zs - d) / self.tools[layer][0]["depth step"])))): + z = max(d, zs - abs(self.tools[layer][0]["depth step"] * (step + 1))) + + gcode += gcode_comment_str("\nStart cutting path id: {}".format(curves[key][0][0])) + if curves[key][0][2] != "()": + gcode += curves[key][0][2] # add comment + + for curve in curves[key][1]: + gcode += self.generate_gcode(curve, layer, z) + + gcode += gcode_comment_str("End cutting path id: {}\n\n".format(curves[key][0][0])) + + else: # pass by pass + mind = min([curve[0][1] for curve in curves]) + for step in range(0, 1 + int(math.ceil(abs((zs - mind) / self.tools[layer][0]["depth step"])))): + z = zs - abs(self.tools[layer][0]["depth step"] * step) + curves_ = [] + for curve in curves: + if curve[0][1] < z: + curves_.append(curve) + + z = zs - abs(self.tools[layer][0]["depth step"] * (step + 1)) + gcode += "\n(Pass at depth {})\n".format(z) + + if self.options.path_to_gcode_sort_paths: + keys = sort_curves([curve[1] for curve in curves_]) + else: + keys = range(len(curves_)) + for key in keys: + + gcode += gcode_comment_str("Start cutting path id: {}".format(curves[key][0][0])) + if curves[key][0][2] != "()": + gcode += curves[key][0][2] # add comment + + for subcurve in curves_[key][1]: + gcode += self.generate_gcode(subcurve, layer, max(z, curves_[key][0][1])) + + gcode += gcode_comment_str("End cutting path id: {}\n\n".format(curves[key][0][0])) + + self.export_gcode(gcode) + + ################################################################################ + # + # dxfpoints + # + ################################################################################ + def tab_dxfpoints(self): + self.get_info_plus() + if self.selected_paths == {}: + self.error("Nothing is selected. Please select something to convert to drill point (dxfpoint) or clear point sign.") + for layer in self.layers: + if layer in self.selected_paths: + for path in self.selected_paths[layer]: + if self.options.dxfpoints_action == 'replace': + + path.set("dxfpoint", "1") + r = re.match("^\\s*.\\s*(\\S+)", path.get("d")) + if r is not None: + print_(("got path=", r.group(1))) + path.set("d", "m {} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000001 z".format(r.group(1))) + path.set("style", MARKER_STYLE["dxf_points"]) + + if self.options.dxfpoints_action == 'save': + path.set("dxfpoint", "1") + + if self.options.dxfpoints_action == 'clear' and path.get("dxfpoint") == "1": + path.set("dxfpoint", "0") + + ################################################################################ + # + # Artefacts + # + ################################################################################ + def tab_area_artefacts(self): + self.get_info_plus() + if self.selected_paths == {} and self.options.auto_select_paths: + paths = self.paths + self.error("No paths are selected! Trying to work on all available paths.") + else: + paths = self.selected_paths + for layer in paths: + for path in paths[layer]: + parent = path.getparent() + if "d" not in path.keys(): + self.error("Warning: One or more paths do not have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!") + continue + csp = path.path.to_superpath() + remove = [] + for i in range(len(csp)): + subpath = [[point[:] for point in points] for points in csp[i]] + subpath = self.apply_transforms(path, [subpath])[0] + bounds = csp_simple_bound([subpath]) + if (bounds[2] - bounds[0]) ** 2 + (bounds[3] - bounds[1]) ** 2 < self.options.area_find_artefacts_diameter ** 2: + if self.options.area_find_artefacts_action == "mark with an arrow": + arrow = Path('m {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000001 z'.format(subpath[0][1][0], subpath[0][1][1])).to_superpath() + arrow = self.apply_transforms(path, arrow, True) + node = parent.add(PathElement()) + node.path = CubicSuperPath(arrow) + node.style = MARKER_STYLE["area artefact arrow"] + node.set('gcodetools', 'area artefact arrow') + elif self.options.area_find_artefacts_action == "mark with style": + node = parent.add(PathElement()) + node.path = CubicSuperPath(csp[i]) + node.style = MARKER_STYLE["area artefact"] + remove.append(i) + elif self.options.area_find_artefacts_action == "delete": + remove.append(i) + print_("Deleted artefact {}".format(subpath)) + remove.reverse() + for i in remove: + del csp[i] + if len(csp) == 0: + parent.remove(path) + else: + path.path = CubicSuperPath(csp) + + return + + def tab_area(self): + """Calculate area curves""" + self.get_info_plus() + if len(self.selected_paths) <= 0: + self.error("This extension requires at least one selected path.") + return + for layer in self.layers: + if layer in self.selected_paths: + self.set_tool(layer) + if self.tools[layer][0]['diameter'] <= 0: + self.error(f"Tool diameter must be > 0 but tool's diameter on '{layer.label}' layer is not!", "error") + + for path in self.selected_paths[layer]: + print_(("doing path", path.get("style"), path.get("d"))) + + area_group = path.getparent().add(Group()) + + csp = path.path.to_superpath() + print_(csp) + if not csp: + print_("omitting non-path") + self.error("Warning: omitting non-path") + continue + + if path.get('sodipodi:type') != "inkscape:offset": + print_("Path {} is not an offset. Preparation started.".format(path.get("id"))) + # Path is not offset. Preparation will be needed. + # Finding top most point in path (min y value) + + min_x, min_y, min_i, min_j, min_t = csp_true_bounds(csp)[1] + + # Reverse path if needed. + if min_y != float("-inf"): + # Move outline subpath to the beginning of csp + subp = csp[min_i] + del csp[min_i] + j = min_j + # Split by the topmost point and join again + if min_t in [0, 1]: + if min_t == 0: + j = j - 1 + subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] + subp = [[subp[j][1], subp[j][1], subp[j][2]]] + subp[j + 1:] + subp[:j] + [[subp[j][0], subp[j][1], subp[j][1]]] + else: + sp1, sp2, sp3 = csp_split(subp[j - 1], subp[j], min_t) + subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1] + subp = [[sp2[1], sp2[1], sp2[2]]] + [sp3] + subp[j + 1:] + subp[:j - 1] + [sp1] + [[sp2[0], sp2[1], sp2[1]]] + csp = [subp] + csp + # reverse path if needed + if csp_subpath_ccw(csp[0]): + for i in range(len(csp)): + n = [] + for j in csp[i]: + n = [[j[2][:], j[1][:], j[0][:]]] + n + csp[i] = n[:] + + # What the absolute fudge is this doing? Closing paths? Ugh. + # Not sure but it most be at this level and not in the if statement, or it will not work with dynamic offsets + d = str(CubicSuperPath(csp)) + print_(("original d=", d)) + d = re.sub(r'(?i)(m[^mz]+)', r'\1 Z ', d) + d = re.sub(r'(?i)\s*z\s*z\s*', r' Z ', d) + d = re.sub(r'(?i)\s*([A-Za-z])\s*', r' \1 ', d) + print_(("formatted d=", d)) + p0 = self.transform([0, 0], layer) + p1 = self.transform([0, 1], layer) + scale = (P(p0) - P(p1)).mag() + if scale == 0: + scale = 1. + else: + scale = 1. / scale + print_(scale) + tool_d = self.tools[layer][0]['diameter'] * scale + r = self.options.area_inkscape_radius * scale + sign = 1 if r > 0 else -1 + print_("Tool diameter = {}, r = {}".format(tool_d, r)) + + # avoiding infinite loops + if self.options.area_tool_overlap > 0.9: + self.options.area_tool_overlap = .9 + + for i in range(self.options.max_area_curves): + radius = - tool_d * (i * (1 - self.options.area_tool_overlap) + 0.5) * sign + if abs(radius) > abs(r): + radius = -r + + elem = area_group.add(PathElement(style=str(MARKER_STYLE["biarc_style_i"]['area']))) + elem.set('sodipodi:type', 'inkscape:offset') + elem.set('inkscape:radius', radius) + elem.set('inkscape:original', d) + print_(("adding curve", area_group, d, str(MARKER_STYLE["biarc_style_i"]['area']))) + if radius == -r: + break + + def tab_area_fill(self): + """Fills area with lines""" + self.get_info_plus() + # convert degrees into rad + self.options.area_fill_angle = self.options.area_fill_angle * math.pi / 180 + if len(self.selected_paths) <= 0: + self.error("This extension requires at least one selected path.") + return + for layer in self.layers: + if layer in self.selected_paths: + self.set_tool(layer) + if self.tools[layer][0]['diameter'] <= 0: + self.error(f"Tool diameter must be > 0 but tool's diameter on '{layer.label}' layer is not!", "error") + tool = self.tools[layer][0] + for path in self.selected_paths[layer]: + lines = [] + print_(("doing path", path.get("style"), path.get("d"))) + area_group = path.getparent().add(Group()) + csp = path.path.to_superpath() + if not csp: + print_("omitting non-path") + self.error("Warning: omitting non-path") + continue + csp = self.apply_transforms(path, csp) + csp = csp_close_all_subpaths(csp) + csp = self.transform_csp(csp, layer) + + # rotate the path to get bounds in defined direction. + a = - self.options.area_fill_angle + rotated_path = [[[[point[0] * math.cos(a) - point[1] * math.sin(a), point[0] * math.sin(a) + point[1] * math.cos(a)] for point in sp] for sp in subpath] for subpath in csp] + bounds = csp_true_bounds(rotated_path) + + # Draw the lines + # Get path's bounds + b = [0.0, 0.0, 0.0, 0.0] # [minx,miny,maxx,maxy] + for k in range(4): + i = bounds[k][2] + j = bounds[k][3] + t = bounds[k][4] + + b[k] = csp_at_t(rotated_path[i][j - 1], rotated_path[i][j], t)[k % 2] + + # Zig-zag + r = tool['diameter'] * (1 - self.options.area_tool_overlap) + if r <= 0: + self.error('Tools diameter must be greater than 0!', 'error') + return + + lines += [[]] + + if self.options.area_fill_method == 'zig-zag': + i = b[0] - self.options.area_fill_shift * r + top = True + last_one = True + while i < b[2] or last_one: + if i >= b[2]: + last_one = False + if not lines[-1]: + lines[-1] += [[i, b[3]]] + + if top: + lines[-1] += [[i, b[1]], [i + r, b[1]]] + + else: + lines[-1] += [[i, b[3]], [i + r, b[3]]] + + top = not top + i += r + else: + + w = b[2] - b[0] + self.options.area_fill_shift * r + h = b[3] - b[1] + self.options.area_fill_shift * r + x = b[0] - self.options.area_fill_shift * r + y = b[1] - self.options.area_fill_shift * r + lines[-1] += [[x, y]] + stage = 0 + start = True + while w > 0 and h > 0: + stage = (stage + 1) % 4 + if stage == 0: + y -= h + h -= r + elif stage == 1: + x += w + if not start: + w -= r + start = False + elif stage == 2: + y += h + h -= r + elif stage == 3: + x -= w + w -= r + + lines[-1] += [[x, y]] + + stage = (stage + 1) % 4 + if w <= 0 and h > 0: + y = y - h if stage == 0 else y + h + if h <= 0 and w > 0: + x = x - w if stage == 3 else x + w + lines[-1] += [[x, y]] + # Rotate created paths back + a = self.options.area_fill_angle + lines = [[[point[0] * math.cos(a) - point[1] * math.sin(a), point[0] * math.sin(a) + point[1] * math.cos(a)] for point in subpath] for subpath in lines] + + # get the intersection points + + splitted_line = [[lines[0][0]]] + intersections = {} + for l1, l2, in zip(lines[0], lines[0][1:]): + ints = [] + + if l1[0] == l2[0] and l1[1] == l2[1]: + continue + for i in range(len(csp)): + for j in range(1, len(csp[i])): + sp1 = csp[i][j - 1] + sp2 = csp[i][j] + roots = csp_line_intersection(l1, l2, sp1, sp2) + for t in roots: + p = tuple(csp_at_t(sp1, sp2, t)) + if l1[0] == l2[0]: + t1 = (p[1] - l1[1]) / (l2[1] - l1[1]) + else: + t1 = (p[0] - l1[0]) / (l2[0] - l1[0]) + if 0 <= t1 <= 1: + ints += [[t1, p[0], p[1], i, j, t]] + if p in intersections: + intersections[p] += [[i, j, t]] + else: + intersections[p] = [[i, j, t]] + + ints.sort() + for i in ints: + splitted_line[-1] += [[i[1], i[2]]] + splitted_line += [[[i[1], i[2]]]] + splitted_line[-1] += [l2] + i = 0 + print_(splitted_line) + while i < len(splitted_line): + # check if the middle point of the first lines segment is inside the path. + # and remove the subline if not. + l1 = splitted_line[i][0] + l2 = splitted_line[i][1] + p = [(l1[0] + l2[0]) / 2, (l1[1] + l2[1]) / 2] + if not point_inside_csp(p, csp): + del splitted_line[i] + else: + i += 1 + + # and apply back transrormations to draw them + csp_line = csp_from_polyline(splitted_line) + csp_line = self.transform_csp(csp_line, layer, True) + + self.draw_csp(csp_line, group=area_group) + + ################################################################################ + # + # Engraving + # + # LT Notes to self: See wiki.inkscape.org/wiki/index.php/PythonEffectTutorial + # To create anything in the Inkscape document, look at the XML editor for + # details of how such an element looks in XML, then follow this model. + # layer number n appears in XML as + # + # to create it, use + # Mylayer = self.svg.add(Layer.new('layername')) + # + # group appears in XML as where nnnnn is a number + # + # to create it, use + # Mygroup = parent.add(Group(gcodetools="My group label") + # where parent may be the layer or a parent group. To get the parent group, you can use + # parent = self.selected_paths[layer][0].getparent() + ################################################################################ + def tab_engraving(self): + self.get_info_plus() + global cspm + global wl + global nlLT + global i + global j + global gcode_3Dleft + global gcode_3Dright + global max_dist # minimum of tool radius and user's requested maximum distance + global eye_dist + eye_dist = 100 # 3D constant. Try varying it for your eyes + + def bisect(nxy1, nxy2): + """LT Find angle bisecting the normals n1 and n2 + + Parameters: Normalised normals + Returns: nx - Normal of bisector, normalised to 1/cos(a) + ny - + sinBis2 - sin(angle turned/2): positive if turning in + Note that bisect(n1,n2) and bisect(n2,n1) give opposite sinBis2 results + If sinturn is less than the user's requested angle tolerance, I return 0 + """ + (nx1, ny1) = nxy1 + (nx2, ny2) = nxy2 + cosBis = math.sqrt(max(0, (1.0 + nx1 * nx2 - ny1 * ny2) / 2.0)) + # We can get correct sign of the sin, assuming cos is positive + if (abs(ny1 - ny2) < ENGRAVING_TOLERANCE) or (abs(cosBis) < ENGRAVING_TOLERANCE): + if abs(nx1 - nx2) < ENGRAVING_TOLERANCE: + return nx1, ny1, 0.0 + sinBis = math.copysign(1, ny1) + else: + sinBis = cosBis * (nx2 - nx1) / (ny1 - ny2) + # We can correct signs by noting that the dot product + # of bisector and either normal must be >0 + costurn = cosBis * nx1 + sinBis * ny1 + if costurn == 0: + return ny1 * 100, -nx1 * 100, 1 # Path doubles back on itself + sinturn = sinBis * nx1 - cosBis * ny1 + if costurn < 0: + sinturn = -sinturn + if 0 < sinturn * 114.6 < (180 - self.options.engraving_sharp_angle_tollerance): + sinturn = 0 # set to zero if less than the user wants to see. + return cosBis / costurn, sinBis / costurn, sinturn + # end bisect + + def get_radius_to_line(xy1, n_xy1, n_xy2, xy2, n_xy23, xy3, n_xy3): + """LT find biggest circle we can engrave here, if constrained by line 2-3 + + Parameters: + x1,y1,nx1,ny1 coordinates and normal of the line we're currently engraving + nx2,ny2 angle bisector at point 2 + x2,y2 coordinates of first point of line 2-3 + nx23,ny23 normal to the line 2-3 + x3,y3 coordinates of the other end + nx3,ny3 angle bisector at point 3 + Returns: + radius or self.options.engraving_max_dist if line doesn't limit radius + This function can be used in three ways: + - With nx1=ny1=0 it finds circle centred at x1,y1 + - with nx1,ny1 normalised, it finds circle tangential at x1,y1 + - with nx1,ny1 scaled by 1/cos(a) it finds circle centred on an angle bisector + where a is the angle between the bisector and the previous/next normals + + If the centre of the circle tangential to the line 2-3 is outside the + angle bisectors at its ends, ignore this line. + + Note that it handles corners in the conventional manner of letter cutting + by mitering, not rounding. + Algorithm uses dot products of normals to find radius + and hence coordinates of centre + """ + (x1, y1) = xy1 + (nx1, ny1) = n_xy1 + (nx2, ny2) = n_xy2 + (x2, y2) = xy2 + (nx23, ny23) = n_xy23 + (x3, y3) = xy3 + (nx3, ny3) = n_xy3 + global max_dist + + # Start by converting coordinates to be relative to x1,y1 + x2, y2 = x2 - x1, y2 - y1 + x3, y3 = x3 - x1, y3 - y1 + + # The logic uses vector arithmetic. + # The dot product of two vectors gives the product of their lengths + # multiplied by the cos of the angle between them. + # So, the perpendicular distance from x1y1 to the line 2-3 + # is equal to the dot product of its normal and x2y2 or x3y3 + # It is also equal to the projection of x1y1-xcyc on the line's normal + # plus the radius. But, as the normal faces inside the path we must negate it. + + # Make sure the line in question is facing x1,y1 and vice versa + dist = -x2 * nx23 - y2 * ny23 + if dist < 0: + return max_dist + denom = 1. - nx23 * nx1 - ny23 * ny1 + if denom < ENGRAVING_TOLERANCE: + return max_dist + + # radius and centre are: + r = dist / denom + cx = r * nx1 + cy = r * ny1 + # if c is not between the angle bisectors at the ends of the line, ignore + # Use vector cross products. Not sure if I need the .0001 safety margins: + if (x2 - cx) * ny2 > (y2 - cy) * nx2 + 0.0001: + return max_dist + if (x3 - cx) * ny3 < (y3 - cy) * nx3 - 0.0001: + return max_dist + return min(r, max_dist) + # end of get_radius_to_line + + def get_radius_to_point(xy1, n_xy, xy2): + """LT find biggest circle we can engrave here, constrained by point x2,y2 + + This function can be used in three ways: + - With nx=ny=0 it finds circle centred at x1,y1 + - with nx,ny normalised, it finds circle tangential at x1,y1 + - with nx,ny scaled by 1/cos(a) it finds circle centred on an angle bisector + where a is the angle between the bisector and the previous/next normals + + Note that I wrote this to replace find_cutter_centre. It is far less + sophisticated but, I hope, far faster. + It turns out that finding a circle touching a point is harder than a circle + touching a line. + """ + (x1, y1) = xy1 + (nx, ny) = n_xy + (x2, y2) = xy2 + global max_dist + + # Start by converting coordinates to be relative to x1,y1 + x2 = x2 - x1 + y2 = y2 - y1 + denom = nx ** 2 + ny ** 2 - 1 + if denom <= ENGRAVING_TOLERANCE: # Not a corner bisector + if denom == -1: # Find circle centre x1,y1 + return math.sqrt(x2 ** 2 + y2 ** 2) + # if x2,y2 not in front of the normal... + if x2 * nx + y2 * ny <= 0: + return max_dist + return (x2 ** 2 + y2 ** 2) / (2 * (x2 * nx + y2 * ny)) + # It is a corner bisector, so.. + discriminator = (x2 * nx + y2 * ny) ** 2 - denom * (x2 ** 2 + y2 ** 2) + if discriminator < 0: + return max_dist # this part irrelevant + r = (x2 * nx + y2 * ny - math.sqrt(discriminator)) / denom + return min(r, max_dist) + # end of get_radius_to_point + + def bez_divide(a, b, c, d): + """LT recursively divide a Bezier. + + Divides until difference between each + part and a straight line is less than some limit + Note that, as simple as this code is, it is mathematically correct. + Parameters: + a,b,c and d are each a list of x,y real values + Bezier end points a and d, control points b and c + Returns: + a list of Beziers. + Each Bezier is a list with four members, + each a list holding a coordinate pair + Note that the final point of one member is the same as + the first point of the next, and the control points + there are smooth and symmetrical. I use this fact later. + """ + bx = b[0] - a[0] + by = b[1] - a[1] + cx = c[0] - a[0] + cy = c[1] - a[1] + dx = d[0] - a[0] + dy = d[1] - a[1] + limit = 8 * math.hypot(dx, dy) / self.options.engraving_newton_iterations + # LT This is the only limit we get from the user currently + if abs(dx * by - bx * dy) < limit and abs(dx * cy - cx * dy) < limit: + return [[a, b, c, d]] + abx = (a[0] + b[0]) / 2.0 + aby = (a[1] + b[1]) / 2.0 + bcx = (b[0] + c[0]) / 2.0 + bcy = (b[1] + c[1]) / 2.0 + cdx = (c[0] + d[0]) / 2.0 + cdy = (c[1] + d[1]) / 2.0 + abcx = (abx + bcx) / 2.0 + abcy = (aby + bcy) / 2.0 + bcdx = (bcx + cdx) / 2.0 + bcdy = (bcy + cdy) / 2.0 + m = [(abcx + bcdx) / 2.0, (abcy + bcdy) / 2.0] + return bez_divide(a, [abx, aby], [abcx, abcy], m) + bez_divide(m, [bcdx, bcdy], [cdx, cdy], d) + # end of bez_divide + + def get_biggest(nxy1, nxy2): + """LT Find biggest circle we can draw inside path at point x1,y1 normal nx,ny + + Parameters: + point - either on a line or at a reflex corner + normal - normalised to 1 if on a line, to 1/cos(a) at a corner + Returns: + tuple (j,i,r) + ..where j and i are indices of limiting segment, r is radius + """ + (x1, y1) = nxy1 + (nx, ny) = nxy2 + global max_dist + global nlLT + global i + global j + + n1 = nlLT[j][i - 1] # current node + jjmin = -1 + iimin = -1 + r = max_dist + # set limits within which to look for lines + xmin = x1 + r * nx - r + xmax = x1 + r * nx + r + ymin = y1 + r * ny - r + ymax = y1 + r * ny + r + for jj in xrange(0, len(nlLT)): # for every subpath of this object + for ii in xrange(0, len(nlLT[jj])): # for every point and line + if nlLT[jj][ii - 1][2]: # if a point + if jj == j: # except this one + if abs(ii - i) < 3 or abs(ii - i) > len(nlLT[j]) - 3: + continue + t1 = get_radius_to_point((x1, y1), (nx, ny), nlLT[jj][ii - 1][0]) + else: # doing a line + if jj == j: # except this one + if abs(ii - i) < 2 or abs(ii - i) == len(nlLT[j]) - 1: + continue + if abs(ii - i) == 2 and nlLT[j][(ii + i) / 2 - 1][3] <= 0: + continue + if (abs(ii - i) == len(nlLT[j]) - 2) and nlLT[j][-1][3] <= 0: + continue + nx2, ny2 = nlLT[jj][ii - 2][1] + x2, y2 = nlLT[jj][ii - 1][0] + nx23, ny23 = nlLT[jj][ii - 1][1] + x3, y3 = nlLT[jj][ii][0] + nx3, ny3 = nlLT[jj][ii][1] + if nlLT[jj][ii - 2][3] > 0: # acute, so use normal, not bisector + nx2 = nx23 + ny2 = ny23 + if nlLT[jj][ii][3] > 0: # acute, so use normal, not bisector + nx3 = nx23 + ny3 = ny23 + x23min = min(x2, x3) + x23max = max(x2, x3) + y23min = min(y2, y3) + y23max = max(y2, y3) + # see if line in range + if n1[2] == False and (x23max < xmin or x23min > xmax or y23max < ymin or y23min > ymax): + continue + t1 = get_radius_to_line((x1, y1), (nx, ny), (nx2, ny2), (x2, y2), (nx23, ny23), (x3, y3), (nx3, ny3)) + if 0 <= t1 < r: + r = t1 + iimin = ii + jjmin = jj + xmin = x1 + r * nx - r + xmax = x1 + r * nx + r + ymin = y1 + r * ny - r + ymax = y1 + r * ny + r + # next ii + # next jj + return jjmin, iimin, r + # end of get_biggest + + def line_divide(xy0, j0, i0, xy1, j1, i1, n_xy, length): + """LT recursively divide a line as much as necessary + + NOTE: This function is not currently used + By noting which other path segment is touched by the circles at each end, + we can see if anything is to be gained by a further subdivision, since + if they touch the same bit of path we can move linearly between them. + Also, we can handle points correctly. + Parameters: + end points and indices of limiting path, normal, length + Returns: + list of toolpath points + each a list of 3 reals: x, y coordinates, radius + + """ + (x0, y0) = xy0 + (x1, y1) = xy1 + (nx, ny) = n_xy + global nlLT + global i + global j + global lmin + x2 = (x0 + x1) / 2 + y2 = (y0 + y1) / 2 + j2, i2, r2 = get_biggest((x2, y2), (nx, ny)) + if length < lmin: + return [[x2, y2, r2]] + if j2 == j0 and i2 == i0: # Same as left end. Don't subdivide this part any more + return [[x2, y2, r2], line_divide((x2, y2), j2, i2, (x1, y1), j1, i1, (nx, ny), length / 2)] + if j2 == j1 and i2 == i1: # Same as right end. Don't subdivide this part any more + return [line_divide((x0, y0), j0, i0, (x2, y2), j2, i2, (nx, ny), length / 2), [x2, y2, r2]] + return [line_divide((x0, y0), j0, i0, (x2, y2), j2, i2, (nx, ny), length / 2), line_divide((x2, y2), j2, i2, (x1, y1), j1, i1, (nx, ny), length / 2)] + # end of line_divide() + + def save_point(xy, w, i, j, ii, jj): + """LT Save this point and delete previous one if linear + + The point is, we generate tons of points but many may be in a straight 3D line. + There is no benefit in saving the intermediate points. + """ + (x, y) = xy + global wl + global cspm + x = round(x, 4) # round to 4 decimals + y = round(y, 4) # round to 4 decimals + w = round(w, 4) # round to 4 decimals + if len(cspm) > 1: + xy1a, xy1, xy1b, i1, j1, ii1, jj1 = cspm[-1] + w1 = wl[-1] + if i == i1 and j == j1 and ii == ii1 and jj == jj1: # one match + xy1a, xy2, xy1b, i1, j1, ii1, jj1 = cspm[-2] + w2 = wl[-2] + if i == i1 and j == j1 and ii == ii1 and jj == jj1: # two matches. Now test linearity + length1 = math.hypot(xy1[0] - x, xy1[1] - y) + length2 = math.hypot(xy2[0] - x, xy2[1] - y) + length12 = math.hypot(xy2[0] - xy1[0], xy2[1] - xy1[1]) + # get the xy distance of point 1 from the line 0-2 + if length2 > length1 and length2 > length12: # point 1 between them + xydist = abs((xy2[0] - x) * (xy1[1] - y) - (xy1[0] - x) * (xy2[1] - y)) / length2 + if xydist < ENGRAVING_TOLERANCE: # so far so good + wdist = w2 + (w - w2) * length1 / length2 - w1 + if abs(wdist) < ENGRAVING_TOLERANCE: + cspm.pop() + wl.pop() + cspm += [[[x, y], [x, y], [x, y], i, j, ii, jj]] + wl += [w] + # end of save_point + + def draw_point(xy0, xy, w, t): + """LT Draw this point as a circle with a 1px dot in the middle (x,y) + and a 3D line from (x0,y0) down to x,y. 3D line thickness should be t/2 + + Note that points that are subsequently erased as being unneeded do get + displayed, but this helps the user see the total area covered. + """ + (x0, y0) = xy0 + (x, y) = xy + global gcode_3Dleft + global gcode_3Dright + if self.options.engraving_draw_calculation_paths: + elem = engraving_group.add(PathElement.arc((x, y), 1)) + elem.set('gcodetools', "Engraving calculation toolpath") + elem.style = "fill:#ff00ff; fill-opacity:0.46; stroke:#000000; stroke-width:0.1;" + + # Don't draw zero radius circles + if w: + elem = engraving_group.add(PathElement.arc((x, y), w)) + elem.set('gcodetools', "Engraving calculation paths") + elem.style = "fill:none; fill-opacity:0.46; stroke:#000000; stroke-width:0.1;" + + # Find slope direction for shading + s = math.atan2(y - y0, x - x0) # -pi to pi + # convert to 2 hex digits as a shade of red + s2 = "#{0:x}0000".format(int(101 * (1.5 - math.sin(s + 0.5)))) + style = "stroke:{}; stroke-opacity:1;stroke-width:{};fill:none".format(s2, t/2) + right = gcode_3Dleft.add(PathElement(style=style, gcodetools="Gcode G1R")) + right.path = "M {:f},{:f} L {:f},{:f}".format( + x0 - eye_dist, y0, x - eye_dist - 0.14 * w, y) + left = gcode_3Dright.add(PathElement(style=style, gcodetools="Gcode G1L")) + left.path = "M {:f},{:f} L {:f},{:f}".format( + x0 + eye_dist, y0, x + eye_dist + 0.14 * r, y) + + # end of subfunction definitions. engraving() starts here: + gcode = '' + r = 0 # theoretical and tool-radius-limited radii in pixels + w = 0 + wmax = 0 + cspe = [] + we = [] + if not self.selected_paths: + self.error("Please select at least one path to engrave and run again.") + return + if not self.check_dir(): + return + # Find what units the user uses + unit = " mm" + if self.options.unit == "G20 (All units in inches)": + unit = " inches" + elif self.options.unit != "G21 (All units in mm)": + self.error("Unknown unit selected. mm assumed") + print_("engraving_max_dist mm/inch", self.options.engraving_max_dist) + + # LT See if we can use this parameter for line and Bezier subdivision: + bitlen = 20 / self.options.engraving_newton_iterations + + for layer in self.layers: + if layer in self.selected_paths and layer in self.orientation_points: + # Calculate scale in pixels per user unit (mm or inch) + p1 = self.orientation_points[layer][0][0] + p2 = self.orientation_points[layer][0][1] + ol = math.hypot(p1[0][0] - p2[0][0], p1[0][1] - p2[0][1]) + oluu = math.hypot(p1[1][0] - p2[1][0], p1[1][1] - p2[1][1]) + print_("Orientation2 p1 p2 ol oluu", p1, p2, ol, oluu) + orientation_scale = ol / oluu + + self.set_tool(layer) + shape = self.tools[layer][0]['shape'] + if re.search('w', shape): + toolshape = eval('lambda w: ' + shape.strip('"')) + else: + self.error("Tool '{}' has no shape. 45 degree cone assumed!".format(self.tools[layer][0]['name'])) + toolshape = lambda w: w + # Get tool radius in pixels + toolr = self.tools[layer][0]['diameter'] * orientation_scale / 2 + print_("tool radius in pixels=", toolr) + # max dist from path to engrave in user's units + max_distuu = min(self.tools[layer][0]['diameter'] / 2, self.options.engraving_max_dist) + max_dist = max_distuu * orientation_scale + print_("max_dist pixels", max_dist) + + engraving_group = self.selected_paths[layer][0].getparent().add(Group()) + if self.options.engraving_draw_calculation_paths and (self.my3Dlayer is None): + self.svg.add(Layer.new("3D")) + # Create groups for left and right eyes + if self.options.engraving_draw_calculation_paths: + gcode_3Dleft = self.my3Dlayer.add(Group(gcodetools="Gcode 3D L")) + gcode_3Dright = self.my3Dlayer.add(Group(gcodetools="Gcode 3D R")) + + for node in self.selected_paths[layer]: + if isinstance(node, inkex.PathElement): + cspi = node.path.to_superpath() + # LT: Create my own list. n1LT[j] is for subpath j + nlLT = [] + for j in xrange(len(cspi)): # LT For each subpath... + # Remove zero length segments, assume closed path + i = 0 # LT was from i=1 + while i < len(cspi[j]): + if abs(cspi[j][i - 1][1][0] - cspi[j][i][1][0]) < ENGRAVING_TOLERANCE and abs(cspi[j][i - 1][1][1] - cspi[j][i][1][1]) < ENGRAVING_TOLERANCE: + cspi[j][i - 1][2] = cspi[j][i][2] + del cspi[j][i] + else: + i += 1 + for csp in cspi: # LT6a For each subpath... + # Create copies in 3D layer + print_("csp is zz ", csp) + cspl = [] + cspr = [] + # create list containing lines and points, starting with a point + # line members: [x,y],[nx,ny],False,i + # x,y is start of line. Normal on engraved side. + # Normal is normalised (unit length) + # Note that Y axis increases down the page + # corner members: [x,y],[nx,ny],True,sin(halfangle) + # if halfangle>0: radius 0 here. normal is bisector + # if halfangle<0. reflex angle. normal is bisector + # corner normals are divided by cos(halfangle) + # so that they will engrave correctly + print_("csp is", csp) + nlLT.append([]) + for i in range(0, len(csp)): # LT for each point + sp0 = csp[i - 2] + sp1 = csp[i - 1] + sp2 = csp[i] + if self.options.engraving_draw_calculation_paths: + # Copy it to 3D layer objects + spl = [] + spr = [] + for j in range(0, 3): + pl = [sp2[j][0] - eye_dist, sp2[j][1]] + pr = [sp2[j][0] + eye_dist, sp2[j][1]] + spl += [pl] + spr += [pr] + cspl += [spl] + cspr += [spr] + # LT find angle between this and previous segment + x0, y0 = sp1[1] + nx1, ny1 = csp_normalized_normal(sp1, sp2, 0) + # I don't trust this function, so test result + if abs(1 - math.hypot(nx1, ny1)) > 0.00001: + print_("csp_normalised_normal error t=0", nx1, ny1, sp1, sp2) + self.error("csp_normalised_normal error. See log.") + + nx0, ny0 = csp_normalized_normal(sp0, sp1, 1) + if abs(1 - math.hypot(nx0, ny0)) > 0.00001: + print_("csp_normalised_normal error t=1", nx0, ny0, sp1, sp2) + self.error("csp_normalised_normal error. See log.") + bx, by, s = bisect((nx0, ny0), (nx1, ny1)) + # record x,y,normal,ifCorner, sin(angle-turned/2) + nlLT[-1] += [[[x0, y0], [bx, by], True, s]] + + # LT now do the line + if sp1[1] == sp1[2] and sp2[0] == sp2[1]: # straightline + nlLT[-1] += [[sp1[1], [nx1, ny1], False, i]] + else: # Bezier. First, recursively cut it up: + nn = bez_divide(sp1[1], sp1[2], sp2[0], sp2[1]) + first = True # Flag entry to divided Bezier + for bLT in nn: # save as two line segments + for seg in range(3): + if seg > 0 or first: + nx1 = bLT[seg][1] - bLT[seg + 1][1] + ny1 = bLT[seg + 1][0] - bLT[seg][0] + l1 = math.hypot(nx1, ny1) + if l1 < ENGRAVING_TOLERANCE: + continue + nx1 = nx1 / l1 # normalise them + ny1 = ny1 / l1 + nlLT[-1] += [[bLT[seg], [nx1, ny1], False, i]] + first = False + if seg < 2: # get outgoing bisector + nx0 = nx1 + ny0 = ny1 + nx1 = bLT[seg + 1][1] - bLT[seg + 2][1] + ny1 = bLT[seg + 2][0] - bLT[seg + 1][0] + l1 = math.hypot(nx1, ny1) + if l1 < ENGRAVING_TOLERANCE: + continue + nx1 = nx1 / l1 # normalise them + ny1 = ny1 / l1 + # bisect + bx, by, s = bisect((nx0, ny0), (nx1, ny1)) + nlLT[-1] += [[bLT[seg + 1], [bx, by], True, 0.]] + # LT for each segment - ends here. + print_(("engraving_draw_calculation_paths=", self.options.engraving_draw_calculation_paths)) + if self.options.engraving_draw_calculation_paths: + # Copy complete paths to 3D layer + cspl += [cspl[0]] # Close paths + cspr += [cspr[0]] # Close paths + style = "stroke:#808080; stroke-opacity:1; stroke-width:0.6; fill:none" + elem = gcode_3Dleft.add(PathElement(style=style, gcodetools="G1L outline")) + elem.path = CubicSuperPath([cspl]) + elem = gcode_3Dright.add(Pathelement(style=style, gcodetools="G1R outline")) + elem.path = CubicSuperPath([cspr]) + + for p in nlLT[-1]: # For last sub-path + if p[2]: + elem = engraving_group.add(PathElement(gcodetools="Engraving normals")) + elem.path = "M {:f},{:f} L {:f},{:f}".format(p[0][0], p[0][1], + p[0][0] + p[1][0] * 10, p[0][1] + p[1][1] * 10) + elem.style = "stroke:#f000af; stroke-opacity:0.46; stroke-width:0.1; fill:none" + else: + elem = engraving_group.add(PathElement(gcodetools="Engraving bisectors")) + elem.path = "M {:f},{:f} L {:f},{:f}".format(p[0][0], p[0][1], + p[0][0] + p[1][0] * 10, p[0][1] + p[1][1] * 10) + elem.style = "stroke:#0000ff; stroke-opacity:0.46; stroke-width:0.1; fill:none" + + # LT6a build nlLT[j] for each subpath - ends here + # Calculate offset points + reflex = False + for j in xrange(len(nlLT)): # LT6b for each subpath + cspm = [] # Will be my output. List of csps. + wl = [] # Will be my w output list + w = r = 0 # LT initial, as first point is an angle + for i in xrange(len(nlLT[j])): # LT for each node + # LT Note: Python enables wrapping of array indices + # backwards to -1, -2, but not forwards. Hence: + n0 = nlLT[j][i - 2] # previous node + n1 = nlLT[j][i - 1] # current node + n2 = nlLT[j][i] # next node + # if n1[2] == True and n1[3]==0 : # A straight angle + # continue + x1a, y1a = n1[0] # this point/start of this line + nx, ny = n1[1] + x1b, y1b = n2[0] # next point/end of this line + if n1[2]: # We're at a corner + bits = 1 + bit0 = 0 + # lastr=r #Remember r from last line + lastw = w # Remember w from last line + w = max_dist + if n1[3] > 0: # acute. Limit radius + len1 = math.hypot((n0[0][0] - n1[0][0]), (n0[0][1] - n1[0][1])) + if i < (len(nlLT[j]) - 1): + len2 = math.hypot((nlLT[j][i + 1][0][0] - n1[0][0]), (nlLT[j][i + 1][0][1] - n1[0][1])) + else: + len2 = math.hypot((nlLT[j][0][0][0] - n1[0][0]), (nlLT[j][0][0][1] - n1[0][1])) + # set initial r value, not to be exceeded + w = math.sqrt(min(len1, len2)) / n1[3] + else: # line. Cut it up if long. + if n0[3] > 0 and not self.options.engraving_draw_calculation_paths: + bit0 = r * n0[3] # after acute corner + else: + bit0 = 0.0 + length = math.hypot((x1b - x1a), (y1a - y1b)) + bit0 = (min(length, bit0)) + bits = int((length - bit0) / bitlen) + # split excess evenly at both ends + bit0 += (length - bit0 - bitlen * bits) / 2 + for b in xrange(bits): # divide line into bits + x1 = x1a + ny * (b * bitlen + bit0) + y1 = y1a - nx * (b * bitlen + bit0) + jjmin, iimin, w = get_biggest((x1, y1), (nx, ny)) + print_("i,j,jjmin,iimin,w", i, j, jjmin, iimin, w) + wmax = max(wmax, w) + if reflex: # just after a reflex corner + reflex = False + if w < lastw: # need to adjust it + draw_point((x1, y1), (n0[0][0] + n0[1][0] * w, n0[0][1] + n0[1][1] * w), w, (lastw - w) / 2) + save_point((n0[0][0] + n0[1][0] * w, n0[0][1] + n0[1][1] * w), w, i, j, iimin, jjmin) + if n1[2]: # We're at a corner + if n1[3] > 0: # acute + save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin) + draw_point((x1, y1), (x1, y1), 0, 0) + save_point((x1, y1), 0, i, j, iimin, jjmin) + elif n1[3] < 0: # reflex + if w > lastw: + draw_point((x1, y1), (x1 + nx * lastw, y1 + ny * lastw), w, (w - lastw) / 2) + wmax = max(wmax, w) + save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin) + elif b > 0 and n2[3] > 0 and not self.options.engraving_draw_calculation_paths: # acute corner coming up + if jjmin == j and iimin == i + 2: + break + draw_point((x1, y1), (x1 + nx * w, y1 + ny * w), w, bitlen) + save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin) + + # LT end of for each bit of this line + if n1[2] == True and n1[3] < 0: # reflex angle + reflex = True + lastw = w # remember this w + # LT next i + cspm += [cspm[0]] + print_("cspm", cspm) + wl += [wl[0]] + print_("wl", wl) + # Note: Original csp_points was a list, each element + # being 4 points, with the first being the same as the + # last of the previous set. + # Each point is a list of [cx,cy,r,w] + # I have flattened it to a flat list of points. + + if self.options.engraving_draw_calculation_paths: + node = engraving_group.add(PathElement( + gcodetools="Engraving calculation paths", + style=MARKER_STYLE["biarc_style_i"]['biarc1'])) + node.path = CubicSuperPath([cspm]) + for i in xrange(len(cspm)): + elem = engraving_group.add(PathElement.arc(cspm[i][1], wl[i])) + elem.set('gcodetools', "Engraving calculation paths") + elem.style = "fill:none;fill-opacity:0.46;stroke:#000000;stroke-width:0.1;" + cspe += [cspm] + wluu = [] # width list in user units: mm/inches + for w in wl: + wluu += [w / orientation_scale] + print_("wl in pixels", wl) + print_("wl in user units", wluu) + # LT previously, we was in pixels so gave wrong depth + we += [wluu] + # LT6b For each subpath - ends here + # LT5 if it is a path - ends here + # LT4 for each selected object in this layer - ends here + + if cspe: + curve = self.parse_curve(cspe, layer, we, toolshape) # convert to lines + self.draw_curve(curve, layer, engraving_group) + gcode += self.generate_gcode(curve, layer, self.options.Zsurface) + + # LT3 for layers loop ends here + if gcode != '': + self.header += "(Tool diameter should be at least " + str(2 * wmax / orientation_scale) + unit + ")\n" + self.header += "(Depth, as a function of radius w, must be " + self.tools[layer][0]['shape'] + ")\n" + self.header += "(Rapid feeds use safe Z=" + str(self.options.Zsafe) + unit + ")\n" + self.header += "(Material surface at Z=" + str(self.options.Zsurface) + unit + ")\n" + self.export_gcode(gcode) + else: + self.error("No need to engrave sharp angles.") + + ################################################################################ + # + # Orientation + # + ################################################################################ + def tab_orientation(self, layer=None): + self.get_info() + Zsurface = f"{self.options.Zsurface:.5f}" + Zdepth = f"{self.options.Zdepth:.5f}" + if layer is None: + layer = self.svg.get_current_layer() if self.svg.get_current_layer() is not None else self.document.getroot() + + transform = self.get_transforms(layer) + if transform: + transform = self.reverse_transform(transform) + transform = str(Transform(transform)) + + if self.options.orientation_points_count == "graffiti": + print_(self.graffiti_reference_points) + print_("Inserting graffiti points") + if layer in self.graffiti_reference_points: + graffiti_reference_points_count = len(self.graffiti_reference_points[layer]) + else: + graffiti_reference_points_count = 0 + axis = ["X", "Y", "Z", "A"][graffiti_reference_points_count % 4] + attr = {'gcodetools': "Gcodetools graffiti reference point"} + if transform: + attr["transform"] = transform + group = layer.add(Group(**attr)) + elem = group.add(PathElement(style="stroke:none;fill:#00ff00;")) + elem.set('gcodetools', "Gcodetools graffiti reference point arrow") + elem.path = 'm {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,'\ + '-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.8125000000'\ + '01 z z'.format(graffiti_reference_points_count * 100, 0) + + draw_text(axis, graffiti_reference_points_count * 100 + 10, -10, group=group, gcodetools_tag="Gcodetools graffiti reference point text") + + elif self.options.orientation_points_count == "in-out reference point": + draw_pointer(group=self.svg.get_current_layer(), x=self.svg.namedview.center, figure="arrow", pointer_type="In-out reference point", text="In-out point") + + else: + print_("Inserting orientation points") + + if layer in self.orientation_points: + self.error("Active layer already has orientation points! Remove them or select another layer!", "error") + + attr = {"gcodetools": "Gcodetools orientation group"} + if transform: + attr["transform"] = transform + + orientation_group = layer.add(Group(**attr)) + doc_height = self.svg.unittouu(self.document.getroot().get('height')) + if self.document.getroot().get('height') == "100%": + doc_height = 1052.3622047 + print_("Overriding height from 100 percents to {}".format(doc_height)) + if self.options.unit == "G21 (All units in mm)": + points = [[0., 0., Zsurface], [100., 0., Zdepth], [0., 100., 0.]] + elif self.options.unit == "G20 (All units in inches)": + points = [[0., 0., Zsurface], [5., 0., Zdepth], [0., 5., 0.]] + if self.options.orientation_points_count == "2": + points = points[:2] + for i in points: + name = "Gcodetools orientation point ({} points)".format( + self.options.orientation_points_count) + grp = orientation_group.add(Group(gcodetools=name)) + elem = grp.add(PathElement(style="stroke:none;fill:#000000;")) + elem.set('gcodetools', "Gcodetools orientation point arrow") + elem.path = 'm {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,'\ + '-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000'\ + '001 z'.format(i[0], -i[1] + doc_height) + + draw_text("({}; {}; {})".format(i[0], i[1], i[2]), (i[0] + 10), (-i[1] - 10 + doc_height), group=grp, gcodetools_tag="Gcodetools orientation point text") + + ################################################################################ + # + # Tools library + # + ################################################################################ + def tab_tools_library(self, layer=None): + self.get_info() + + if self.options.tools_library_type == "check": + return self.check_tools_and_op() + + # Add a tool to the drawing + if layer is None: + layer = self.svg.get_current_layer() if self.svg.get_current_layer() is not None else self.document.getroot() + if layer in self.tools: + self.error("Active layer already has a tool! Remove it or select another layer!", "error") + + if self.options.tools_library_type == "cylinder cutter": + tool = { + "name": "Cylindrical cutter", + "id": "Cylindrical cutter 0001", + "diameter": 10, + "penetration angle": 90, + "feed": "400", + "penetration feed": "100", + "depth step": "1", + "tool change gcode": " " + } + elif self.options.tools_library_type == "lathe cutter": + tool = { + "name": "Lathe cutter", + "id": "Lathe cutter 0001", + "diameter": 10, + "penetration angle": 90, + "feed": "400", + "passing feed": "800", + "fine feed": "100", + "penetration feed": "100", + "depth step": "1", + "tool change gcode": " " + } + elif self.options.tools_library_type == "cone cutter": + tool = { + "name": "Cone cutter", + "id": "Cone cutter 0001", + "diameter": 10, + "shape": "w", + "feed": "400", + "penetration feed": "100", + "depth step": "1", + "tool change gcode": " " + } + elif self.options.tools_library_type == "tangent knife": + tool = { + "name": "Tangent knife", + "id": "Tangent knife 0001", + "feed": "400", + "penetration feed": "100", + "depth step": "100", + "4th axis meaning": "tangent knife", + "4th axis scale": 1., + "4th axis offset": 0, + "tool change gcode": " " + } + + elif self.options.tools_library_type == "plasma cutter": + tool = { + "name": "Plasma cutter", + "id": "Plasma cutter 0001", + "diameter": 10, + "penetration feed": 100, + "feed": 400, + "gcode before path": """G31 Z-100 F500 (find metal) +G92 Z0 (zero z) +G00 Z10 F500 (going up) +M03 (turn on plasma) +G04 P0.2 (pause) +G01 Z1 (going to cutting z)\n""", + "gcode after path": "M05 (turn off plasma)\n", + } + elif self.options.tools_library_type == "graffiti": + tool = { + "name": "Graffiti", + "id": "Graffiti 0001", + "diameter": 10, + "penetration feed": 100, + "feed": 400, + "gcode before path": """M03 S1(Turn spray on)\n """, + "gcode after path": "M05 (Turn spray off)\n ", + "tool change gcode": "(Add G00 here to change sprayer if needed)\n", + + } + + else: + tool = self.default_tool + + tool_num = sum([len(self.tools[i]) for i in self.tools]) + colors = ["00ff00", "0000ff", "ff0000", "fefe00", "00fefe", "fe00fe", "fe7e00", "7efe00", "00fe7e", "007efe", "7e00fe", "fe007e"] + + tools_group = layer.add(Group(gcodetools="Gcodetools tool definition")) + bg = tools_group.add(PathElement(gcodetools="Gcodetools tool background")) + bg.style = "fill-opacity:0.5;stroke:#444444;" + bg.style['fill'] = "#" + colors[tool_num % len(colors)] + + y = 0 + keys = [] + for key in self.tools_field_order: + if key in tool: + keys += [key] + for key in tool: + if key not in keys: + keys += [key] + for key in keys: + g = tools_group.add(Group(gcodetools="Gcodetools tool parameter")) + draw_text(key, 0, y, group=g, gcodetools_tag="Gcodetools tool definition field name", font_size=10 if key != 'name' else 20) + param = tool[key] + if type(param) == str and re.match("^\\s*$", param): + param = "(None)" + draw_text(param, 150, y, group=g, gcodetools_tag="Gcodetools tool definition field value", font_size=10 if key != 'name' else 20) + v = str(param).split("\n") + y += 15 * len(v) if key != 'name' else 20 * len(v) + + bg.set('d', "m -20,-20 l 400,0 0,{:f} -400,0 z ".format(y + 50)) + tools_group.transform.add_translate(*self.svg.namedview.center) + tools_group.transform.add_translate(-150, 0) + + ################################################################################ + # + # Check tools and OP assignment + # + ################################################################################ + def check_tools_and_op(self): + if len(self.svg.selected) <= 0: + self.error("Selection is empty! Will compute whole drawing.") + paths = self.paths + else: + paths = self.selected_paths + # Set group + parent = self.selected_paths.keys()[0] if len(self.selected_paths.keys()) > 0 else self.layers[0] + group = parent.add(Group()) + trans_ = [[1, 0.3, 0], [0, 0.5, 0]] + + self.set_markers() + + bounds = [float('inf'), float('inf'), float('-inf'), float('-inf')] + tools_bounds = {} + for layer in self.layers: + if layer in paths: + self.set_tool(layer) + tool = self.tools[layer][0] + tools_bounds[layer] = tools_bounds[layer] if layer in tools_bounds else [float("inf"), float("-inf")] + for path in paths[layer]: + group.insert(0, PathElement(**path.attrib)) + new = group.getchildren()[0] + new.style = Style( + stroke='#000044', stroke_width=1, + marker_mid='url(#CheckToolsAndOPMarker)', + fill=tool["style"].get('fill', '#00ff00'), + fill_opacity=tool["style"].get('fill-opacity', 0.5)) + + trans = trans_ * self.get_transforms(path) + csp = path.path.transform(trans).to_superpath() + + path_bounds = csp_simple_bound(csp) + trans = str(Transform(trans)) + bounds = [min(bounds[0], path_bounds[0]), min(bounds[1], path_bounds[1]), max(bounds[2], path_bounds[2]), max(bounds[3], path_bounds[3])] + tools_bounds[layer] = [min(tools_bounds[layer][0], path_bounds[1]), max(tools_bounds[layer][1], path_bounds[3])] + + new.set("transform", trans) + trans_[1][2] += 20 + trans_[1][2] += 100 + + for layer in self.layers: + if layer in self.tools: + if layer in tools_bounds: + tool = self.tools[layer][0] + g = copy.deepcopy(tool["self_group"]) + g.attrib["gcodetools"] = "Check tools and OP assignment" + trans = [[1, 0.3, bounds[2]], [0, 0.5, tools_bounds[layer][0]]] + g.set("transform", str(Transform(trans))) + group.insert(0, g) + + ################################################################################ + # TODO Launch browser on help tab + ################################################################################ + def tab_help(self): + self.error("Switch to another tab to run the extensions.\n" + "No changes are made if the preferences or help tabs are active.\n\n" + "Tutorials, manuals and support can be found at\n" + " English support forum:\n" + " http://www.cnc-club.ru/gcodetools\n" + "and Russian support forum:\n" + " http://www.cnc-club.ru/gcodetoolsru") + return + + def tab_about(self): + return self.tab_help() + + def tab_preferences(self): + return self.tab_help() + + def tab_options(self): + return self.tab_help() + + + ################################################################################ + # Lathe + ################################################################################ + def generate_lathe_gcode(self, subpath, layer, feed_type): + if len(subpath) < 2: + return "" + feed = " F {:f}".format(self.tool[feed_type]) + x = self.options.lathe_x_axis_remap + z = self.options.lathe_z_axis_remap + flip_angle = -1 if x.lower() + z.lower() in ["xz", "yx", "zy"] else 1 + alias = {"X": "I", "Y": "J", "Z": "K", "x": "i", "y": "j", "z": "k"} + i_ = alias[x] + k_ = alias[z] + c = [[subpath[0][1], "move", 0, 0, 0]] + for sp1, sp2 in zip(subpath, subpath[1:]): + c += biarc(sp1, sp2, 0, 0) + for i in range(1, len(c)): # Just in case check end point of each segment + c[i - 1][4] = c[i][0][:] + c += [[subpath[-1][1], "end", 0, 0, 0]] + self.draw_curve(c, layer, style=MARKER_STYLE["biarc_style_lathe_{}".format(feed_type)]) + + gcode = ("G01 {} {:f} {} {:f}".format(x, c[0][4][0], z, c[0][4][1])) + feed + "\n" # Just in case move to the start... + for s in c: + if s[1] == 'line': + gcode += ("G01 {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1])) + feed + "\n" + elif s[1] == 'arc': + r = [(s[2][0] - s[0][0]), (s[2][1] - s[0][1])] + if (r[0] ** 2 + r[1] ** 2) > self.options.min_arc_radius ** 2: + r1 = (P(s[0]) - P(s[2])) + r2 = (P(s[4]) - P(s[2])) + if abs(r1.mag() - r2.mag()) < 0.001: + gcode += ("G02" if s[3] * flip_angle < 0 else "G03") + (" {} {:f} {} {:f} {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1], i_, (s[2][0] - s[0][0]), k_, (s[2][1] - s[0][1]))) + feed + "\n" + else: + r = (r1.mag() + r2.mag()) / 2 + gcode += ("G02" if s[3] * flip_angle < 0 else "G03") + (" {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1])) + " R{:f}".format(r) + feed + "\n" + return gcode + + def tab_lathe(self): + self.get_info_plus() + if not self.check_dir(): + return + x = self.options.lathe_x_axis_remap + z = self.options.lathe_z_axis_remap + x = re.sub("^\\s*([XYZxyz])\\s*$", r"\1", x) + z = re.sub("^\\s*([XYZxyz])\\s*$", r"\1", z) + if x not in ["X", "Y", "Z", "x", "y", "z"] or z not in ["X", "Y", "Z", "x", "y", "z"]: + self.error("Lathe X and Z axis remap should be 'X', 'Y' or 'Z'. Exiting...") + return + if x.lower() == z.lower(): + self.error("Lathe X and Z axis remap should be the same. Exiting...") + return + if x.lower() + z.lower() in ["xy", "yx"]: + gcode_plane_selection = "G17 (Using XY plane)\n" + if x.lower() + z.lower() in ["xz", "zx"]: + gcode_plane_selection = "G18 (Using XZ plane)\n" + if x.lower() + z.lower() in ["zy", "yz"]: + gcode_plane_selection = "G19 (Using YZ plane)\n" + self.options.lathe_x_axis_remap = x + self.options.lathe_z_axis_remap = z + + paths = self.selected_paths + self.tool = [] + gcode = "" + for layer in self.layers: + if layer in paths: + self.set_tool(layer) + if self.tool != self.tools[layer][0]: + self.tool = self.tools[layer][0] + self.tool["passing feed"] = float(self.tool["passing feed"] if "passing feed" in self.tool else self.tool["feed"]) + self.tool["feed"] = float(self.tool["feed"]) + self.tool["fine feed"] = float(self.tool["fine feed"] if "fine feed" in self.tool else self.tool["feed"]) + gcode += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", self.tool["name"]))) + self.tool["tool change gcode"] + "\n" + + for path in paths[layer]: + csp = self.transform_csp(path.path.to_superpath(), layer) + + for subpath in csp: + # Offset the path if fine cut is defined. + fine_cut = subpath[:] + if self.options.lathe_fine_cut_width > 0: + r = self.options.lathe_fine_cut_width + if self.options.lathe_create_fine_cut_using == "Move path": + subpath = [[[i2[0], i2[1] + r] for i2 in i1] for i1 in subpath] + else: + # Close the path to make offset correct + bound = csp_simple_bound([subpath]) + minx, miny, maxx, maxy = csp_true_bounds([subpath]) + offsetted_subpath = csp_subpath_line_to(subpath[:], [[subpath[-1][1][0], miny[1] - r * 10], [subpath[0][1][0], miny[1] - r * 10], [subpath[0][1][0], subpath[0][1][1]]]) + left = subpath[-1][1][0] + right = subpath[0][1][0] + if left > right: + left, right = right, left + offsetted_subpath = csp_offset([offsetted_subpath], r if not csp_subpath_ccw(offsetted_subpath) else -r) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [left, 10], [left, 0]) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [right, 0], [right, 10]) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [0, miny[1] - r], [10, miny[1] - r]) + # Join offsetted_subpath together + # Hope there won't be any circles + subpath = csp_join_subpaths(offsetted_subpath)[0] + + # Create solid object from path and lathe_width + bound = csp_simple_bound([subpath]) + top_start = [subpath[0][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width] + top_end = [subpath[-1][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width] + + gcode += ("G01 {} {:f} F {:f} \n".format(z, top_start[1], self.tool["passing feed"])) + gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"])) + + subpath = csp_concat_subpaths(csp_subpath_line_to([], [top_start, subpath[0][1]]), subpath) + subpath = csp_subpath_line_to(subpath, [top_end, top_start]) + + width = max(0, self.options.lathe_width - max(0, bound[1])) + step = self.tool['depth step'] + steps = int(math.ceil(width / step)) + for i in range(steps + 1): + current_width = self.options.lathe_width - step * i + intersections = [] + for j in range(1, len(subpath)): + sp1 = subpath[j - 1] + sp2 = subpath[j] + intersections += [[j, k] for k in csp_line_intersection([bound[0] - 10, current_width], [bound[2] + 10, current_width], sp1, sp2)] + intersections += [[j, k] for k in csp_line_intersection([bound[0] - 10, current_width + step], [bound[2] + 10, current_width + step], sp1, sp2)] + parts = csp_subpath_split_by_points(subpath, intersections) + for part in parts: + minx, miny, maxx, maxy = csp_true_bounds([part]) + y = (maxy[1] + miny[1]) / 2 + if y > current_width + step: + gcode += self.generate_lathe_gcode(part, layer, "passing feed") + elif current_width <= y <= current_width + step: + gcode += self.generate_lathe_gcode(part, layer, "feed") + else: + # full step cut + part = csp_subpath_line_to([], [part[0][1], part[-1][1]]) + gcode += self.generate_lathe_gcode(part, layer, "feed") + + top_start = [fine_cut[0][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width] + top_end = [fine_cut[-1][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width] + gcode += "\n(Fine cutting start)\n(Calculating fine cut using {})\n".format(self.options.lathe_create_fine_cut_using) + for i in range(int(self.options.lathe_fine_cut_count)): + width = self.options.lathe_fine_cut_width * (1 - float(i + 1) / self.options.lathe_fine_cut_count) + if width == 0: + current_pass = fine_cut + else: + if self.options.lathe_create_fine_cut_using == "Move path": + current_pass = [[[i2[0], i2[1] + width] for i2 in i1] for i1 in fine_cut] + else: + minx, miny, maxx, maxy = csp_true_bounds([fine_cut]) + offsetted_subpath = csp_subpath_line_to(fine_cut[:], [[fine_cut[-1][1][0], miny[1] - r * 10], [fine_cut[0][1][0], miny[1] - r * 10], [fine_cut[0][1][0], fine_cut[0][1][1]]]) + left = fine_cut[-1][1][0] + right = fine_cut[0][1][0] + if left > right: + left, right = right, left + offsetted_subpath = csp_offset([offsetted_subpath], width if not csp_subpath_ccw(offsetted_subpath) else -width) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [left, 10], [left, 0]) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [right, 0], [right, 10]) + offsetted_subpath = csp_clip_by_line(offsetted_subpath, [0, miny[1] - r], [10, miny[1] - r]) + current_pass = csp_join_subpaths(offsetted_subpath)[0] + + gcode += "\n(Fine cut {:d}-th cicle start)\n".format(i + 1) + gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"])) + gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, current_pass[0][1][0], z, current_pass[0][1][1] + self.options.lathe_fine_cut_width, self.tool["passing feed"])) + gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, current_pass[0][1][0], z, current_pass[0][1][1], self.tool["fine feed"])) + + gcode += self.generate_lathe_gcode(current_pass, layer, "fine feed") + gcode += ("G01 {} {:f} F {:f} \n".format(z, top_start[1], self.tool["passing feed"])) + gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"])) + + self.export_gcode(gcode) + + ################################################################################ + # + # Lathe modify path + # Modifies path to fit current cutter. As for now straight rect cutter. + # + ################################################################################ + + def tab_lathe_modify_path(self): + self.get_info() + if self.selected_paths == {} and self.options.auto_select_paths: + paths = self.paths + self.error("No paths are selected! Trying to work on all available paths.") + else: + paths = self.selected_paths + + for layer in self.layers: + if layer in paths: + width = self.options.lathe_rectangular_cutter_width + for path in paths[layer]: + csp = self.transform_csp(path.path.to_superpath(), layer) + new_csp = [] + for subpath in csp: + orientation = subpath[-1][1][0] > subpath[0][1][0] + new_subpath = [] + + # Split segment at x' and y' == 0 + for sp1, sp2 in zip(subpath[:], subpath[1:]): + ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2) + roots = cubic_solver_real(0, 3 * ax, 2 * bx, cx) + roots += cubic_solver_real(0, 3 * ay, 2 * by, cy) + new_subpath = csp_concat_subpaths(new_subpath, csp_seg_split(sp1, sp2, roots)) + subpath = new_subpath + new_subpath = [] + first_seg = True + for sp1, sp2 in zip(subpath[:], subpath[1:]): + n = csp_normalized_normal(sp1, sp2, 0) + a = math.atan2(n[0], n[1]) + if a == 0 or a == math.pi: + n = csp_normalized_normal(sp1, sp2, 1) + a = math.atan2(n[0], n[1]) + if a != 0 and a != math.pi: + o = 0 if 0 < a <= math.pi / 2 or -math.pi < a < -math.pi / 2 else 1 + if not orientation: + o = 1 - o + + # Add first horizontal straight line if needed + if not first_seg and new_subpath == []: + new_subpath = [[[subpath[0][i][0] - width * o, subpath[0][i][1]] for i in range(3)]] + + new_subpath = csp_concat_subpaths( + new_subpath, + [ + [[sp1[i][0] - width * o, sp1[i][1]] for i in range(3)], + [[sp2[i][0] - width * o, sp2[i][1]] for i in range(3)] + ] + ) + first_seg = False + + # Add last horizontal straight line if needed + if a == 0 or a == math.pi: + new_subpath += [[[subpath[-1][i][0] - width * o, subpath[-1][i][1]] for i in range(3)]] + + new_csp += [new_subpath] + self.draw_csp(new_csp, layer) + + ################################################################################ + # Graffiti function generates Gcode for graffiti drawer + ################################################################################ + def tab_graffiti(self): + self.get_info_plus() + # Get reference points. + + def get_gcode_coordinates(point, layer): + gcode = '' + pos = [] + for ref_point in self.graffiti_reference_points[layer]: + c = math.sqrt((point[0] - ref_point[0][0]) ** 2 + (point[1] - ref_point[0][1]) ** 2) + gcode += " {} {:f}".format(ref_point[1], c) + pos += [c] + return pos, gcode + + def graffiti_preview_draw_point(x1, y1, color, radius=.5): + self.graffiti_preview = self.graffiti_preview + r, g, b, a_ = color + for x in range(int(x1 - 1 - math.ceil(radius)), int(x1 + 1 + math.ceil(radius) + 1)): + for y in range(int(y1 - 1 - math.ceil(radius)), int(y1 + 1 + math.ceil(radius) + 1)): + if x >= 0 and y >= 0 and y < len(self.graffiti_preview) and x * 4 < len(self.graffiti_preview[0]): + d = math.sqrt((x1 - x) ** 2 + (y1 - y) ** 2) + a = float(a_) * (max(0, (1 - (d - radius))) if d > radius else 1) / 256 + self.graffiti_preview[y][x * 4] = int(r * a + (1 - a) * self.graffiti_preview[y][x * 4]) + self.graffiti_preview[y][x * 4 + 1] = int(g * a + (1 - a) * self.graffiti_preview[y][x * 4 + 1]) + self.graffiti_preview[y][x * 4 + 2] = int(g * b + (1 - a) * self.graffiti_preview[y][x * 4 + 2]) + self.graffiti_preview[y][x * 4 + 3] = min(255, int(self.graffiti_preview[y][x * 4 + 3] + a * 256)) + + def graffiti_preview_transform(x, y): + tr = self.graffiti_preview_transform + d = max(tr[2] - tr[0] + 2, tr[3] - tr[1] + 2) + return [(x - tr[0] + 1) * self.options.graffiti_preview_size / d, self.options.graffiti_preview_size - (y - tr[1] + 1) * self.options.graffiti_preview_size / d] + + def draw_graffiti_segment(layer, start, end, feed, color=(0, 255, 0, 40), emmit=1000): + # Emit = dots per second + l = math.sqrt(sum([(start[i] - end[i]) ** 2 for i in range(len(start))])) + time_ = l / feed + c1 = self.graffiti_reference_points[layer][0][0] + c2 = self.graffiti_reference_points[layer][1][0] + d = math.sqrt((c1[0] - c2[0]) ** 2 + (c1[1] - c2[1]) ** 2) + if d == 0: + raise ValueError("Error! Reference points should not be the same!") + for i in range(int(time_ * emmit + 1)): + t = i / (time_ * emmit) + r1 = start[0] * (1 - t) + end[0] * t + r2 = start[1] * (1 - t) + end[1] * t + a = (r1 ** 2 - r2 ** 2 + d ** 2) / (2 * d) + h = math.sqrt(r1 ** 2 - a ** 2) + xa = c1[0] + a * (c2[0] - c1[0]) / d + ya = c1[1] + a * (c2[1] - c1[1]) / d + + x1 = xa + h * (c2[1] - c1[1]) / d + x2 = xa - h * (c2[1] - c1[1]) / d + y1 = ya - h * (c2[0] - c1[0]) / d + y2 = ya + h * (c2[0] - c1[0]) / d + + x = x1 if y1 < y2 else x2 + y = min(y1, y2) + x, y = graffiti_preview_transform(x, y) + graffiti_preview_draw_point(x, y, color) + + def create_connector(p1, p2, t1, t2): + P1 = P(p1) + P2 = P(p2) + N1 = P(rotate_ccw(t1)) + N2 = P(rotate_ccw(t2)) + r = self.options.graffiti_min_radius + C1 = P1 + N1 * r + C2 = P2 + N2 * r + # Get closest possible centers of arcs, also we define that arcs are both ccw or both not. + dc, N1, N2, m = ( + ( + (((P2 - N1 * r) - (P1 - N2 * r)).l2(), -N1, -N2, 1) + if vectors_ccw(t1, t2) else + (((P2 + N1 * r) - (P1 + N2 * r)).l2(), N1, N2, -1) + ) + if vectors_ccw((P1 - C1).to_list(), t1) == vectors_ccw((P2 - C2).to_list(), t2) else + ( + (((P2 + N1 * r) - (P1 - N2 * r)).l2(), N1, -N2, 1) + if vectors_ccw(t1, t2) else + (((P2 - N1 * r) - (P1 + N2 * r)).l2(), -N1, N2, 1) + ) + ) + dc = math.sqrt(dc) + C1 = P1 + N1 * r + C2 = P2 + N2 * r + Dc = C2 - C1 + + if dc == 0: + # can be joined by one arc + return csp_from_arc(p1, p2, C1.to_list(), r, t1) + + cos = Dc.x / dc + sin = Dc.y / dc + + p1_end = [C1.x - r * sin * m, C1.y + r * cos * m] + p2_st = [C2.x - r * sin * m, C2.y + r * cos * m] + if point_to_point_d2(p1, p1_end) < 0.0001 and point_to_point_d2(p2, p2_st) < 0.0001: + return [[p1, p1, p1], [p2, p2, p2]] + + arc1 = csp_from_arc(p1, p1_end, C1.to_list(), r, t1) + arc2 = csp_from_arc(p2_st, p2, C2.to_list(), r, [cos, sin]) + return csp_concat_subpaths(arc1, arc2) + + if not self.check_dir(): + return + if self.selected_paths == {} and self.options.auto_select_paths: + paths = self.paths + self.error("No paths are selected! Trying to work on all available paths.") + else: + paths = self.selected_paths + self.tool = [] + gcode = """(Header) +(Generated by gcodetools from Inkscape.) +(Using graffiti extension.) +(Header end.)""" + + minx = float("inf") + miny = float("inf") + maxx = float("-inf") + maxy = float("-inf") + # Get all reference points and path's bounds to make preview + + for layer in self.layers: + if layer in paths: + # Set reference points + if layer not in self.graffiti_reference_points: + reference_points = None + for i in range(self.layers.index(layer), -1, -1): + if self.layers[i] in self.graffiti_reference_points: + reference_points = self.graffiti_reference_points[self.layers[i]] + self.graffiti_reference_points[layer] = self.graffiti_reference_points[self.layers[i]] + break + if reference_points is None: + self.error('There are no graffiti reference points for layer {}'.format(layer), "error") + + # Transform reference points + for i in range(len(self.graffiti_reference_points[layer])): + self.graffiti_reference_points[layer][i][0] = self.transform(self.graffiti_reference_points[layer][i][0], layer) + point = self.graffiti_reference_points[layer][i] + gcode += "(Reference point {:f};{:f} for {} axis)\n".format(point[0][0], point[0][1], point[1]) + + if self.options.graffiti_create_preview: + for point in self.graffiti_reference_points[layer]: + minx = min(minx, point[0][0]) + miny = min(miny, point[0][1]) + maxx = max(maxx, point[0][0]) + maxy = max(maxy, point[0][1]) + for path in paths[layer]: + csp = path.path.to_superpath() + csp = self.apply_transforms(path, csp) + csp = self.transform_csp(csp, layer) + bounds = csp_simple_bound(csp) + minx = min(minx, bounds[0]) + miny = min(miny, bounds[1]) + maxx = max(maxx, bounds[2]) + maxy = max(maxy, bounds[3]) + + if self.options.graffiti_create_preview: + self.graffiti_preview = list([[255] * (4 * self.options.graffiti_preview_size) for _ in range(self.options.graffiti_preview_size)]) + self.graffiti_preview_transform = [minx, miny, maxx, maxy] + + for layer in self.layers: + if layer in paths: + + r = re.match("\\s*\\(\\s*([0-9\\-,.]+)\\s*;\\s*([0-9\\-,.]+)\\s*\\)\\s*", self.options.graffiti_start_pos) + if r: + start_point = [float(r.group(1)), float(r.group(2))] + else: + start_point = [0., 0.] + last_sp1 = [[start_point[0], start_point[1] - 10] for _ in range(3)] + last_sp2 = [start_point for _ in range(3)] + + self.set_tool(layer) + self.tool = self.tools[layer][0] + # Change tool every layer. (Probably layer = color so it'll be + # better to change it even if the tool has not been changed) + gcode += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", self.tool["name"]))) + self.tool["tool change gcode"] + "\n" + + subpaths = [] + for path in paths[layer]: + # Rebuild the paths to polyline. + csp = path.path.to_superpath() + csp = self.apply_transforms(path, csp) + csp = self.transform_csp(csp, layer) + subpaths += csp + polylines = [] + while len(subpaths) > 0: + i = min([(point_to_point_d2(last_sp2[1], subpaths[i][0][1]), i) for i in range(len(subpaths))])[1] + subpath = subpaths[i][:] + del subpaths[i] + polylines += [ + ['connector', create_connector( + last_sp2[1], + subpath[0][1], + csp_normalized_slope(last_sp1, last_sp2, 1.), + csp_normalized_slope(subpath[0], subpath[1], 0.), + )] + ] + polyline = [] + spl = None + + # remove zerro length segments + i = 0 + while i < len(subpath) - 1: + if cspseglength(subpath[i], subpath[i + 1]) < 0.00000001: + subpath[i][2] = subpath[i + 1][2] + del subpath[i + 1] + else: + i += 1 + + for sp1, sp2 in zip(subpath, subpath[1:]): + if spl is not None and abs(cross(csp_normalized_slope(spl, sp1, 1.), csp_normalized_slope(sp1, sp2, 0.))) > 0.1: # TODO add coefficient into inx + # We've got sharp angle at sp1. + polyline += [sp1] + polylines += [['draw', polyline[:]]] + polylines += [ + ['connector', create_connector( + sp1[1], + sp1[1], + csp_normalized_slope(spl, sp1, 1.), + csp_normalized_slope(sp1, sp2, 0.), + )] + ] + polyline = [] + # max_segment_length + polyline += [sp1] + print_(polyline) + print_(sp1) + + spl = sp1 + polyline += [sp2] + polylines += [['draw', polyline[:]]] + + last_sp1 = sp1 + last_sp2 = sp2 + + # Add return to start_point + if not polylines: + continue + polylines += [["connect1", [[polylines[-1][1][-1][1] for _ in range(3)], [start_point for _ in range(3)]]]] + + # Make polylines from polylines. They are still csp. + for i in range(len(polylines)): + polyline = [] + l = 0 + print_("polylines", polylines) + print_(polylines[i]) + for sp1, sp2 in zip(polylines[i][1], polylines[i][1][1:]): + print_(sp1, sp2) + l = cspseglength(sp1, sp2) + if l > 0.00000001: + polyline += [sp1[1]] + parts = int(math.ceil(l / self.options.graffiti_max_seg_length)) + for j in range(1, parts): + polyline += [csp_at_length(sp1, sp2, float(j) / parts)] + if l > 0.00000001: + polyline += [sp2[1]] + print_(i) + polylines[i][1] = polyline + + t = 0 + last_state = None + for polyline_ in polylines: + polyline = polyline_[1] + # Draw linearization + if self.options.graffiti_create_linearization_preview: + t += 1 + csp = [[polyline[i], polyline[i], polyline[i]] for i in range(len(polyline))] + draw_csp(self.transform_csp([csp], layer, reverse=True)) + + # Export polyline to gcode + # we are making transform from XYZA coordinates to R1...Rn + # where R1...Rn are radius vectors from graffiti reference points + # to current (x,y) point. Also we need to assign custom feed rate + # for each segment. And we'll use only G01 gcode. + last_real_pos, g = get_gcode_coordinates(polyline[0], layer) + last_pos = polyline[0] + if polyline_[0] == "draw" and last_state != "draw": + gcode += self.tool['gcode before path'] + "\n" + for point in polyline: + real_pos, g = get_gcode_coordinates(point, layer) + real_l = sum([(real_pos[i] - last_real_pos[i]) ** 2 for i in range(len(last_real_pos))]) + l = (last_pos[0] - point[0]) ** 2 + (last_pos[1] - point[1]) ** 2 + if l != 0: + feed = self.tool['feed'] * math.sqrt(real_l / l) + gcode += "G01 " + g + " F {:f}\n".format(feed) + if self.options.graffiti_create_preview: + draw_graffiti_segment(layer, real_pos, last_real_pos, feed, color=(0, 0, 255, 200) if polyline_[0] == "draw" else (255, 0, 0, 200), emmit=self.options.graffiti_preview_emmit) + last_real_pos = real_pos + last_pos = point[:] + if polyline_[0] == "draw" and last_state != "draw": + gcode += self.tool['gcode after path'] + "\n" + last_state = polyline_[0] + self.export_gcode(gcode, no_headers=True) + if self.options.graffiti_create_preview: + try: + # Draw reference points + for layer in self.graffiti_reference_points: + for point in self.graffiti_reference_points[layer]: + x, y = graffiti_preview_transform(point[0][0], point[0][1]) + graffiti_preview_draw_point(x, y, (0, 255, 0, 255), radius=5) + + import png + writer = png.Writer(width=self.options.graffiti_preview_size, height=self.options.graffiti_preview_size, size=None, greyscale=False, alpha=True, bitdepth=8, palette=None, transparent=None, background=None, gamma=None, compression=None, interlace=False, bytes_per_sample=None, planes=None, colormap=None, maxval=None, chunk_limit=1048576) + with open(os.path.join(self.options.directory, self.options.file + ".png"), 'wb') as f: + writer.write(f, self.graffiti_preview) + + except: + self.error("Png module have not been found!") + + def get_info_plus(self): + """Like get_info(), but checks some of the values""" + self.get_info() + if self.orientation_points == {}: + self.error("Orientation points have not been defined! A default set of orientation points has been automatically added.") + self.tab_orientation(self.layers[min(1, len(self.layers) - 1)]) + self.get_info() + if self.tools == {}: + self.error("Cutting tool has not been defined! A default tool has been automatically added.") + self.options.tools_library_type = "default" + self.tab_tools_library(self.layers[min(1, len(self.layers) - 1)]) + self.get_info() + + ################################################################################ + # + # Effect + # + # Main function of Gcodetools class + # + ################################################################################ + def effect(self): + start_time = time.time() + global options + options = self.options + options.self = self + options.doc_root = self.document.getroot() + + # define print_ function + global print_ + if self.options.log_create_log: + try: + if os.path.isfile(self.options.log_filename): + os.remove(self.options.log_filename) + with open(self.options.log_filename, "a") as fhl: + fhl.write("""Gcodetools log file. +Started at {}. +{} +""".format(time.strftime("%d.%m.%Y %H:%M:%S"), options.log_filename)) + except: + print_ = lambda *x: None + else: + print_ = lambda *x: None + + # This automatically calls any `tab_{tab_name_in_inx}` which in this + # extension is A LOT of different functions. So see all method prefixed + # with tab_ to find out what's supported here. + self.options.active_tab() + + print_("------------------------------------------") + print_("Done in {:f} seconds".format(time.time() - start_time)) + print_("End at {}.".format(time.strftime("%d.%m.%Y %H:%M:%S"))) + + + def tab_offset(self): + self.get_info() + if self.options.offset_just_get_distance: + for layer in self.selected_paths: + if len(self.selected_paths[layer]) == 2: + csp1 = self.selected_paths[layer][0].path.to_superpath() + csp2 = self.selected_paths[layer][1].path.to_superpath() + dist = csp_to_csp_distance(csp1, csp2) + print_(dist) + draw_pointer(list(csp_at_t(csp1[dist[1]][dist[2] - 1], csp1[dist[1]][dist[2]], dist[3])) + + list(csp_at_t(csp2[dist[4]][dist[5] - 1], csp2[dist[4]][dist[5]], dist[6])), "red", "line", comment=math.sqrt(dist[0])) + return + if self.options.offset_step == 0: + self.options.offset_step = self.options.offset_radius + if self.options.offset_step * self.options.offset_radius < 0: + self.options.offset_step *= -1 + time_ = time.time() + offsets_count = 0 + for layer in self.selected_paths: + for path in self.selected_paths[layer]: + + offset = self.options.offset_step / 2 + while abs(offset) <= abs(self.options.offset_radius): + offset_ = csp_offset(path.path.to_superpath(), offset) + offsets_count += 1 + if offset_: + for iii in offset_: + draw_csp([iii], width=1) + else: + print_("------------Reached empty offset at radius {}".format(offset)) + break + offset += self.options.offset_step + print_() + print_("-----------------------------------------------------------------------------------") + print_("-----------------------------------------------------------------------------------") + print_("-----------------------------------------------------------------------------------") + print_() + print_("Done in {}".format(time.time() - time_)) + print_("Total offsets count {}".format(offsets_count)) + + +if __name__ == '__main__': + Gcodetools().run() diff --git a/share/extensions/other/gcodetools/gcodetools_about.inx b/share/extensions/other/gcodetools/gcodetools_about.inx new file mode 100644 index 0000000..72f2b99 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_about.inx @@ -0,0 +1,52 @@ + + + + About + ru.cnc-club.filter.gcodetools_about_no_options_no_preferences + + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_area.inx b/share/extensions/other/gcodetools/gcodetools_area.inx new file mode 100644 index 0000000..6a500e2 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_area.inx @@ -0,0 +1,133 @@ + + + + Area + ru.cnc-club.filter.gcodetools_area_area_fill_area_artefacts_ptg + + + + 100 + -10 + 0 + + + + + + 0 + 0 + 0 + + + + + + + + 5.0 + + + + + + + + + + 1 + 4 + + + + + + + d + true + + + + + + 1 + 0.0 + true + 0.05 + + false + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_dxf_points.inx b/share/extensions/other/gcodetools/gcodetools_dxf_points.inx new file mode 100644 index 0000000..8cd782a --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_dxf_points.inx @@ -0,0 +1,79 @@ + + + + DXF Points + ru.cnc-club.filter.gcodetools_dxfpoints_no_options + + + + + + + + + + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_engraving.inx b/share/extensions/other/gcodetools/gcodetools_engraving.inx new file mode 100644 index 0000000..daf2d4a --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_engraving.inx @@ -0,0 +1,91 @@ + + + + Engraving + ru.cnc-club.filter.gcodetools_engraving + + + + 175 + 10 + 4 + false + + + + + + 1 + 0.0 + true + 0.05 + + false + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_graffiti.inx b/share/extensions/other/gcodetools/gcodetools_graffiti.inx new file mode 100644 index 0000000..ea428b7 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_graffiti.inx @@ -0,0 +1,120 @@ + + + + Graffiti + ru.cnc-club.filter.gcodetools_graffiti_orientation + + + + 10 + 10 + (0.0;0.0) + true + true + 800 + 1000 + + + + + + + + + + + + 0 + -1 + + + + + + + + + + 1 + 0.0 + true + 0.05 + + false + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_lathe.inx b/share/extensions/other/gcodetools/gcodetools_lathe.inx new file mode 100644 index 0000000..ac486bb --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_lathe.inx @@ -0,0 +1,113 @@ + + + + Lathe + ru.cnc-club.filter.gcodetools_lathe_lathe_modify_path_ptg + + + + 10 + 1 + 1 + + + + + X + Z + + + + + 4 + + + + + 1 + 4 + + + + + + + d + true + + + + + + 1 + 0.0 + true + 0.05 + + false + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_orientation_points.inx b/share/extensions/other/gcodetools/gcodetools_orientation_points.inx new file mode 100644 index 0000000..41aeeb6 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_orientation_points.inx @@ -0,0 +1,57 @@ + + + + Orientation points + ru.cnc-club.filter.gcodetools_orientation_no_options_no_preferences + + + + + + + + + + 0 + -1 + + + + + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx b/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx new file mode 100644 index 0000000..9c6365c --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx @@ -0,0 +1,93 @@ + + + + Path to Gcode + ru.cnc-club.filter.gcodetools_ptg + + + + 1 + 4 + + + + + + + d + true + + + + + + 1 + 0.0 + true + 0.05 + + false + + + + + output.ngc + true + + /home + + 5 + + + + + + + + + + + + + + + false + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx b/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx new file mode 100644 index 0000000..53e6035 --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx @@ -0,0 +1,59 @@ + + + + Prepare path for plasma + ru.cnc-club.filter.gcodetools_plasma-prepare-path_no_options_no_preferences + + + + true + 10 + 10 + + + + + + 10 + false + false + + + true + 10 + 140 + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/gcodetools_tools_library.inx b/share/extensions/other/gcodetools/gcodetools_tools_library.inx new file mode 100644 index 0000000..ca78a0c --- /dev/null +++ b/share/extensions/other/gcodetools/gcodetools_tools_library.inx @@ -0,0 +1,62 @@ + + + + Tools library + ru.cnc-club.filter.gcodetools_tools_library_no_options_no_preferences + + + + + + + + + + + + + + + + + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/other/gcodetools/genpofiles.sh b/share/extensions/other/gcodetools/genpofiles.sh new file mode 100755 index 0000000..5106c52 --- /dev/null +++ b/share/extensions/other/gcodetools/genpofiles.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +OLDPATH=`pwd` + +cd ../.. +find share/extensions -name "*.inx" | sort | xargs -n 1 printf "[type: gettext/xml] %s\n" +cd ${OLDPATH} diff --git a/share/extensions/other/gcodetools/setup.cfg b/share/extensions/other/gcodetools/setup.cfg new file mode 100644 index 0000000..b7e4789 --- /dev/null +++ b/share/extensions/other/gcodetools/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out new file mode 100644 index 0000000..61a62cc --- /dev/null +++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + (0.0; 0.0; 0.00000)(100.0; 0.0; -0.00000)(0.0; 100.0; 0.0) + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out new file mode 100644 index 0000000..e2ae9a3 --- /dev/null +++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out @@ -0,0 +1,30 @@ +% +(Header) +(Generated by gcodetools from Inkscape.) +(Using default header. To add your own header create file "header" in the output dir.) +M3 +(Header end.) +G21 (All units in mm) + +(Start cutting path id: p1) +(Change tool to Default tool) + +G00 Z5.000000 +G00 X100.000000 Y400.000000 + +G01 Z-0.125000 F100.0(Penetrate) +G01 X200.000000 Y300.000000 Z-0.125000 F400.000000 +G01 X300.000000 Y400.000000 Z-0.125000 +G01 X400.000000 Y300.000000 Z-0.125000 +G00 Z5.000000 + +(End cutting path id: p1) + + +(Footer) +M5 +G00 X0.0000 Y0.0000 +M2 +(Using default footer. To add your own footer create file "footer" in the output dir.) +(end) +% \ No newline at end of file diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out new file mode 100644 index 0000000..8694e43 --- /dev/null +++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out @@ -0,0 +1,40 @@ +% +(Header) +(Generated by gcodetools from Inkscape.) +(Using default header. To add your own header create file "header" in the output dir.) +M3 +(Header end.) +G21 (All units in mm) +(Change tool to Default tool) + +G01 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 401.000000 F 800.000000 +G01 X 200.000000 Z 301.000000 F 800.000000 +G01 X 300.000000 Z 401.000000 F 800.000000 +G01 X 400.000000 Z 301.000000 F 800.000000 +G01 X 400.000000 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 16.000000 F 800.000000 + +(Fine cutting start) +(Calculating fine cut using Move path) + +(Fine cut 1-th cicle start) +G01 X 100.000000 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 401.000000 F 800.000000 +G01 X 100.000000 Z 400.000000 F 800.000000 +G01 X 100.000000 Z 400.000000 F 800.000000 +G01 X 200.000000 Z 300.000000 F 800.000000 +G01 X 300.000000 Z 400.000000 F 800.000000 +G01 X 400.000000 Z 300.000000 F 800.000000 +G01 Z 16.000000 F 800.000000 +G01 X 100.000000 Z 16.000000 F 800.000000 + +(Footer) +M5 +G00 X0.0000 Y0.0000 +M2 +(Using default footer. To add your own footer create file "footer" in the output dir.) +(end) +% \ No newline at end of file diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg b/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg new file mode 100644 index 0000000..259e13c --- /dev/null +++ b/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg @@ -0,0 +1,37 @@ + + + + + + + + + image/svg+xml + + + + + + diff --git a/share/extensions/other/gcodetools/tests/data/svg/shapes.svg b/share/extensions/other/gcodetools/tests/data/svg/shapes.svg new file mode 100644 index 0000000..eb9caed --- /dev/null +++ b/share/extensions/other/gcodetools/tests/data/svg/shapes.svg @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/other/gcodetools/tests/dev_requirements.txt b/share/extensions/other/gcodetools/tests/dev_requirements.txt new file mode 100644 index 0000000..0e358d9 --- /dev/null +++ b/share/extensions/other/gcodetools/tests/dev_requirements.txt @@ -0,0 +1,11 @@ +# Dev Requirements +pytest +pytest-cov + +# Code requirements +typing +lxml +numpy +scour +pyserial +cssselect \ No newline at end of file diff --git a/share/extensions/other/gcodetools/tests/test_gcodetools.py b/share/extensions/other/gcodetools/tests/test_gcodetools.py new file mode 100644 index 0000000..0575729 --- /dev/null +++ b/share/extensions/other/gcodetools/tests/test_gcodetools.py @@ -0,0 +1,65 @@ +# coding=utf-8 + +import sys +import os + +from gcodetools import Gcodetools +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentBytes + +SETTINGS = ( + '--id=p1', '--max-area-curves=100', + '--area-inkscape-radius=-10', '--area-tool-overlap=0', + '--area-fill-angle=0', '--area-fill-shift=0', '--area-fill-method=0', + '--area-fill-method=0', '--area-find-artefacts-diameter=5', + '--area-find-artefacts-action=mark with an arrow', + '--biarc-tolerance=1', '--biarc-max-split-depth=4', + '--path-to-gcode-order=subpath by subpath', + '--path-to-gcode-depth-function=d', + '--path-to-gcode-sort-paths=false', '--Zscale=1', '--Zoffset=0', + '--auto_select_paths=true', '--min-arc-radius=0.05000000074505806', + '--comment-gcode-from-properties=false', '--create-log=false', + '--add-numeric-suffix-to-filename=false', '--Zsafe=5', + '--unit=G21 (All units in mm)', '--postprocessor= ', +) +FILESET = SETTINGS + ('--directory=/home', '--filename=output.ngc',) + +class TestGcodetoolsBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + stderr_protect = False + effect_class = Gcodetools + comparisons = [ + FILESET + ('--active-tab="area_fill"',), + FILESET + ('--active-tab="area"',), + FILESET + ('--active-tab="area_artefacts"',), + FILESET + ('--active-tab="dxfpoints"',), + FILESET + ('--active-tab="orientation"',), + FILESET + ('--active-tab="tools_library"',), + FILESET + ('--active-tab="lathe_modify_path"',), + FILESET + ('--active-tab="offset"',), + FILESET + ('--active-tab="plasma-prepare-path"',), + ] + compare_filters = [CompareOrderIndependentBytes()] + compare_file_extension = 'dxf' + + def test_all_comparisons(self): + """ + gcodetools tries to write to a folder and filename specified + on the command line, this needs to be handled carefully. + """ + for tab in ( + ('--active-tab="path-to-gcode"',), + #('--active-tab="engraving"',), + #('--active-tab="graffiti"',), + ('--active-tab="lathe"',), + ): + args = SETTINGS + tab + ( + '--directory={}'.format(self.tempdir), + '--filename=output.ngc', + ) + outfile = os.path.join(self.tempdir, 'output.ngc') + self.assertCompare(self.compare_file, None, args, 'output.ngc') + +class TestGcodeToolsOrientationScientific(ComparisonMixin, TestCase): + effect_class = Gcodetools + compare_file = "svg/shapes.svg" + comparisons = [("--active-tab=orientation", "--Zsurface=0.00000000000001e-5", "--Zdepth=-9.71445146547012e-17", "--orientation-points-count=3")] diff --git a/share/extensions/other/gcodetools/tests/test_inkex_inx.py b/share/extensions/other/gcodetools/tests/test_inkex_inx.py new file mode 100644 index 0000000..211b746 --- /dev/null +++ b/share/extensions/other/gcodetools/tests/test_inkex_inx.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test elements extra logic from svg xml lxml custom classes. +""" + +import os +from glob import glob + +from inkex.utils import PY3 +from inkex.tester import TestCase +from inkex.tester.inx import InxMixin +from inkex.inx import InxFile + +class InxTestCase(InxMixin, TestCase): + """Test INX files""" + def test_inx_effect(self): + inx = InxFile(""" + + TestOne + org.inkscape.test.inx_one + + all + + + + + + + +""") + self.assertEqual(inx.name, 'TestOne') + self.assertEqual(inx.ident, 'org.inkscape.test.inx_one') + self.assertEqual(inx.slug, 'InxOne') + self.assertEqual(inx.metadata, {'type': 'effect', 'preview': False, 'objects': 'all'}) + self.assertEqual(inx.menu, ['Banana', 'Ice Cream', 'TestOne']) + self.assertEqual(inx.warnings, []) + + def test_inx_output(self): + inx = InxFile(""" + + <_name>TestTwo + org.inkscape.test.inx_two + + .inx + text/xml+inx + Extension (*.inx) + <_filetypetooltip>The extension extension repention suspension. + true + +""") + self.assertEqual(inx.name, 'TestTwo') + self.assertEqual(inx.ident, 'org.inkscape.test.inx_two') + self.assertEqual(inx.metadata, { + 'dataloss': True, + 'extension': '.inx', + 'mimetype': 'text/xml+inx', + 'name': 'Extension (*.inx)', + 'tooltip': 'The extension extension repention suspension.', + 'type': 'output'}) + self.assertEqual(inx.warnings, [ + 'Use of old translation scheme: <_filetypetooltip...>', + 'Use of old translation scheme: <_name...>']) + + def test_inx_input(self): + inx = InxFile(""" + TestThree + org.inkscape.test.inx_three + +""") + self.assertEqual(inx.name, 'TestThree') + self.assertEqual(inx.metadata, { + 'extension': '.inx', + 'mimetype': 'text/xml+inx', + 'name': 'Extension (*.inx)', + 'tooltip': 'The extension extension repention suspension.', + 'type': 'input'}) + self.assertEqual(inx.warnings, ['No inx xml prefix.']) + + def test_inx_template(self): + inx = InxFile(""" + TestFour + org.inkscape.test.inx_four + + all + + + + Magic Number + Donky Oaty + Something might happen. + 2070-01-01 + word food strawberry + +""") + self.assertEqual(inx.name, 'TestFour') + self.assertEqual(inx.metadata, {'author': 'Donky Oaty', 'desc': 'Something might happen.', 'type': 'template'}) + self.assertEqual(inx.warnings, ['No inx xml prefix.']) + + + def test_inx_files(self): + """Get all inx files and test each of them""" + if not PY3: + self.skipTest("No INX testing in python2") + return + for inx_file in glob(os.path.join(self._testdir(), '..', '*.inx')): + self.assertInxIsGood(inx_file) diff --git a/share/extensions/other/gcodetools/tox.ini b/share/extensions/other/gcodetools/tox.ini new file mode 100644 index 0000000..a554a8b --- /dev/null +++ b/share/extensions/other/gcodetools/tox.ini @@ -0,0 +1,14 @@ +[tox] +envlist = py{36,37,38,39,310}-normal +skipsdist = True + + + +[testenv] +setenv = COVERAGE_FILE=.coverage-{env:TOX_ENV_NAME} + +commands = + pytest --cov=. --cov-report html --cov-report term {posargs} + +deps = + -rtests/dev_requirements.txt diff --git a/share/extensions/other/inkman/MANIFEST.in b/share/extensions/other/inkman/MANIFEST.in new file mode 100644 index 0000000..cffd671 --- /dev/null +++ b/share/extensions/other/inkman/MANIFEST.in @@ -0,0 +1,6 @@ +include inkman/data/*.glade +include inkman/data/*.ui +include inkman/data/pixmaps/*.svg +include inkman/data/pixmaps/*.png +include manage-extensions.inx +include manage-extensions.py diff --git a/share/extensions/other/inkman/inkman/__init__.py b/share/extensions/other/inkman/inkman/__init__.py new file mode 100644 index 0000000..04089ba --- /dev/null +++ b/share/extensions/other/inkman/inkman/__init__.py @@ -0,0 +1,5 @@ +__pkgname__ = "inkscape-extension-manager" +__version__ = "1.0" +__issues__ = "https://gitlab.com/inkscape/extras/extension-manager/-/issues" +__state__ = f"({__version__})" +__inkscape__ = ["1.2"] diff --git a/share/extensions/other/inkman/inkman/archive.py b/share/extensions/other/inkman/inkman/archive.py new file mode 100644 index 0000000..abc1758 --- /dev/null +++ b/share/extensions/other/inkman/inkman/archive.py @@ -0,0 +1,120 @@ +# +# Copyright (c) Gary Wilson Jr. and contributors. +# +# MIT License, see https://github.com/gdub/python-archive/blob/master/LICENSE.txt +# +""" +Compatability for zip and tar files, taken from upstream and stripped down +to provide list and read interface, removed PY2 support. +""" + +import os +import sys +import tarfile +import zipfile + + +class ArchiveException(Exception): + """Base exception class for all archive errors.""" + + +class UnrecognizedArchiveFormat(ArchiveException): + """Error raised when passed file is not a recognized archive format.""" + + +class Archive(object): + """ + The external API class that encapsulates an archive implementation. + """ + + def __init__(self, filename, ext=""): + """ + Arguments: + * 'file' can be a string path to a file or a file-like object. + * Optional 'ext' argument can be given to override the file-type + guess that is normally performed using the file extension of the + given 'file'. Should start with a dot, e.g. '.tar.gz'. + """ + cls = self._archive_cls(filename, ext=ext) + self._archive = cls(filename) + + def __enter__(self): + return self._archive + + def __exit__(self, exc, value, traceback): + pass + + @staticmethod + def _archive_cls(filename, ext=""): + """ + Return the proper Archive implementation class, based on the file type. + """ + cls = None + if not isinstance(filename, str): + try: + filename = filename.name + except AttributeError: + raise UnrecognizedArchiveFormat( + "File object not a recognized archive format." + ) + lookup_filename = filename + ext + base, tail_ext = os.path.splitext(lookup_filename.lower()) + cls = extension_map.get(tail_ext) + if not cls: + base, ext = os.path.splitext(base) + cls = extension_map.get(ext) + if not cls: + raise UnrecognizedArchiveFormat( + "Path not a recognized archive format: %s" % filename + ) + return cls + + +class BaseArchive(object): + def __del__(self): + if hasattr(self, "_archive"): + self._archive.close() + + def list(self): + raise NotImplementedError() + + def filenames(self): + raise NotImplementedError() + + +class TarArchive(BaseArchive): + def __init__(self, filename): + # tarfile's open uses different parameters for file path vs. file obj. + if isinstance(filename, str): + self._archive = tarfile.open(name=filename) + else: + self._archive = tarfile.open(fileobj=filename) + + def filenames(self): + return self._archive.getnames() + + def read(self, name): + return self._archive.extractfile(name).read() + + +class ZipArchive(BaseArchive): + def __init__(self, file): + # ZipFile's 'file' parameter can be path (string) or file-like obj. + self._archive = zipfile.ZipFile(file) + + def filenames(self): + return self._archive.namelist() + + def read(self, name): + return self._archive.read(name) + + +extension_map = { + ".egg": ZipArchive, + ".zip": ZipArchive, + ".tar": TarArchive, + ".tar.bz2": TarArchive, + ".tar.gz": TarArchive, + ".tgz": TarArchive, + ".tz2": TarArchive, +} diff --git a/share/extensions/other/inkman/inkman/backfoot.py b/share/extensions/other/inkman/inkman/backfoot.py new file mode 100644 index 0000000..42a7e69 --- /dev/null +++ b/share/extensions/other/inkman/inkman/backfoot.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2021 Martin Owens +# +# 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 3 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, see +# +""" +When the extension manager fails, this allows us to upgrade automatically. +""" + +import os +import sys +import traceback + +# Note: All imports are being done as late as possible in this module. +# If any of the imports caused the error, then we'll still message the user. + + +def update_pip_package(package): + """ + Update the package using the pip update. + """ + from inkex.utils import get_user_directory + from inkex.command import ProgramRunError, call + + try: + pip = os.path.join(get_user_directory(), "bin", "pip") + log = call(pip, "install", "--upgrade", package).decode("utf8") + logs = [line for line in log.split("\n") if "skip" not in line] + return "\n".join(logs) + except ProgramRunError as err: + raise IOError(f"Failed to update the package {package}") + + +def attempt_to_recover(): + """ + Messages the user, provides a traceback and attepts a self-update + """ + info = sys.exc_info() + sys.stderr.write("An error occured with the extensions manager!\n") + sys.stderr.write("Trying to self-update the package... ") + sys.stderr.flush() + + from inkman import __pkgname__, __version__, __file__, __issues__ + + location = os.path.dirname(__file__) + update_log = "Not done" + + try: + update_log = update_pip_package(__pkgname__) + sys.stderr.write("Updated!\n\nPlease try and reload the program again.\n\n") + except Exception: + sys.stderr.write( + "Failed to update!\n\nPlease delete the package manually! (see location below)\n\n" + ) + + sys.stderr.write( + f""" +Please report this error +------------------------ + +Report URL: {__issues__} +Location: {location} +{__pkgname__}: {__version__} + +{update_log} +""" + ) + + traceback.print_exception(*info) + del info + sys.exit(2) diff --git a/share/extensions/other/inkman/inkman/data/__init__.py b/share/extensions/other/inkman/inkman/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/other/inkman/inkman/data/gui.ui b/share/extensions/other/inkman/inkman/data/gui.ui new file mode 100644 index 0000000..3462d25 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/gui.ui @@ -0,0 +1,736 @@ + + + + + + + + + + False + dialog + + + + + + False + vertical + 2 + + + False + end + + + gtk-close + True + True + True + True + True + + + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + + + True + False + 20 + 15 + 10 + 10 + gtk-dialog-error + 6 + + + False + True + 0 + + + + + True + False + $message + True + + + True + True + 1 + + + + + True + True + 1 + + + + + + + + application/x-bzip + application/x-bzip2 + application/zip + + + *.zip + *.tar.bz2 + *.tar.gz + + + + True + False + gtk-info + + + True + False + gtk-add + + + True + False + gtk-add + + + True + False + gtk-open + + + True + False + gtk-delete + + + True + False + gtk-save + + + False + Inkscape Extensions + center + 600 + 400 + pixmaps/icon.svg + + + + + + True + True + + + True + False + vertical + 3 + + + True + False + + + True + True + in + + + True + True + + + + + + + + True + True + 4 + 0 + + + + + True + True + 4 + 0 + + + + + True + False + 8 + + + _Uninstall Package + True + False + True + True + img_uninstall + True + True + + + + + False + True + 4 + end + 0 + + + + + Update All + True + False + True + True + img_update + True + True + + + + + False + True + 1 + + + + + True + False + + + True + True + 2 + + + + + _Details + True + False + True + True + True + True + + + + + False + True + end + 3 + + + + + False + True + 4 + 1 + + + + + True + + + + + True + False + Active Packages + + + False + + + + + True + False + vertical + + + True + False + 4 + 4 + + + True + True + edit-find-symbolic + False + False + + + + True + True + 0 + + + + + searcher + True + False + + 4 + 4 + 4 + 4 + + + False + True + 6 + end + 1 + + + + + gtk-refresh + True + True + True + True + + + + + False + True + 3 + + + + + False + True + 4 + 0 + + + + + True + False + + + Details and Comments + True + True + True + img_info + True + True + + + + + False + True + 4 + 0 + + + + + True + False + + + True + True + 1 + + + + + _Install Package + True + True + True + True + True + + + + + False + True + 4 + end + 2 + + + + + True + True + True + img_install_zip + True + + + + + False + True + 4 + end + 3 + + + + + False + True + 4 + end + 1 + + + + + True + False + error + + + False + 6 + end + + + + + + + + + + + + False + False + 0 + + + + + False + 16 + + + True + False + 10 + gtk-dialog-warning + 3 + + + False + True + 0 + + + + + True + False + <b>Online content!</b> All packages are peer-reviewed by volunteers in the Inkscape community, but this does not mean these packages are safe. <i>Only download and use extensions if you trust the author or peers and understand the risks of running this software.</i> + True + True + + + True + True + 1 + + + + + + + + False + False + 0 + + + + + + + + False + True + 2 + + + + + True + False + + + True + True + 4 + 4 + in + + + True + True + + + + + + + + True + True + 0 + + + + + False + vertical + + + True + False + 1 + pixmaps/not-found.png + + + True + True + 0 + + + + + True + False + 4 + 4 + 4 + 4 + No results found + 0 + + + + + + + True + True + 1 + + + + + True + True + 1 + + + + + True + True + 3 + + + + + 1 + True + + + + + True + False + Install Packages + + + 1 + False + + + + + True + False + vertical + + + True + False + end + pixmaps/docs.png + + + True + True + 0 + + + + + True + False + + + + + + Find out how to create and upload Extensions + True + True + False + True + start + none + https://inkscape.org/develop/extensions/ + + + False + True + 1 + + + + + True + True + 1 + + + + + 2 + True + + + + + True + False + Create Package + + + 2 + False + + + + + + + False + popup + Choose Extensions Package File + dialog + center + gui + filter-for-extensions + False + False + False + + + False + vertical + 2 + + + False + end + + + + + + + + + False + False + 0 + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/info.ui b/share/extensions/other/inkman/inkman/data/info.ui new file mode 100644 index 0000000..ace3436 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/info.ui @@ -0,0 +1,338 @@ + + + + + + + + + + False + Package Information + True + center-always + 500 + 350 + gtk-about + + + + + + True + False + vertical + + + True + False + + + True + False + 7 + 7 + True + Package Name + 0 + + + + + + + 1 + 0 + 2 + + + + + True + False + 5 + 5 + 5 + 5 + gtk-about + 6 + + + 0 + 0 + 3 + + + + + True + False + 6 + 6 + 2 + 2 + Package Description + 0 + 0 + + + + + + 1 + 1 + 2 + 2 + + + + + True + False + 4 + 8 + True + + + True + False + 2 + 6 + 2 + 2 + License: + 1 + + + + + + 0 + 1 + + + + + True + False + 2 + 6 + 2 + 2 + Author: + 1 + + + + + + 0 + 0 + + + + + True + False + 2 + 6 + 2 + 2 + Version: + 1 + + + + + + 0 + 2 + + + + + True + False + 2 + 6 + 2 + 2 + Website: + 1 + + + + + + 0 + 3 + + + + + True + False + label + 0 + + + 1 + 0 + + + + + True + False + label + 0 + + + 1 + 1 + + + + + True + False + label + 0 + + + 1 + 2 + + + + + button + True + True + False + True + True + none + 0 + https://inkscape.org + + + 1 + 3 + + + + + 0 + 3 + 3 + + + + + False + True + 0 + + + + + True + False + + + True + True + in + + + True + True + + + + + + + + True + True + 4 + 0 + + + + + True + True + 4 + 1 + + + + + True + False + 8 + + + gtk-close + True + True + True + True + True + True + + + + + False + True + 4 + end + 0 + + + + + True + False + + + True + True + 2 + + + + + False + True + 4 + 2 + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/package.json b/share/extensions/other/inkman/inkman/data/package.json new file mode 100644 index 0000000..e064c7e --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/package.json @@ -0,0 +1,20 @@ +{ + "author" : "doctormo", + "dates" : { + "created" : "2021-04-22T15:08:20", + "edited" : "2021-04-22T15:08:20" + }, + "files" : [], + "icon" : "inkman/data/pixmaps/icon.svg", + "id" : "org.inkscape.extension.inkman", + "license" : "GPLv3", + "links" : { + "file": "https://media.inkscape.org/static/extensions-manager-fallback.zip" + }, + "name" : "Inkscape Extensions Manager", + "summary" : "Manage extensions from inside another extension", + "tags" : [ + "infrastructure" + ], + "verified" : true +} diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/__init__.py b/share/extensions/other/inkman/inkman/data/pixmaps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg new file mode 100644 index 0000000..427aa3d --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/default.svg b/share/extensions/other/inkman/inkman/data/pixmaps/default.svg new file mode 100644 index 0000000..4595b57 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/default.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg new file mode 100644 index 0000000..a760f78 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg @@ -0,0 +1,71 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/docs.png b/share/extensions/other/inkman/inkman/data/pixmaps/docs.png new file mode 100644 index 0000000..4613579 Binary files /dev/null and b/share/extensions/other/inkman/inkman/data/pixmaps/docs.png differ diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg new file mode 100644 index 0000000..88531a5 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg @@ -0,0 +1,79 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg new file mode 100644 index 0000000..ec65871 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg @@ -0,0 +1,82 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png b/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png new file mode 100644 index 0000000..40d6dec Binary files /dev/null and b/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png differ diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg new file mode 100644 index 0000000..ed05621 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg @@ -0,0 +1,88 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg new file mode 100644 index 0000000..a73f3a9 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg @@ -0,0 +1,95 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg new file mode 100644 index 0000000..1b30ff0 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg @@ -0,0 +1,95 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg new file mode 100644 index 0000000..da99cd7 --- /dev/null +++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg @@ -0,0 +1,95 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/other/inkman/inkman/factory.py b/share/extensions/other/inkman/inkman/factory.py new file mode 100644 index 0000000..51aa77a --- /dev/null +++ b/share/extensions/other/inkman/inkman/factory.py @@ -0,0 +1,199 @@ +# +# Copyright 2020 Martin Owens +# +# 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 3 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, see +# +""" +Extract information from an inx file and follow all the files. +""" + +import os +import sys + +from datetime import datetime +from modulefinder import ModuleFinder +from collections import defaultdict + +from inkex.inx import InxFile + +from inkman import __pkgname__, __version__ +from inkman.utils import DATA_DIR + +MODULES = ( + ( + "Depricated", + "Using depricated modules {names}", + "Critical", + ( + "bezmisc", + "cubicsuperpath", + "simplestyle", + "cspsubdiv", + "ffgeom", + "simplepath", + "simpletransform", + ), + ), + ("Unusual", "Unusual modules being used {names}", "Warning", ("argparse",)), + ("Ignored", None, None, ("os", "sys", "lxml")), +) + + +class PackageInxFile(InxFile): + def __init__(self, filename): + super().__init__(filename) + self.inx_file = filename + + def get_file_root(self): + return os.path.dirname(self.inx_file) + + def get_script(self): + """Return the file the INX points to""" + if self.script.get("location", None) in ("inx", None): + return os.path.join(self.get_file_root(), self.script["script"]) + raise IOError("Can't find script filename") + + +class IncludeFile(object): + """A file to include in the package""" + + def __init__(self, root, filepath, target=None): + self.root = root + self.filepath = filepath + self.name = os.path.basename(filepath) + self.target = target or os.path.dirname(filepath) + + def __repr__(self): + return f"" + + def file_icon(self): + """Return a filename type""" + ext = self.filepath.rsplit(".", 1)[-1] + if ext in ("inx", "py", "txt", "svg", "png"): + return ext + return "default" + + def detect_deps(self, modules=False): + if not self.filepath.endswith(".py"): + return [], [] + # We want to find all modules imported by the script directly + # So we set the location to nowhere and collect the badmodules + finder = ModuleFinder("never-land") + finder.run_script(self.filepath) + # TODO: split out local modules, system modules and genuine deps + + deps, mods = [], [] + for key, locs in finder.badmodules.items(): + if "__main__" not in locs: + continue + try: + mod_path = finder.find_module("inkman", path=sys.path)[1] + if "/python" in mod_path: + if "site-packages" in mod_path: + deps.append(key.split(".")[0]) + elif mod_path.startswith(self.root): + mods.append(mod_path) + except ImportError: + continue + return mods, deps + + +class GeneratePackage(object): + """A generated package based on data""" + + def __init__(self, inx_files, template=os.path.join(DATA_DIR, "setup.template")): + with open(template, "r") as fhl: + self._template = fhl.read() + self.files = [] + self.requires = set() + self.warnings = defaultdict(list) + self.name = "" + self.ident = "" + + for x, inx_file in enumerate(inx_files): + try: + inx = PackageInxFile(inx_file) + except Exception as err: + self.add_warning(f"Can't add file {inx_file}: {err}", 5) + continue + self._add_file(inx.get_file_root(), inx.inx_file) + self._add_file(inx.get_file_root(), inx.get_script()) + if not x: + self.name = inx.name or "" + self.ident = inx.ident.replace(".", "-") + + def _add_file(self, root, fname): + included = IncludeFile(root, fname) + self.files.append(included) + (mods, deps) = included.detect_deps() + for dep in deps: + self._add_dep(dep) + for fname in mods: + self._add_file(root, fname) + print(f"DEP: {self.requires}") + + def _add_dep(self, name): + """Try and find the package associated with this name""" + for (list_name, warning, level, mod_list) in MODULES: + if name in mod_list: + self.warnings[list_name].append(name) + return + self.requires.add(name) + + def generate_setup(self, target): + """Generates a setup.py file contents""" + args = { + "__pkgname__": __pkgname__, + "__version__": __version__, + "year": datetime.now().year, + "readme": self.generate_readme(target), + "ident": self.generate_ident(), + "version": self.generate_version(), + "description": self.widget("entry_name").get_text(), + "author": self.widget("entry_author").get_text(), + "author_email": self.widget("entry_email").get_text(), + "url": self.widget("entry_url").get_text(), + "license": self.widget("licenses").get_active_id(), + "datafiles": self.generate_datafiles(), + "requires": self.generate_requires(), + "classifiers": "", # TODO + } + return self_template.format(**args) + + def generate_ident(self): + """Generate the ident from the text entry""" + ident = self.widget("entry_ident").get_text() + ident = ident.replace(" ", "-").lower() + self.widget("entry_ident").set_text(ident) + return "inx-" + ident + + def generate_datafiles(self): + """Generate a list of datafile and their install location""" + result = "" + template = " ('{target}', ['{file}']),\n" + # 2. Loop through all the file objects in the list + # 3. Add them to the final result + return result.strip() + + def generate_requires(self): + """Generate a list of required modules""" + # TODO: Version keeping + result = "" + # 1. Loop through all the dep objects in the list + # 2. Append them to the result + return result + + +if __name__ == "__main__": + gen = GeneratePackage(sys.argv[1:]) diff --git a/share/extensions/other/inkman/inkman/gui/__init__.py b/share/extensions/other/inkman/inkman/gui/__init__.py new file mode 100644 index 0000000..042956e --- /dev/null +++ b/share/extensions/other/inkman/inkman/gui/__init__.py @@ -0,0 +1,32 @@ +# +# Copyright 2018-2022 Martin Owens +# +# 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 3 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, see +# +"""All graphical interfaces bound into a GtkApp""" + +import os + +from inkex.gui import GtkApp + +from .main import ExtensionManagerWindow +from .info import MoreInformation + + +class ManagerApp(GtkApp): + """Load the inkscape extensions glade file and attach to window""" + + ui_dir = os.path.join(os.path.dirname(__file__), "..", "data") + app_name = "inkscape-extensions-manager" + windows = [ExtensionManagerWindow, MoreInformation] diff --git a/share/extensions/other/inkman/inkman/gui/info.py b/share/extensions/other/inkman/inkman/gui/info.py new file mode 100644 index 0000000..5e17923 --- /dev/null +++ b/share/extensions/other/inkman/inkman/gui/info.py @@ -0,0 +1,105 @@ +# +# Copyright 2018-2022 Martin Owens +# +# 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 3 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, see +# +"""Information about a package""" + +import os +import sys + +from inkex.gui import ChildWindow, TreeView + + +class ExtensionTreeItem(object): + """Shows the name of the item in the extensions tree""" + + def __init__(self, name, kind="debug", parent=None): + self.kind = kind + self.name = str(name) + + +class ExtensionTreeView(TreeView): + """A list of extensions (inx file based)""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.parents = {} + self.menus = {} + + def setup(self, *args, **kwargs): + self.ViewColumn("Name", expand=True, text="name") + self.ViewSort(data=lambda item: item.name, ascending=True) + + def get_menu(self, parent, *remain): + menu_id = "::".join([str(r) for r in remain]) + if menu_id in self.menus: + return self.menus[menu_id] + + if remain[:-1]: + parent = self.get_menu(parent, *remain[:-1]) + + menu = self._add_item([ExtensionTreeItem(remain[-1])], parent=parent) + self.menus[menu_id] = menu + return menu + + def add_item(self, item, parent=None): + if not item or not item.name: + return None + if item.kind not in self.parents: + tree_item = ExtensionTreeItem(item.kind.title()) + self.parents[item.kind] = self._add_item([tree_item], parent=None) + parent = self.parents[item.kind] + if item.kind == "effect" and len(item.menu) > 1: + parent = self.get_menu(parent, *item.menu[:-1]) + return self._add_item([item], parent) + + +class MoreInformation(ChildWindow): + """Show further information for an installed package""" + + name = "info" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.inx = ExtensionTreeView(self.widget("inx"), selected=self.select_inx) + + def load_widgets(self, pixmaps, item): + """Initialise the information""" + try: + self.widget("info_website").show() + self.widget("info_website").set_uri(item.link) + self.widget("info_website").set_label(item.link) + except Exception: + self.widget("info_website").hide() + + self.pixmaps = pixmaps + self.window.set_title(item.name) + self.widget("info_name").set_label(item.name) + self.widget("info_desc").set_label(item.summary) + self.widget("info_version").set_label(item.version) + self.widget("info_license").set_label(item.license) + self.widget("info_author").set_label(f"{item.author}") + try: + self.widget("info_image").set_from_pixbuf(pixmaps.get(item.get_icon())) + except Exception: + pass + + self.inx.clear() + if hasattr(item, "get_files"): + for fn in item.get_files(filters=("*.inx",)): + self.inx.add([ExtensionTreeItem(fn, kind="lost-and-found")]) + + def select_inx(self, item): + pass diff --git a/share/extensions/other/inkman/inkman/gui/main.py b/share/extensions/other/inkman/inkman/gui/main.py new file mode 100644 index 0000000..9ff8065 --- /dev/null +++ b/share/extensions/other/inkman/inkman/gui/main.py @@ -0,0 +1,371 @@ +# +# Copyright 2018 Martin Owens +# +# 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 3 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, see +# +"""Gtk 3+ Inkscape 1.0 Extensions Manager GUI.""" + +import os +import sys +import webbrowser + +from inkex.gui import Window, ChildWindow, TreeView, asyncme +from inkex.gui.pixmap import PixmapManager +from inkex.gui.app import Gtk + +from ..utils import DATA_DIR, INKSCAPE_PROFILE +from ..remote import RemoteArchive, SearchError +from .. import __state__ + + +def tag(name, color="#EFEFEF", fgcolor="#333333"): + return f" {name} " + + +class LocalTreeView(TreeView): + """A List of locally installed packages""" + + def __init__(self, target, widget, *args, **kwargs): + self._target = target + self._pixmaps = kwargs["pixmaps"] + self._version = kwargs.pop("version", None) + + style = widget.get_style_context() + self._fg_color = style.get_color(Gtk.StateFlags.NORMAL) + # self._bg_color = style.get_property('background-color', Gtk.StateFlags.NORMAL) + + super().__init__(widget, *args, **kwargs) + + def get_name(self, item): + # color = self._style.get_property('color', Gtk.StateFlags.NORMAL) + return f"{item.name}\n{item.summary}" + + def get_icon(self, item): + try: + return self._pixmaps.get(item.get_icon(), "") + except Exception: + return "" + + def setup(self, *args, **kwargs): + """Setup the treeview with one or many columns manually""" + + col = self.create_column("Extensions Package", expand=True) + + img = col.add_image_renderer(self.get_icon, pad=0, pixmaps=self._pixmaps) + img.set_property("ypad", 2) + + txt = col.add_text_renderer(self.get_name) + txt.set_property("foreground-rgba", self._fg_color) + # This is detected as black for remote treeview, we're not sure why + # txt.set_property("background-rgba", self._bg_color) + txt.set_property("xpad", 8) + + col = self.create_column("Version", expand=False) + txt = col.add_text_renderer("version", template=f"{0}") + txt.set_property("foreground-rgba", self._fg_color) + + col = self.create_column("Author", expand=False) + txt = col.add_text_renderer("author") + txt.set_property("foreground-rgba", self._fg_color) + + if self._target.version_specific: + col = self.create_column("Inkscape", expand=False) + txt = col.add_text_renderer("target") + txt.set_property("foreground-rgba", self._fg_color) + + self.create_sort(data=lambda item: item.name, ascending=True, contains="name") + + super().setup(*args, **kwargs) + + +class RemoteTreeView(LocalTreeView): + """A List of remote packages for installation""" + + def get_installed(self, item): + if item.installed is None: + item.set_installed(False) + for installed_item in self._target.list_installed(): + if item.ident == installed_item.ident: + item.set_installed(True) + return bool(item.installed) + + def setup(self, *args, **kwargs): + def get_star(item): + star = "star-none.svg" + if item.stars > 10: + star = "star-lots.svg" + elif item.stars > 1: + star = "star-some.svg" + return self._pixmaps.get(star) + + def get_sort(item): + if not item.verified: + return -100 + item.stars + if self._version not in item.targets: + return -20 + item.stars + return item.stars + (1000 * int(item.recommended)) + + super().setup(*args, **kwargs) + + col = self.create_column("Stars", expand=True) + img = col.add_image_renderer(get_star, pad=0, size=16, pixmaps=self._pixmaps) + img.set_property("ypad", 2) + txt = col.add_text_renderer("stars") + txt.set_property("foreground-rgba", self._fg_color) + + self.create_sort(data=get_sort, ascending=True) + + def get_name(self, item): + summary = item.summary + if self.get_installed(item): + summary = tag("Installed", "#37943e", "white") + summary.strip() + elif not item.verified: + summary = tag("Unverified", "#CB0000", "white") + summary.strip() + elif self._version not in item.targets: + targets = item.targets or ["No Inkscape Versions"] + summary = ( + "".join([tag(t, "#00CB00", "white") for t in targets]) + summary.strip() + ) + else: + summary = ( + tag("Verified", "#37943e", "white") + + tag(self._version, "#37943e", "white") + + summary.strip() + ) + + return f"{item.name}\n{summary}\n" + "".join( + tag(t) for t in item.tags + ) + + +class LocalPixmaps(PixmapManager): + """Load local pictures""" + + pixmap_dir = DATA_DIR + + +class ExtensionManagerWindow(Window): + name = "gui" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.target = self.gapp.kwargs["target"] + self._version = self.gapp.kwargs["version"] + + self.pixmaps = LocalPixmaps("pixmaps", size=48, load_size=(96, 96)) + self.searching = self.widget("dl-searching") + self.searchbox = self.searching.get_parent() + self.searchbox.remove(self.searching) + + self.local = LocalTreeView( + self.target, + self.widget("local_extensions"), + version=self._version, + pixmaps=self.pixmaps, + selected=self.select_local, + ) + + self.remote = RemoteTreeView( + self.target, + self.widget("remote_extensions"), + version=self._version, + pixmaps=self.pixmaps, + selected=self.select_remote, + ) + + self.widget("loading").start() + self.window.show_all() + self.window.present() + # self.window.set_keep_above(True) + + self.refresh_local() + self.widget("remote_install").set_sensitive(False) + self.widget("remote_info").set_sensitive(False) + self.widget("local_install").set_sensitive(True) + self.window.set_title(self.target.label + f" ({self._version}) - {__state__}") + + if not self.target.is_search: + self.widget("remote_getlist").show() + self.widget("dl-search").hide() + else: + self.widget("dl-search").show() + self.widget("remote_getlist").hide() + self.widget("no_results").hide() + + # Get a tasting of items from the server + self._remote_search(None) + + def remote_getlist(self, widget): + self._remote_search("") + + @asyncme.run_or_none + def refresh_local(self): + """Searches for locally installed extensions and adds them""" + self.local.clear() + self.widget("local_uninstall").set_sensitive(False) + self.widget("local_information").set_sensitive(False) + + all_packages = [] + for item in self.target.list_installed(cached=False): + self.local.add_item(item) + self.widget("loading").stop() + + def select_local(self, item): + """Select an installed extension""" + self.widget("local_uninstall").set_sensitive(item.is_uninstallable()) + self.widget("local_information").set_sensitive(bool(item)) + + def local_information(self, widget): + """Show the more information window""" + if self.local.selected: + self.load_window("info", pixmaps=self.pixmaps, item=self.local.selected) + + def local_uninstall(self, widget): + """Uninstall selected extection package""" + item = self.local.selected + if item.is_uninstallable(): + if item.uninstall(): + self.local.remove_item(item) + self.remote.refresh() + + def change_remote_all(self, widget, unk): + """When the source switch button is clicked""" + self.remote_search(self.widget("dl-search")) + + def remote_search(self, widget): + """Remote search activation""" + query = widget.get_text() + if len(query) > 2: + self._remote_search(query) + + def _remote_search(self, query): + filtered = False # self.widget('remote_target').get_active() + self.remote.clear() + self.widget("no_results").hide() + self.widget("results_found").show() + self.widget("remote_install").set_sensitive(False) + self.widget("remote_info").set_sensitive(False) + self.widget("dl-search").set_sensitive(False) + self.searchbox.add(self.searching) + self.widget("dl-searching").start() + self.async_search(query, filtered) + + def remote_info(self, widget): + """Show the remote information""" + if self.remote.selected and self.remote.selected.link: + webbrowser.open(self.remote.selected.link) + + @asyncme.run_or_none + def async_search(self, query, filtered): + """Asyncronous searching in PyPI""" + try: + for package in self.target.search(query, filtered): + self.add_search_result(package) + except SearchError as err: + # Ignore taster request + if query is not None: + self.dialog(str(err)) + self.search_finished() + + @asyncme.mainloop_only + def add_search_result(self, package): + """Adding things to Gtk must be done in mainloop""" + self.remote.add_item(package) + + @asyncme.mainloop_only + def search_finished(self): + """After everything, finish the search""" + self.searchbox.remove(self.searching) + self.widget("dl-search").set_sensitive(True) + self.replace(self.searching, self.remote._list) + if not self.remote._model.iter_n_children(): + self.widget("no_results").show() + self.widget("results_found").hide() + + def select_remote(self, item): + """Select an installed extension""" + # Do we have a place to install packages to? + active = ( + self.remote.selected + and self.remote.selected.is_installable(self._version) + and not self.remote.selected.installed + ) + self.widget("remote_install").set_sensitive(active) + if self.remote.selected.link: + self.widget("remote_info").set_sensitive(True) + + def remote_install(self, widget): + """Install a remote package""" + self.widget("remote_install").set_sensitive(False) + item = self.remote.selected + try: + item.install() + except Exception as err: + self.dialog(str(err)) + return + self.remote.refresh() + self.refresh_local() + self.widget("main_notebook").set_current_page(0) + + def local_install(self, widget): + """Install from a local filename""" + dialog = Gtk.FileChooserDialog( + title="Please choose a package file", + transient_for=self.window, + action=Gtk.FileChooserAction.OPEN, + ) + + dialog.add_buttons( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, + ) + + filter_py = Gtk.FileFilter() + filter_py.set_name("Packages") + filter_py.add_mime_type("application/x-compressed-tar") + filter_py.add_mime_type("application/zip") + dialog.add_filter(filter_py) + + filter_text = Gtk.FileFilter() + filter_text.set_name("Python Wheel") + filter_text.add_mime_type("application/zip") + filter_text.add_pattern("*.whl") + dialog.add_filter(filter_text) + + filter_any = Gtk.FileFilter() + filter_any.set_name("Any files") + filter_any.add_pattern("*") + dialog.add_filter(filter_any) + + response = dialog.run() + if response == Gtk.ResponseType.OK: + self.target._install(dialog.get_filename(), {}) + self.refresh_local() + + dialog.destroy() + + def update_all(self, widget=None): + """Update the extensions manager, and everything else""" + pass + + def dialog(self, msg): + self.widget("dialog_msg").set_label(msg) + self.widget("dialog").set_transient_for(self.window) + self.widget("dialog").show_all() + + def close_dialog(self, widget): + self.widget("dialog_msg").set_label("") + self.widget("dialog").hide() diff --git a/share/extensions/other/inkman/inkman/package.py b/share/extensions/other/inkman/inkman/package.py new file mode 100644 index 0000000..a19127e --- /dev/null +++ b/share/extensions/other/inkman/inkman/package.py @@ -0,0 +1,330 @@ +# +# Copyright (C) 2019 Martin Owens +# +# 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. +# +""" +Support for constructing and understanding installed extensions +as python packages. + +Start by using 'PackageLists' and iterate over to get 'PackageList' objects +iterate over those to get 'Package' objects and use those to know more +information about the installed packages. +""" + +import os +import sys +import json +import logging +from fnmatch import fnmatch + +from .utils import ( + DATA_DIR, + ICON_SEP, + parse_metadata, + clean_author, + get_user_directory, + get_inkscape_directory, + ExtensionInx, +) + +# The ORDER of these places is important, when installing packages it will +# choose the FIRST writable directory in the lsit, so make sure that the +# more preferable locations appear at the top. +EXTENSION_PLACES = [] + +for path in sys.path: + if "extensions" in path: + if "/bin" in path: + path = path.replace("/bin", "") + EXTENSION_PLACES.append(path) + +CORE_ICON = os.path.join(DATA_DIR, "pixmaps", "core_icon.svg") +ORPHAN_ICON = os.path.join(DATA_DIR, "pixmaps", "orphan_icon.svg") +DEFAULT_ICON = os.path.join(DATA_DIR, "pixmaps", "default_icon.svg") +MODULE_ICON = os.path.join(DATA_DIR, "pixmaps", "module_icon.svg") + + +class PackageItem(object): + """ + Gets information about the package using requests. + + Can be remote, or local json file. + """ + + default_icon = DEFAULT_ICON + + @classmethod + def is_pkg(cls, info): + """Returns true if this info package is considered a managed package""" + for field in ("name", "author", "verified", "links", "summary"): + if field not in info: + return False + return True + + def __init__(self, info, remote=None): + if not self.is_pkg(info): + raise ValueError("Not a valid package, refusing to create it.") + + self.info = info + self.remote = remote + self.installed = None + self._installer = None + self._uninstaller = None + self._missing = [] + self._icon = None + + ident = property(lambda self: self.info.get("id")) + url = property(lambda self: self.info["links"]["file"]) + link = property(lambda self: self.info["links"]["html"]) + name = property(lambda self: self.info["name"] or "Unnamed") + license = property(lambda self: self.info.get("license") or "") + author = property(lambda self: self.info["author"]) + tags = property(lambda self: self.info.get("tags", [])) + + stars = property(lambda self: self.info["stats"]["liked"]) + downloads = property(lambda self: self.info["stats"]["downloaded"]) + verified = property(lambda self: self.info["verified"]) + recommended = property(lambda self: self.info["stats"].get("extra", 0) == 7) + + targets = property(lambda self: self.info.get("Inkscape Version", [])) + target = property(lambda self: ", ".join(self.targets)) + + @property + def summary(self): + ret = self.info["summary"] or "No summary" + if len(ret) > 110: + ret = ret.split(". ", 1)[0] + if len(ret) > 110: + ret = ret[:110].rsplit(" ", 1)[0] + "..." + return ret + + @property + def version(self): + if "version" in self.info: + return str(self.info["version"]) + if "stats" in self.info and "revisions" in self.info["stats"]: + return str(int(self.info["stats"]["revisions"]) + 1) + return "?" + + def set_installer(self, fn): + self._installer = fn + + def set_uninstaller(self, fn, *args): + def _inner(info): + return fn(info, *args) + + self._uninstaller = _inner + + def set_installed(self, installed=True): + self.installed = installed + + def is_installable(self, version): + if version not in self.targets or not self.verified: + return False + return bool(not self.installed and self._installer) + + def is_uninstallable(self): + return bool(self._uninstaller) + + def install(self): + """Install the remote package""" + if not self.remote: + raise IOError("Can not install without a defined remote") + url = self.remote(self.info["links"]["file"]) + msg = self._installer(url.as_local_file(), self.info) + self.set_installed(True) + return msg + + def uninstall(self): + """Remove the pakage if possible""" + if self._uninstaller(self.info): + self.set_installed(False) + return True + return False + + def get_icon(self): + if self._icon: + return self._icon + if self.info.get("icon"): + if not self.remote: + raise IOError("Can get icon without a defined remote") + icon = self.remote(self.info["icon"]) + self._icon = icon.as_local_file() or self.default_icon + return self._icon + for filename in self.get_files(): + name = os.path.basename(filename) + if name in ("icon.svg", "icon.png"): + self._icon = os.path.abspath(filename) + return filename + return self.default_icon + + def get_files(self, missing=False): + """List files""" + return [ + name + for name in self.info.get("files", []) + if missing or name not in self._missing + ] + + +class OrphanedItem(PackageItem): + """ + A special kind of item to collect all orphaned files + """ + + default_icon = ORPHAN_ICON + + def __init__(self, parent): + super().__init__( + { + "name": "Orphan Extensions", + "author": "Various", + "verified": False, + "summary": "Old and manually installed extensions", + "license": "Unknown", + "links": {}, + "version": "-", + "stats": {"liked": -1, "downloaded": -1}, + } + ) + + self._icon = self.default_icon + self._parent = os.path.abspath(parent) + self._files = set() + self._removed = set() + self._items = {} + + def _get_target_file(self, filename): + if not os.path.isabs(filename): + filename = os.path.join(self._parent, filename) + path = os.path.abspath(filename) + return path.replace(self._parent, "").lstrip("/") + + def add_file(self, filename): + """Add a file to the 'this file exists' list""" + self._files.add(self._get_target_file(filename)) + + def remove_file(self, filename, item=None): + """Add a file to the 'this file is said to exist' list""" + fn = self._get_target_file(filename) + self._removed.add(fn) + if item is not None: + self._items[fn] = item + + def get_files(self, filters=()): + """Returns a filtered set of files which exist, minus ones said to exist""" + if not filters: + filters = ("*",) + items = [] + for item in self._files - self._removed: + if any([fnmatch(item, filt) for filt in filters]): + items.append(item) + return items + + def get_missing(self): + """Returns a set of files which don't exist, even though they were said to""" + return [(fn, self._items.get(fn, None)) for fn in self._removed - self._files] + + +class PythonItem(PackageItem): + """ + A python package that has an inx file, but was never installed properly. + """ + + def __init__(self, pip): + self.pip = pip + info = self.pip.get_metadata() + super().__init__( + { + "pip": True, + "name": info["name"], + "summary": info["summary"], + "author": info["author"] or "Unknown", + "version": info["version"], + "license": info["license"], + "verified": False, + "links": {}, + "stats": {"liked": -1, "downloaded": -1}, + } + ) + + def get_files(self): + return self.pip.package_files() + + +class PythonPackage(object): + """ + A reprisentation of the python package, NOT the json based packages. + """ + + name = property(lambda self: self.get_metadata()["name"]) + version = property(lambda self: self.get_metadata()["version"]) + + def __init__(self, path, parent): + self._metadata = None + self.path = path + self.parent = parent + + def get_inx(self): + """Yields all of the inx files in this package""" + for filename in self.package_files(): + if filename.endswith(".inx"): + yield filename + + def package_files(self): + """Return a generator of all files in this installed package""" + parent = os.path.abspath(os.path.dirname(self.path)) + record = self.get_file("RECORD") + if not record: + return + for line in record.split("\n"): + if line and "," in line: + (filename, checksum, size) = line.rsplit(",", 2) + # XXX Check filesize or checksum? + if not os.path.isabs(filename): + filename = os.path.join(parent, filename) + yield filename + + def get_metadata(self): + """Returns the metadata from an array of known types""" + if self._metadata is None: + for name in ("METADATA", "PKG-INFO"): + md_mail = self.get_file(name) + if md_mail: + self._metadata = parse_metadata(md_mail) + + if self._metadata is None: + md_json = self.get_file("metadata.json") + if md_json: + self._metadata = clean_author(json.loads(md_json)) + + if self._metadata is None: + raise KeyError("Can't find package meta data: {}".format(self.path)) + return self._metadata + + def get_file(self, name): + """Get filename if it exists""" + if not self.path or not os.path.isdir(self.path): + return None + path = os.path.join(self.path, name) + if os.path.isfile(path): + with open(path, "r") as fhl: + return fhl.read() + return None + + def get_depedencies(self): + """Return a list of other pip packages this packages needs""" + return self.get_metadata()["requires"] diff --git a/share/extensions/other/inkman/inkman/remote.py b/share/extensions/other/inkman/inkman/remote.py new file mode 100644 index 0000000..c2c4b54 --- /dev/null +++ b/share/extensions/other/inkman/inkman/remote.py @@ -0,0 +1,153 @@ +# +# Copyright (C) 2019-2021 Martin Owens +# +# 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. +# +""" +Searching for external packages and getting meta data about them. +""" + +import re +import os +import json +import logging +import requests + +try: + from cachecontrol import CacheControl, CacheControlAdapter + from cachecontrol.caches.file_cache import FileCache + from cachecontrol.heuristics import ExpiresAfter +except (ImportError, ModuleNotFoundError): + CacheControl = None + +from inkex.command import CommandNotFound, ProgramRunError, call +from collections import defaultdict + +from .utils import INKSCAPE_VERSION, CACHE_DIR +from .package import DEFAULT_ICON, PackageItem + +PYTHON_VERSION = "py3" + +class SearchError(IOError): + pass + +class LocalFile(object): + """Same API as RemoteFile, but for locals""" + + def __init__(self, basedir, url): + self.basedir = basedir + self.url = url + + def __str__(self): + return self.url + + def filename(self): + return self.url.split("/")[-1] + + def filepath(self): + return os.path.join(self.basedir, self.url) + + def as_local_file(self): + filename = self.filepath() + if os.path.isfile(filename): + return filename + raise IOError(f"Can't find file: {filename}") + + +class RemoteFile(object): + """A remote file, icon, zip etc""" + + def __init__(self, session, url): + self.session = session + self.url = url + + def __str__(self): + return self.url + + def get(self): + return self.session.get(self.url) + + def filename(self): + return self.url.split("/")[-1] + + def filepath(self): + return os.path.join(CACHE_DIR, self.filename()) + + def as_local_file(self): + if self.url: + remote = self.get() + if remote and remote.status_code == 200: + with open(self.filepath(), "wb") as fhl: + fhl.write(remote.content) + return self.filepath() + return None + + +class RemoteArchive(object): + """The remote archive used to be PyPI but is now inkscape's own website.""" + + URL = "https://inkscape.org/gallery/={category}/json/" + + def __init__(self, category, version=INKSCAPE_VERSION): + self.version = version + self.url = self.URL.format(category=category) + self.session = requests.session() + if CacheControl is not None: + self.session.mount( + "https://", + CacheControlAdapter( + cache=FileCache(CACHE_DIR), + heuristic=ExpiresAfter(days=1), + ), + ) + + def _remote_file(self, url): + return RemoteFile(self.session, url) + + def search(self, query, filtered=True): + """Search for extension packages""" + for info in self._search(query): + item = PackageItem(info, remote=self._remote_file) + if not filtered or not self.version or self.version in item.targets: + yield item + + def _search(self, query, tags=[]): + """Search for the given query and yield each item, will raise if any other response""" + response = None + + if query is None: + try: + response = self.session.get( + self.url, + params={ + "tags": tags, + "checked": 1, + "limit": 10, + "order": "extra_status", + }, + ) + except requests.exceptions.RequestException as err: + raise SearchError(str(err)) + except ConnectionError as err: + raise SearchError(str(err)) + except requests.exceptions.RequestsWarning: + pass + else: + response = self.session.get( + self.url, params={"q": query, "tags": tags, "checked": 1} + ) + if response is not None: + for item in response.json()["items"]: + yield item diff --git a/share/extensions/other/inkman/inkman/target.py b/share/extensions/other/inkman/inkman/target.py new file mode 100644 index 0000000..dff1211 --- /dev/null +++ b/share/extensions/other/inkman/inkman/target.py @@ -0,0 +1,375 @@ +# +# Copyright (C) 2019 Martin Owens +# +# 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. +# +""" +Target a directory to install resources into. +""" + +import os +import sys +import json +import logging +from shutil import which + +from inkex.inx import InxFile +from inkex.command import call, CommandNotFound, ProgramRunError + +from .archive import Archive, UnrecognizedArchiveFormat +from .remote import RemoteArchive, LocalFile +from .utils import INKSCAPE_PROFILE, CACHE_DIR, ExtensionInx +from .package import PackageItem, OrphanedItem, PythonItem, PythonPackage + + +class BasicTarget(object): + """ + A location where to install something, plus how to search for it. + """ + + version_specific = False + + def __init__(self, category, label, path, is_search=False, filters=()): + self.category = category + self.label = label + self.path = os.path.join(INKSCAPE_PROFILE, path) + self.is_search = is_search + self.archive = RemoteArchive(category) + self.filters = filters + self._installed = None + + def search(self, query, filtered=False): + """Search the online archive for things""" + for pkg in self.archive.search(query, filtered): + pkg.set_installer(self._install) + yield pkg + + def is_writable(self): + """Can the folder be written to (for installation)""" + try: + return os.access(self.path, os.W_OK) + except IOError: + return False + + def _install(self, filename, info): + if not info.get("id"): + info["id"] = self.generate_id(filename) + + if not info.get("id"): + raise ValueError("Id is a required field for packages") + + if filename.endswith(".zip"): + location = info["id"] + fname = "info.json" + info["files"] = list(self.install_zip_files(filename, location)) + else: + location = "pkg" + fname = info["id"] + ".json" + info["files"] = [self.write_file(filename, os.path.basename(filename))] + + self.write_file(json.dumps(info).encode("utf8"), fname, extra=location) + + return f"Package installed! Remember to restart inkscape to use it!" + + def _uninstall(self, info, json_file): + self._installed = None + for fname in info.get("files"): + self.remove_file(fname) + if json_file and os.path.isfile(json_file): + self.remove_file(json_file) + return True + + def install_zip_files(self, filename, location): + """Install the files in the zip filename as non-pip files""" + with Archive(filename) as archive: + for filename in archive.filenames(): + yield self.write_file(archive.read(filename), filename, extra=location) + + def generate_id(self, filename): + """User submitted zip file, generate an id as best we can""" + return filename.replace(".zip", "") + + def list_installed(self, cached=True): + """ + Loops through all the files in the target path and finds all the installed items. + """ + if cached and self._installed: + yield from self._installed + return + + self._installed = [] + for item in self._list_installed(): + self._installed.append(item) + yield item + + def _list_installed(self): + orphans = OrphanedItem(self.path) + for root, subs, files in os.walk(self.path): + for fname in files: + fpath = os.path.join(root, fname) + name = self.unprefix_path(fpath) + if fname.endswith(".json"): + if os.path.basename(fpath) == "package.json": + continue + with open(fpath, "rb") as fhl: + data = fhl.read() + info = json.loads(data) + if not PackageItem.is_pkg(info): + continue + + item = PackageItem( + info, remote=self._remote_or_local_file(root) + ) + item.set_uninstaller(self._uninstall, fpath) + yield item + + for pkg_file in item.get_files(missing=True): + orphans.remove_file(pkg_file, item) + orphans.remove_file(os.path.join(root, pkg_file), item) + else: + orphans.add_file(name) + + for fname, item in orphans.get_missing(): + if item is not None: + item._missing.append(fname) + + if orphans.get_files(filters=self.filters): + yield orphans + + def _remote_or_local_file(self, basedir): + # If a json file specifies something that's local, it's "ALWAYS" local to the + # json file as a basedir. + def _inner(url): + if "://" not in url: + return LocalFile(basedir, url) + return self.archive._remote_file(url) + + return _inner + + def write_file(self, source, source_name=None, extra=None): + target = os.path.join(self.path, extra) if extra else self.path + + if isinstance(source, str): + if not source_name: + source_name = source + with open(source, "rb") as fhl: + source = fhl.read() + + path = os.path.join(target, source_name) + filedir = os.path.dirname(path) + if not os.path.isdir(filedir): + os.makedirs(filedir) + + # Ignore paths + if not os.path.isdir(path): + with open(path, "wb") as whl: + whl.write(source) + + return self.unprefix_path(path) + + def remove_file(self, filename): + """ + Remove the given file and clean up + """ + if not filename.startswith(self.path): + filename = os.path.join(self.path, filename) + if os.path.isfile(filename): + os.unlink(filename) + + # Recursively clean up directories (if empty) + path = os.path.dirname(filename) + while path.lstrip("/") != self.path.lstrip("/"): + if os.listdir(path): + break + os.rmdir(path) + path = os.path.dirname(path) + + def unprefix_path(self, path): + """ + Removes the prefix of the given path, if it's based in self.path + """ + # Strip just the OS seperator, but what if the files were moved from another OS? + return path.replace(self.path, "").lstrip("/").lstrip("\\") + + +class ExtensionsTarget(BasicTarget): + """ + Extra functional target for extensions (pip based) + """ + + version_specific = True + + def get_pip(self): + path = os.path.abspath(os.path.join(self.path, "bin")) + return which("pip", path=path + ":" + os.environ["PATH"]) + + def _install(self, filename, info): + if self.is_pip_package(filename): + results = self.pip_install(filename) + if results: + info["pip"] = True + info["id"] = results.strip().split()[-1] + fname = info["id"] + ".json" + self.write_file(json.dumps(info).encode("utf8"), fname, extra="lib") + return ( + f"Python Package installed! Remember to restart inkscape to use it!" + ) + return f"Failed to install, something is wrong with your setup." + + return super()._install(filename, info) + + def _uninstall(self, info, json_file): + self._installed = None + if not info.get("pip"): + return super()._uninstall(info, json_file) + self.pip_uninstall(info["name"]) + if json_file and os.path.isfile(json_file): + self.remove_file(json_file) + return True + + def is_pip_package(self, filename): + """Return true if this is a detectable pip package""" + if filename.endswith(".whl"): + return True + try: + with Archive(filename) as archive: + for filename in archive.filenames(): + if filename.endswith("setup.py"): + return True + except UnrecognizedArchiveFormat: + return False + return False + + def pip_install(self, filename): + """Install the filename as a pip package""" + pip = self.get_pip() + if pip is None: + logging.error( + "This package requires python VirtualEnv which is not available on your system." + ) + return None + try: + results = call( + pip, + "install", + ("isolated", True), + ("disable-pip-version-check", True), + ("cache-dir", CACHE_DIR), + filename, + ).decode("utf8") + except ProgramRunError as err: + raise + return results + + def pip_uninstall(self, name): + """Uninstall the given pip package name""" + try: + results = call( + self.get_pip(), "uninstall", ("disable-pip-version-check", True), name + ).decode("utf8") + except ProgramRunError as err: + raise + return results + + def generate_id(self, filename): + """Extensions have an id internally, try and use it""" + try: + with Archive(filename) as archive: + inxes = [item for item in archive.filenames() if item.endswith(".inx")] + if not inxes: + raise IOError("Refusing to install extension without inx file!") + inx = ExtensionInx(archive.read(inxes[0]).decode("utf-8")) + return inx.ident + except UnrecognizedArchiveFormat: + raise IOError( + "Refusing the install extension without inx file (unknown archive)" + ) + except: + raise IOError("Refusing the install extension with bad inx file!") + + def _list_installed(self): + """ + Add pip packages to file lists. + """ + orphans = None + packages = {} + all_deps = set() + all_files = set() + + # First collect a list of python packages installed + for node in self.get_python_paths(): + if node.endswith(".dist-info") or node.endswith(".egg-info"): + package = PythonPackage(node, self.path) + packages[package.name] = package + all_files |= set(package.package_files()) + for dep, _ in package.get_depedencies(): + all_deps.add(dep) + + # Now return all non pip packaged extensions (from super) + for item in super()._list_installed(): + if item.info.get("pip", False): + if self.info.ident not in packages: + print(f"Can't find python package: {item.ient}") + continue + + pip_pkg = packages[item.ident] + item.info["version"] = pip_pkg.version + + if isinstance(item, OrphanedItem): + orphans = item + else: + yield item + + # Remove all orphaned files that were installed by pip packages + if orphans is not None: + for fn in all_files: + orphans.remove_file(fn) + if orphans.get_files(filters=self.filters): + # Yield if we still have orphans + yield orphans + + # Now what to do with all these remaining packages, pretend their installed? + for name, package in packages.items(): + for inx in package.get_inx(): + item = PythonItem(package) + item.set_uninstaller(self._uninstall, None) + yield item + break + + for dep in all_deps: + if dep not in packages: + # These packages are often just installed into the system, nothing to say. + # XXX But, there is a future where pip could be interigated. + # logging.error(f"Missing python depedency: {dep}") + continue + packages.pop(dep) + + def get_python_paths(self): + """Returns paths related to the python packages""" + pyver = "python" + sys.version[:3] + for varient in [ + os.path.join(self.path, "lib", pyver, "site-packages"), + ]: + if os.path.isdir(varient): + for subpath in os.listdir(varient): + yield os.path.join(varient, subpath) + + def get_package(self, name, version=None): + """Test every package in this list if it matches the name and version""" + for package in self.iter(): + found = package.is_package(name, version=version) + if found: + return package + return None diff --git a/share/extensions/other/inkman/inkman/targets.py b/share/extensions/other/inkman/inkman/targets.py new file mode 100644 index 0000000..e7bed7c --- /dev/null +++ b/share/extensions/other/inkman/inkman/targets.py @@ -0,0 +1,20 @@ +""" +Definition of available Inkscape target directories and their machinery +""" + +from .target import ExtensionsTarget, BasicTarget + +TARGETS = [ + # Website slug, Visible name, local directory, search instead of list + ExtensionsTarget("extension", "Extensions", "extensions", True, filters=("*.inx",)), + BasicTarget("template", "Templates", "templates", True, filters=("*.svg",)), + BasicTarget("palette", "Shared Paletts", "palettes", filters=("*.gpl",)), + BasicTarget("symbol", "Symbol Collections", "symbols", filters=("*.svg",)), + BasicTarget("keyboard", "Keyboard Shortcuts", "keys", filters=("*.xml",)), + # ('marker', 'Marker Collections', '', False), # No marker config + # ('pattern', 'Pattern Collections', '', False), # No pattern config + # ('', 'User Interface Themes', 'themes', False), # No website category + # ('', 'Paint Server', 'paint', False), # No website category + # ('', 'User Interfaces', 'ui', False), # No website category + # ('', 'Icon Sets', 'icons', False), # No website category +] diff --git a/share/extensions/other/inkman/inkman/utils.py b/share/extensions/other/inkman/inkman/utils.py new file mode 100644 index 0000000..f98f3b1 --- /dev/null +++ b/share/extensions/other/inkman/inkman/utils.py @@ -0,0 +1,166 @@ +# +# Copyright (C) 2019 Martin Owens +# +# 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. +# +""" +Utilities functions for inkscape extension manager. +""" + +import os + +from collections import defaultdict +from email.parser import FeedParser +from appdirs import user_cache_dir + +from inkex.inx import InxFile +from inkex.command import inkscape, ProgramRunError, CommandNotFound + +DEFAULT_VERSION = "1.1" +CACHE_DIR = user_cache_dir("inkscape-extension-manager", "Inkscape") +INKSCAPE_VERSION = os.environ.get("INKSCAPE_VERSION", None) +INKSCAPE_PROFILE = os.environ.get("INKSCAPE_PROFILE_DIR", None) + +# This directory can be passed and used by inkscape to override it's +# profile directory for extensions +INKSCAPE_EXTENSIONS = os.environ.get("INKSCAPE_EXTENSIONS_DIR", None) + +if not INKSCAPE_PROFILE and "VIRTUAL_ENV" in os.environ: + INKSCAPE_PROFILE = os.path.dirname(os.environ["VIRTUAL_ENV"]) + +if not INKSCAPE_PROFILE and "APPDATA" in os.environ: + INKSCAPE_PROFILE = os.path.join(os.environ["APPDATA"], "inkscape") + +if not INKSCAPE_PROFILE and not INKSCAPE_EXTENSIONS: + raise ImportError("The Inkscape profile directory isn't set!") + +if not os.path.isdir(CACHE_DIR): + os.makedirs(CACHE_DIR) + +DATA_DIR = os.path.join(os.path.dirname(__file__), "data") +ICON_SEP = ("-" * 12) + "SVGICON" + ("-" * 12) + + +def _pythonpath(): + for pth in os.environ.get("PYTHONPATH", "").split(":"): + if os.path.isdir(pth): + yield pth + + +def get_user_directory(): + """Return the user directory where extensions are stored.""" + if INKSCAPE_EXTENSIONS: + return os.path.abspath(INKSCAPE_EXTENSIONS) + + if "INKSCAPE_PROFILE_DIR" in os.environ: + return os.path.abspath( + os.path.expanduser( + os.path.join(os.environ["INKSCAPE_PROFILE_DIR"], "extensions") + ) + ) + + home = os.path.expanduser("~") + for pth in _pythonpath(): + if pth.startswith(home): + return pth + + +def get_inkscape_directory(): + """Return the system directory where inkscape's core is.""" + for pth in _pythonpath(): + if os.path.isdir(os.path.join(pth, "inkex")): + return pth + + +def get_inkscape_version(): + """Attempt to detect the inkscape version""" + try: + line = inkscape(version=True, svg_file=None) + except (ProgramRunError, CommandNotFound): + return DEFAULT_VERSION + if isinstance(line, bytes): + line = line.decode("utf8") + (major, minor) = line.strip().split(" ")[1].split(".")[:2] + return "{}.{}".format(int(major), int(minor.split("-")[0])) + + +def format_requires(string): + """Get a version requires.""" + primary = string.split("; ", 1)[0] + if "(" in primary: + primary, version = primary.split("(", 1) + return (primary.strip(), version.strip(") ")) + return (primary.strip(), None) + + +def parse_metadata(data): + """ + Convert older email based meta data into a newer json format, + See PEP 566 for details. + """ + feed_parser = FeedParser() + feed_parser.feed(data) + metadata = feed_parser.close() + + def getdict(): + """Multi-dimentional dictionary""" + return defaultdict(getdict) + + ret = defaultdict(getdict) + + ret["description"] = metadata.get_payload() + ret["requires"] = [ + format_requires(m) for m in metadata.get_all("Requires-Dist", []) + ] + + for key, value in metadata.items(): + if key == "Home-page": + ret["extensions"]["python.details"]["project_urls"]["Home"] = value + elif key == "Classifier": + ret["classifiers"] = list(ret["classifiers"]) + ret["classifiers"].append(value) + else: + ret[key.lower().replace("-", "_")] = value + + return ret + + +def clean_author(data): + """Clean the author so it has consistant keys""" + for contact in ( + data.get("extensions", {}).get("python.details", {}).get("contacts", []) + ): + if contact["role"] == "author": + data["author"] = contact["name"] + data["author_email"] = contact.get("email", "") + if "<" in data["author"]: + data["author"], other = data["author"].split("<", 1) + if "@" in other and not data["author_email"]: + data["author_email"] = data["author"].split(">")[0] + return data + + +class ExtensionInx(InxFile): + """Information about an extension specifically""" + + ident = property(lambda self: super().ident or f"[no-id] {self.filename}") + name = property(lambda self: super().name or f"[unnamed] {self.ident}") + + @property + def menu(self): + menu = self.xml.find_one("effect/effects-menu") + if menu is not None and menu.get("hidden", "false") == "true": + return ["_hidden", self.name] + return super().menu diff --git a/share/extensions/other/inkman/manage_extensions.inx b/share/extensions/other/inkman/manage_extensions.inx new file mode 100644 index 0000000..dc2b01f --- /dev/null +++ b/share/extensions/other/inkman/manage_extensions.inx @@ -0,0 +1,12 @@ + + + Manage Extensions... + org.inkscape.extension.manager + + all + + + diff --git a/share/extensions/other/inkman/manage_extensions.py b/share/extensions/other/inkman/manage_extensions.py new file mode 100755 index 0000000..41494c7 --- /dev/null +++ b/share/extensions/other/inkman/manage_extensions.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright 2018 Martin Owens +# +# 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 3 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, see +# +""" +Inkscape Extensions Manager, Graphical User Interface (Gtk3) +""" + +import os +import sys +import logging +import warnings +warnings.filterwarnings("ignore") + +from inkex import gui + +from argparse import ArgumentParser + + +def run(args): + # Late imports to catch import errors. + from inkman.targets import TARGETS + from inkman.gui import ManagerApp + from inkman.utils import get_inkscape_version + + arg_parser = ArgumentParser(description=__doc__) + arg_parser.add_argument("input_file", nargs="?") + arg_parser.add_argument( + "--target", default=TARGETS[0].category, choices=[t.category for t in TARGETS] + ) + arg_parser.add_argument("--for-version", default=None) + options = arg_parser.parse_args(args) + version = options.for_version or get_inkscape_version() + try: + ManagerApp( + start_loop=True, + version=version, + target=[t for t in TARGETS if t.category == options.target][0], + ) + except KeyboardInterrupt: + logging.error("User Interputed") + logging.debug("Exiting Application") + + +def recovery_run(args): + try: + run(args) + except Exception: + from inkman.backfoot import attempt_to_recover + + attempt_to_recover() + + +if __name__ == "__main__": + recovery_run(sys.argv[1:]) diff --git a/share/extensions/other/inkman/pyproject.toml b/share/extensions/other/inkman/pyproject.toml new file mode 100644 index 0000000..d2a4fbf --- /dev/null +++ b/share/extensions/other/inkman/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "inkman" +version = "1.0.0" +description = "A GTK3 based extension manager for Inkscape." +authors = ["Martin Owens "] +maintainers = ["Martin Owens "] +license = "GPL-3.0-or-later" + +# The dependencies below are NOT used for packaging, they are abstract. +# They are merely for packagers' convenience and are used in CI for extensions. +[tool.poetry.dependencies] +python = ">=3.7" +appdirs = "1.4.4" +requests = "*" +CacheControl = {extras = ["filecache"], version = "*"} + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/share/extensions/output_scour.inx b/share/extensions/output_scour.inx new file mode 100644 index 0000000..d1348da --- /dev/null +++ b/share/extensions/output_scour.inx @@ -0,0 +1,129 @@ + + + Optimized SVG Output + org.inkscape.output.scour_inkscape + + + + 5 + + true + true + + true + true + + false + false + + true + + + + false + false + false + true + false + + + true + + + + + + 1 + false + + + true + + false + + + true + + + + + + output_scour.svg + + + + + + + + + + + + + + + + 0.31 + true + + + + + .svg + image/svg+xml + Optimized SVG (*.svg) + Scalable Vector Graphics + + + + diff --git a/share/extensions/output_scour.py b/share/extensions/output_scour.py new file mode 100755 index 0000000..185ea97 --- /dev/null +++ b/share/extensions/output_scour.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +""" +Run the scour module on the svg output. +""" + + +import inkex +from inkex.localization import inkex_gettext as _ + +try: + from packaging.version import Version +except ImportError: + raise inkex.DependencyError( + _( + """Failed to import module 'packaging'. +Please make sure it is installed (e.g. using 'pip install packaging' +or 'sudo apt-get install python3-packaging') and try again. +""" + ) + ) + +try: + import scour + from scour.scour import scourString +except ImportError: + raise inkex.DependencyError( + _( + """Failed to import module 'scour'. +Please make sure it is installed (e.g. using 'pip install scour' + or 'sudo apt-get install python3-scour') and try again. +""" + ) + ) + + +class ScourInkscape(inkex.OutputExtension): + """Scour Inkscape Extension""" + + # Scour options + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--simplify-colors", type=inkex.Boolean, dest="simple_colors") + pars.add_argument("--style-to-xml", type=inkex.Boolean) + pars.add_argument( + "--group-collapsing", type=inkex.Boolean, dest="group_collapse" + ) + pars.add_argument("--create-groups", type=inkex.Boolean, dest="group_create") + pars.add_argument("--enable-id-stripping", type=inkex.Boolean, dest="strip_ids") + pars.add_argument("--shorten-ids", type=inkex.Boolean) + pars.add_argument("--shorten-ids-prefix") + pars.add_argument("--embed-rasters", type=inkex.Boolean) + pars.add_argument( + "--keep-unreferenced-defs", type=inkex.Boolean, dest="keep_defs" + ) + pars.add_argument("--keep-editor-data", type=inkex.Boolean) + pars.add_argument("--remove-metadata", type=inkex.Boolean) + pars.add_argument("--strip-xml-prolog", type=inkex.Boolean) + pars.add_argument("--set-precision", type=int, dest="digits") + pars.add_argument("--indent", dest="indent_type") + pars.add_argument("--nindent", type=int, dest="indent_depth") + pars.add_argument("--line-breaks", type=inkex.Boolean, dest="newlines") + pars.add_argument( + "--strip-xml-space", type=inkex.Boolean, dest="strip_xml_space_attribute" + ) + pars.add_argument("--protect-ids-noninkscape", type=inkex.Boolean) + pars.add_argument("--protect-ids-list") + pars.add_argument("--protect-ids-prefix") + pars.add_argument("--enable-viewboxing", type=inkex.Boolean) + pars.add_argument( + "--enable-comment-stripping", type=inkex.Boolean, dest="strip_comments" + ) + pars.add_argument("--renderer-workaround", type=inkex.Boolean) + + # options for internal use of the extension + pars.add_argument("--scour-version") + pars.add_argument("--scour-version-warn-old", type=inkex.Boolean) + + def save(self, stream): + # version check if enabled in options + if self.options.scour_version_warn_old: + scour_version = scour.__version__ + scour_version_min = self.options.scour_version + if Version(scour_version) < Version(scour_version_min): + raise inkex.AbortExtension( + f""" +The extension 'Optimized SVG Output' is designed for Scour {scour_version_min} or later but you're + using the older version Scour {scour_version}. + +Note: You can permanently disable this message on the 'About' tab of the extension window.""" + ) + del self.options.scour_version + del self.options.scour_version_warn_old + + # do the scouring + stream.write(scourString(self.svg.tostring(), self.options).encode("utf8")) + + +if __name__ == "__main__": + ScourInkscape().run() diff --git a/share/extensions/output_scour.svg b/share/extensions/output_scour.svg new file mode 100644 index 0000000..8f1b941 --- /dev/null +++ b/share/extensions/output_scour.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/share/extensions/param_curves.inx b/share/extensions/param_curves.inx new file mode 100644 index 0000000..85f7c32 --- /dev/null +++ b/share/extensions/param_curves.inx @@ -0,0 +1,61 @@ + + + Parametric Curves + org.inkscape.effect.param_curves + + + 0.0 + 1.0 + true + -1.0 + 1.0 + -1.0 + 1.0 + 30 + false + + + + + + + + + + + + + + + + + + + cos(3*t) + sin(5*t) + true + false + + rect + + + + + + diff --git a/share/extensions/param_curves.py b/share/extensions/param_curves.py new file mode 100755 index 0000000..dd90332 --- /dev/null +++ b/share/extensions/param_curves.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 Michel Chatelain. +# 2007 Tavmjong Bah, tavmjong@free.fr +# 2006 Georg Wiora, xorx@quarkbox.de +# 2006 Johan Engelen, johan@shouraizou.nl +# 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +# Changes: +# * This program is derived by Michel Chatelain from funcplot.py. +# His changes are in the Public Domain. +# * Michel Chatelain, 17-18 janvier 2009, a partir de funcplot.py +# * 20 janvier 2009 : adaptation a la version 0.46 a partir de la nouvelle version de funcplot.py +# + +import math +import random +from math import pi +from inkex.utils import math_eval + +import inkex + + +def drawfunction( + t_start, + t_end, + xleft, + xright, + ybottom, + ytop, + samples, + width, + height, + left, + bottom, + fx="cos(3*t)", + fy="sin(5*t)", + times2pi=False, + isoscale=True, + drawaxis=True, +): + if times2pi: + t_start *= 2 * pi + t_end *= 2 * pi + + # coords and scales based on the source rect + scalex = width / (xright - xleft) + xoff = left + coordx = lambda x: (x - xleft) * scalex + xoff # convert x-value to coordinate + scaley = height / (ytop - ybottom) + yoff = bottom + coordy = lambda y: (ybottom - y) * scaley + yoff # convert y-value to coordinate + + # Check for isotropic scaling and use smaller of the two scales, correct ranges + if isoscale: + if scaley < scalex: + # compute zero location + xzero = coordx(0) + # set scale + scalex = scaley + # correct x-offset + xleft = (left - xzero) / scalex + xright = (left + width - xzero) / scalex + else: + # compute zero location + yzero = coordy(0) + # set scale + scaley = scalex + # correct x-offset + ybottom = (yzero - bottom) / scaley + ytop = (bottom + height - yzero) / scaley + + # functions specified by the user + f1 = math_eval(fx, "t") + f2 = math_eval(fy, "t") + + # step is increment of t + step = (t_end - t_start) / (samples - 1) + third = step / 3.0 + ds = step * 0.001 # Step used in calculating derivatives + + a = [] # path array + # add axis + if drawaxis: + # check for visibility of x-axis + if ybottom <= 0 <= ytop: + # xaxis + a.append(["M", [left, coordy(0)]]) + a.append(["l", [width, 0]]) + # check for visibility of y-axis + if xleft <= 0 <= xright: + # xaxis + a.append(["M", [coordx(0), bottom]]) + a.append(["l", [0, -height]]) + + # initialize functions and derivatives for 0; + # they are carried over from one iteration to the next, to avoid extra function calculations. + # print("RET: {}".format(f1(1))) + x0 = f1(t_start) + y0 = f2(t_start) + + # numerical derivatives, using 0.001*step as the small differential + t1 = t_start + ds # Second point AFTER first point (Good for first point) + x1 = f1(t1) + y1 = f2(t1) + dx0 = (x1 - x0) / ds + dy0 = (y1 - y0) / ds + + # Start curve + a.append(["M", [coordx(x0), coordy(y0)]]) # initial moveto + for i in range(int(samples - 1)): + t1 = (i + 1) * step + t_start + t2 = t1 - ds # Second point BEFORE first point (Good for last point) + x1 = f1(t1) + x2 = f1(t2) + y1 = f2(t1) + y2 = f2(t2) + + # numerical derivatives + dx1 = (x1 - x2) / ds + dy1 = (y1 - y2) / ds + + # create curve + a.append( + [ + "C", + [ + coordx(x0 + (dx0 * third)), + coordy(y0 + (dy0 * third)), + coordx(x1 - (dx1 * third)), + coordy(y1 - (dy1 * third)), + coordx(x1), + coordy(y1), + ], + ] + ) + t0 = t1 # Next segment's start is this segments end + x0 = x1 + y0 = y1 + dx0 = dx1 # Assume the functions are smooth everywhere, so carry over the derivatives too + dy0 = dy1 + return a + + +class ParamCurves(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument("--t_start", type=float, default=0.0, help="Start t-value") + pars.add_argument("--t_end", type=float, default=1.0, help="End t-value") + pars.add_argument( + "--times2pi", + type=inkex.Boolean, + default=True, + help="Multiply t-range by 2*pi", + ) + pars.add_argument("--xleft", type=float, default=-1.0, help="x-value of left") + pars.add_argument("--xright", type=float, default=1.0, help="x-value of right") + pars.add_argument( + "--ybottom", type=float, default=-1.0, help="y-value of bottom" + ) + pars.add_argument("--ytop", type=float, default=1.0, help="y-value of top") + pars.add_argument("-s", "--samples", type=int, default=30, help="Samples") + pars.add_argument("--fofx", default="cos(3*t)", help="fx(t) for plotting") + pars.add_argument("--fofy", default="sin(5*t)", help="fy(t) for plotting") + pars.add_argument( + "--remove", type=inkex.Boolean, default=True, help="Remove rectangle" + ) + pars.add_argument( + "--isoscale", type=inkex.Boolean, default=False, help="Isotropic scaling" + ) + pars.add_argument("--drawaxis", type=inkex.Boolean, default=False) + pars.add_argument("--tab", default="sampling") + + def effect(self): + for node in self.svg.selection: + if isinstance(node, inkex.Rectangle): + # create new path with basic dimensions of selected rectangle + newpath = inkex.PathElement() + x = float(node.get("x")) + y = float(node.get("y")) + width = float(node.get("width")) + height = float(node.get("height")) + + # copy attributes of rect + newpath.style = node.style + newpath.transform = node.transform + + # top and bottom were exchanged + newpath.path = drawfunction( + self.options.t_start, + self.options.t_end, + self.options.xleft, + self.options.xright, + self.options.ybottom, + self.options.ytop, + self.options.samples, + width, + height, + x, + y + height, + self.options.fofx, + self.options.fofy, + self.options.times2pi, + self.options.isoscale, + self.options.drawaxis, + ) + newpath.set("title", self.options.fofx + " " + self.options.fofy) + + # newpath.set('desc', '!func;' + self.options.fofx + ';' + self.options.fofy + ';' + # + `self.options.t_start` + ';' + # + `self.options.t_end` + ';' + # + `self.options.samples`) + + # add path into SVG structure + node.getparent().append(newpath) + # option whether to remove the rectangle or not. + if self.options.remove: + node.getparent().remove(node) + + +if __name__ == "__main__": + ParamCurves().run() diff --git a/share/extensions/path_envelope.inx b/share/extensions/path_envelope.inx new file mode 100644 index 0000000..d27a5cb --- /dev/null +++ b/share/extensions/path_envelope.inx @@ -0,0 +1,14 @@ + + + Envelope + org.inkscape.path.envelope + + path + + + + + + diff --git a/share/extensions/path_envelope.py b/share/extensions/path_envelope.py new file mode 100755 index 0000000..3fc263e --- /dev/null +++ b/share/extensions/path_envelope.py @@ -0,0 +1,159 @@ +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# + +import inkex +from inkex.transforms import DirectedLineSegment +from inkex.localization import inkex_gettext as _ +from operator import truediv + + +class Envelope(inkex.EffectExtension): + """Distort a path/group of paths to a second path""" + + def effect(self): + if len(self.svg.selection) != 2: + raise inkex.AbortExtension(_("You must select two objects only.")) + + obj, envelope = self.svg.selection + + if isinstance(obj, (inkex.PathElement, inkex.Group)): + if isinstance(envelope, inkex.PathElement): + # Get bounding box plus any extra composed transform of parents. + bbox = obj.bounding_box(obj.getparent().composed_transform()) + + # distill trafo into four node points + path = envelope.path.transform( + envelope.composed_transform() + ).to_superpath() + tbox = self.envelope_box_from_path(path) + else: + if isinstance(envelope, inkex.Group): + raise inkex.AbortExtension( + _( + "The second selected object is a group, not a" + " path.\nTry using Object->Ungroup." + ) + ) + raise inkex.AbortExtension( + _( + "The second selected object is not a path.\nTry using" + " the procedure Path->Object to Path." + ) + ) + else: + raise inkex.AbortExtension( + _( + "The first selected object is neither a path nor a group.\nTry using" + " the procedure Path->Object to Path." + ) + ) + + self.process_object(obj, tbox, bbox) + + def envelope_box_from_path(self, envelope_path): + if len(envelope_path) < 1 or len(envelope_path[0]) < 4: + raise inkex.AbortExtension( + _("Second selected path is too short. Must be four or more nodes.") + ) + trafo = [[(csp[1][0], csp[1][1]) for csp in subs] for subs in envelope_path][0][ + :4 + ] + # vectors pointing away from the trafo origin + tbox = [ + DirectedLineSegment(trafo[0], trafo[1]), + DirectedLineSegment(trafo[1], trafo[2]), + DirectedLineSegment(trafo[3], trafo[2]), + DirectedLineSegment(trafo[0], trafo[3]), + ] + vects = [segment.vector for segment in tbox] + if ( + 0.0 + == vects[0].cross(vects[1]) + == vects[1].cross(vects[2]) + == vects[2].cross(vects[3]) + ): + raise inkex.AbortExtension( + _("The points for the selected envelope must not all be in a line.") + ) + return tbox + + def process_object(self, obj, tbox, bbox): + if isinstance(obj, inkex.PathElement): + self.process_path(obj, tbox, bbox) + elif isinstance(obj, inkex.Group): + self.process_group(obj, tbox, bbox) + + def process_group(self, group, tbox, bbox): + """Go through all groups to process all paths inside them""" + for node in group: + self.process_object(node, tbox, bbox) + + def process_path(self, element, tbox, bbox): + # Get out path's absolute and root coordinates, so obj and envelope + # are always in the same coordinate system. + points = ( + element.path.to_absolute() + .transform(element.composed_transform()) + .to_superpath() + ) + + for subs in points: + for csp in subs: + csp[0] = self.transform_point(tbox, bbox, *csp[0]) + csp[1] = self.transform_point(tbox, bbox, *csp[1]) + csp[2] = self.transform_point(tbox, bbox, *csp[2]) + + # Put the modified path back, undo the root transformation + element.path = points.to_path().transform(-element.composed_transform()) + + @staticmethod + def transform_point(tbox, bbox, x, y): + """Transform algorithm thanks to Jose Hevia (freon)""" + vector = (x, y) - bbox.minimum + xratio, yratio = map(truediv, vector, (bbox.width, bbox.height)) + horz = DirectedLineSegment( + tbox[0].point_at_ratio(xratio), tbox[2].point_at_ratio(xratio) + ) + vert = DirectedLineSegment( + tbox[3].point_at_ratio(yratio), tbox[1].point_at_ratio(yratio) + ) + denom = horz.vector.cross(vert.vector) + if denom == 0.0: + # Degenerate cases of intersecting envelope edges + if horz.length == 0.0: + return horz.start + if vert.length == 0.0: + return vert.start + # Here we should know that the lines share a start or end point. + if horz.vector.dot(vert.vector) < 0: + # Segments point opposite directions + if (horz.start - vert.start).length <= 1e-8: + return horz.start + return horz.end + # Otherwise they are pointing the same direction + if (horz.start - vert.end).length < 1e-8: + return horz.start + return horz.end + # If we didn't hit a degenerate case we can treat the segments as infinite lines + intersect_ratio = (vert.start - horz.start).cross(vert.vector) / denom + return horz.point_at_ratio(intersect_ratio) + + +if __name__ == "__main__": + Envelope().run() diff --git a/share/extensions/path_mesh_m2p.inx b/share/extensions/path_mesh_m2p.inx new file mode 100644 index 0000000..9ce099d --- /dev/null +++ b/share/extensions/path_mesh_m2p.inx @@ -0,0 +1,37 @@ + + + Mesh-Gradient to Path + org.inkscape.meshes.mesh_to_path + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + + + diff --git a/share/extensions/path_mesh_m2p.py b/share/extensions/path_mesh_m2p.py new file mode 100755 index 0000000..cb5425b --- /dev/null +++ b/share/extensions/path_mesh_m2p.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 su_v, +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +Convert mesh gradient to path +""" + +import inkex +from inkex.elements import MeshGradient + +# globals +EPSILON = 1e-3 +MG_PROPS = ["fill", "stroke"] + + +def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): + """Test approximate equality. + + ref: + PEP 485 -- A Function for testing approximate equality + https://www.python.org/dev/peps/pep-0485/#proposed-implementation + """ + # pylint: disable=invalid-name + return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) + + +def reverse_path(csp): + """Reverse path in CSP notation.""" + rcsp = [] + for subpath in reversed(csp): + rsub = [list(reversed(cp)) for cp in reversed(subpath)] + rcsp.append(rsub) + return rcsp + + +def join_path(csp1, sp1, csp2, sp2): + """Join sub-paths *sp1* and *sp2*.""" + pt1 = csp1[sp1][-1][1] + pt2 = csp2[sp2][0][1] + if isclose(pt1[0], pt2[0], EPSILON) and isclose(pt1[1], pt2[1], EPSILON): + csp1[sp1][-1][2] = csp2[sp2][0][2] + csp1[sp1].extend(csp2[sp2][1:]) + else: + # inkex.debug('not close') + csp1.append(csp2[sp2]) + return csp1 + + +def is_url(val): + """Check whether attribute value is linked resource.""" + return val.startswith("url(#") + + +def mesh_corners(meshgradient): + """Return list of mesh patch corners, patch paths.""" + rows = len(meshgradient) + cols = len(meshgradient[0]) + # first corner of mesh gradient + corner_x = float(meshgradient.get("x", "0.0")) + corner_y = float(meshgradient.get("y", "0.0")) + # init corner and meshpatch lists + corners = [[None for _ in range(cols + 1)] for _ in range(rows + 1)] + corners[0][0] = [corner_x, corner_y] + meshpatch_csps = [] + for meshrow in range(rows): + for meshpatch in range(cols): + # get start point for current meshpatch edges + if meshrow == 0: + first_corner = corners[meshrow][meshpatch] + if meshrow > 0: + first_corner = corners[meshrow][meshpatch + 1] + # parse path of meshpatch edges + path = "M {},{}".format(*first_corner) + for edge in meshgradient[meshrow][meshpatch]: + path = " ".join([path, edge.get("path")]) + csp = inkex.Path(path).to_superpath() + # update corner list with current meshpatch + if meshrow == 0: + corners[meshrow][meshpatch + 1] = csp[0][1][1] + corners[meshrow + 1][meshpatch + 1] = csp[0][2][1] + if meshpatch == 0: + corners[meshrow + 1][meshpatch] = csp[0][3][1] + if meshrow > 0: + corners[meshrow][meshpatch + 1] = csp[0][0][1] + corners[meshrow + 1][meshpatch + 1] = csp[0][1][1] + if meshpatch == 0: + corners[meshrow + 1][meshpatch] = csp[0][2][1] + # append to list of meshpatch csp + meshpatch_csps.append(csp) + return corners, meshpatch_csps + + +def mesh_hvlines(meshgradient): + """Return lists of vertical and horizontal patch edges.""" + rows = len(meshgradient) + cols = len(meshgradient[0]) + # init lists for horizontal, vertical lines + hlines = [[None for _ in range(cols)] for _ in range(rows + 1)] + vlines = [[None for _ in range(rows)] for _ in range(cols + 1)] + for meshrow in range(rows): + for meshpatch in range(cols): + # horizontal edges + if meshrow == 0: + edge = meshgradient[meshrow][meshpatch][0] + hlines[meshrow][meshpatch] = edge.get("path") + edge = meshgradient[meshrow][meshpatch][2] + hlines[meshrow + 1][meshpatch] = edge.get("path") + if meshrow > 0: + edge = meshgradient[meshrow][meshpatch][1] + hlines[meshrow + 1][meshpatch] = edge.get("path") + # vertical edges + if meshrow == 0: + edge = meshgradient[meshrow][meshpatch][1] + vlines[meshpatch + 1][meshrow] = edge.get("path") + if meshpatch == 0: + edge = meshgradient[meshrow][meshpatch][3] + vlines[meshpatch][meshrow] = edge.get("path") + if meshrow > 0: + edge = meshgradient[meshrow][meshpatch][0] + vlines[meshpatch + 1][meshrow] = edge.get("path") + if meshpatch == 0: + edge = meshgradient[meshrow][meshpatch][2] + vlines[meshpatch][meshrow] = edge.get("path") + return hlines, vlines + + +def mesh_to_outline(corners, hlines, vlines): + """Construct mesh outline as CSP path.""" + outline_csps = [] + path = "M {},{}".format(*corners[0][0]) + for edge_path in hlines[0]: + path = " ".join([path, edge_path]) + for edge_path in vlines[-1]: + path = " ".join([path, edge_path]) + for edge_path in reversed(hlines[-1]): + path = " ".join([path, edge_path]) + for edge_path in reversed(vlines[0]): + path = " ".join([path, edge_path]) + outline_csps.append(inkex.Path(path).to_superpath()) + return outline_csps + + +def mesh_to_grid(corners, hlines, vlines): + """Construct mesh grid with CSP paths.""" + rows = len(corners) - 1 + cols = len(corners[0]) - 1 + gridline_csps = [] + # horizontal + path = "M {},{}".format(*corners[0][0]) + for edge_path in hlines[0]: + path = " ".join([path, edge_path]) + gridline_csps.append(inkex.Path(path).to_superpath()) + for i in range(1, rows + 1): + path = "M {},{}".format(*corners[i][-1]) + for edge_path in reversed(hlines[i]): + path = " ".join([path, edge_path]) + gridline_csps.append(inkex.Path(path).to_superpath()) + # vertical + path = "M {},{}".format(*corners[-1][0]) + for edge_path in reversed(vlines[0]): + path = " ".join([path, edge_path]) + gridline_csps.append(inkex.Path(path).to_superpath()) + for j in range(1, cols + 1): + path = "M {},{}".format(*corners[0][j]) + for edge_path in vlines[j]: + path = " ".join([path, edge_path]) + gridline_csps.append(inkex.Path(path).to_superpath()) + return gridline_csps + + +def mesh_to_faces(corners, hlines, vlines): + """Construct mesh faces with CSP paths.""" + rows = len(corners) - 1 + cols = len(corners[0]) - 1 + face_csps = [] + for row in range(rows): + for col in range(cols): + # init new face + face = [] + # init edge paths + edge_t = hlines[row][col] + edge_b = hlines[row + 1][col] + edge_l = vlines[col][row] + edge_r = vlines[col + 1][row] + # top edge, first + if row == 0: + path = "M {},{}".format(*corners[row][col]) + path = " ".join([path, edge_t]) + face.append(inkex.Path(path).to_superpath()[0]) + else: + path = "M {},{}".format(*corners[row][col + 1]) + path = " ".join([path, edge_t]) + face.append(reverse_path(inkex.Path(path).to_superpath())[0]) + # right edge + path = "M {},{}".format(*corners[row][col + 1]) + path = " ".join([path, edge_r]) + join_path(face, -1, inkex.Path(path).to_superpath(), 0) + # bottom edge + path = "M {},{}".format(*corners[row + 1][col + 1]) + path = " ".join([path, edge_b]) + join_path(face, -1, inkex.Path(path).to_superpath(), 0) + # left edge + if col == 0: + path = "M {},{}".format(*corners[row + 1][col]) + path = " ".join([path, edge_l]) + join_path(face, -1, inkex.Path(path).to_superpath(), 0) + else: + path = "M {},{}".format(*corners[row][col]) + path = " ".join([path, edge_l]) + join_path(face, -1, reverse_path(inkex.Path(path).to_superpath()), 0) + # append face to output list + face_csps.append(face) + return face_csps + + +class MeshToPath(inkex.EffectExtension): + """Effect extension to convert mesh geometry to path data.""" + + def add_arguments(self, pars): + pars.add_argument("--tab", help="The selected UI-tab") + pars.add_argument("--mode", default="outline", help="Edge mode") + + def process_props(self, mdict, res_type="meshgradient"): + """Process style properties of style dict *mdict*.""" + result = [] + for key, val in mdict.items(): + if key in MG_PROPS: + if is_url(val): + paint_server = self.svg.getElementById(val) + if res_type == "meshgradient" and isinstance( + paint_server, MeshGradient + ): + result.append(paint_server) + return result + + def process_style(self, node, res_type="meshgradient"): + """Process style of *node*.""" + result = node.specified_style() + result = self.process_props(result, res_type) + # TODO: check for child paint servers + return result + + def find_meshgradients(self, node): + """Parse node style, return list with linked meshgradients.""" + return self.process_style(node, res_type="meshgradient") + + # ----- Process meshgradient definitions + + def mesh_to_csp(self, meshgradient): + """Parse mesh geometry and build csp-based path data.""" + + # init variables + transform = None + mode = self.options.mode + + # gradient units + mesh_units = meshgradient.get("gradientUnits", "objectBoundingBox") + if mesh_units == "objectBoundingBox": + # TODO: position and scale based on "objectBoundingBox" units + return + + # Inkscape SVG 0.92 and SVG 2.0 draft mesh transformations + transform = meshgradient.gradientTransform @ meshgradient.transform + + # parse meshpatches, calculate absolute corner coords + corners, meshpatch_csps = mesh_corners(meshgradient) + + if mode == "meshpatches": + return meshpatch_csps, transform + else: + hlines, vlines = mesh_hvlines(meshgradient) + if mode == "outline": + return mesh_to_outline(corners, hlines, vlines), transform + elif mode == "gridlines": + return mesh_to_grid(corners, hlines, vlines), transform + elif mode == "faces": + return mesh_to_faces(corners, hlines, vlines), transform + + # ----- Convert meshgradient definitions + + def csp_to_path(self, node, csp_list, transform=None): + """Create new paths based on csp data, return group with paths.""" + # set up stroke width, group + stroke_width = self.svg.viewport_to_unit("1px") + stroke_color = "#000000" + style = { + "fill": "none", + "stroke": stroke_color, + "stroke-width": str(stroke_width), + } + + group = inkex.Group() + # apply gradientTransform and node's preserved transform to group + group.transform = transform @ node.transform + + # convert each csp to path, append to group + for csp in csp_list: + elem = group.add(inkex.PathElement()) + elem.style = style + elem.path = inkex.CubicSuperPath(csp) + if self.options.mode == "outline": + elem.path.close() + elif self.options.mode == "faces": + if len(csp) == 1 and len(csp[0]) == 5: + elem.path.close() + return group + + def effect(self): + """Main routine to convert mesh geometry to path data.""" + # loop through selection + for node in self.svg.selection.values(): + meshgradients = self.find_meshgradients(node) + # if style references meshgradient + if meshgradients: + for meshgradient in meshgradients: + csp_list = None + result = None + # parse mesh geometry + if meshgradient is not None: + csp_list, mat = self.mesh_to_csp(meshgradient) + # generate new paths with path data based on mesh geometry + if csp_list is not None: + result = self.csp_to_path(node, csp_list, mat) + # add result (group) to document + if result is not None: + index = node.getparent().index(node) + node.getparent().insert(index + 1, result) + + +if __name__ == "__main__": + MeshToPath().run() diff --git a/share/extensions/path_mesh_p2m.inx b/share/extensions/path_mesh_p2m.inx new file mode 100644 index 0000000..f8be151 --- /dev/null +++ b/share/extensions/path_mesh_p2m.inx @@ -0,0 +1,32 @@ + + + Path to Mesh-Gradient + org.inkscape.meshes.path_to_mesh + + + + + + + + + + + + + + + + all + + + + + + + + + + diff --git a/share/extensions/path_mesh_p2m.py b/share/extensions/path_mesh_p2m.py new file mode 100755 index 0000000..a346fc6 --- /dev/null +++ b/share/extensions/path_mesh_p2m.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 su_v, +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +Convert path to mesh gradient +""" + +import inkex +from inkex.paths import Line, Curve +from inkex.elements import MeshGradient + + +class PathToMesh(inkex.EffectExtension): + """Convert path data to mesh geometry.""" + + def add_arguments(self, pars): + pars.add_argument("--tab", help="The selected UI-tab") + + def add_mesh(self, meshgradient): + """Add meshgradient definition to current document.""" + self.svg.defs.append(meshgradient) + meshgradient.set_random_id("meshgradient") + return meshgradient.get_id() + + def effect(self): + """Main routine to convert path data to mesh geometry.""" + # loop through selection + for node in self.svg.selection.filter(inkex.PathElement): + csp = None + meshgradient = None + mesh_id = None + # parse path data + csp = node.path.to_superpath() + # convert csp to meshgradient definition + if csp is not None: + # TODO: check length of path data / csp + meshgradient = self.to_mesh(node, csp) + # add meshgradient to document + if meshgradient is not None: + mesh_id = self.add_mesh(meshgradient) + # apply meshgradient to node + if mesh_id is not None: + node.style["fill"] = "url(#{})".format(mesh_id) + + def to_mesh(self, node, csp, subpath=0): + """Convert csp to meshgradient geometry.""" + # mesh data + corners, edges = self.to_meshdata(csp[subpath]) + # alternating stop colors + colors = [node.style.get("fill"), "#ffffff"] + # define meshgradient with first corner as initial point + meshgradient = MeshGradient.new_mesh(pos=corners[0], rows=1, cols=1) + # define stops (stop-color, path) for first meshpatch + meshgradient[0][0].stops(edges[0:4], colors) + return meshgradient + + @staticmethod + def to_meshdata(subpath): + """Convert csp subpath to corners, edge path data.""" + if len(subpath) >= 5: + corners = [] + edges = [] + for i, corner in enumerate(subpath[:4]): + corners.append(corner[1]) + edge = [list(subpath[i]), list(subpath[i + 1])] + edge[0][0] = list(edge[0][1]) + edge[1][2] = list(edge[1][1]) + if inkex.CubicSuperPath.is_line(edge[0], edge[1]): + edges.append(Line(*edge[1][1])) + else: + edges.append(Curve(*(edge[0][2] + edge[1][0] + edge[1][1]))) + + return corners, edges + + +if __name__ == "__main__": + PathToMesh().run() diff --git a/share/extensions/path_number_nodes.inx b/share/extensions/path_number_nodes.inx new file mode 100644 index 0000000..574fd17 --- /dev/null +++ b/share/extensions/path_number_nodes.inx @@ -0,0 +1,30 @@ + + + Number Nodes + org.inkscape.filter.number_nodes + + + 20px + 10px + 1 + 1 + + + + + + + + path + + + + + + diff --git a/share/extensions/path_number_nodes.py b/share/extensions/path_number_nodes.py new file mode 100755 index 0000000..e43fce4 --- /dev/null +++ b/share/extensions/path_number_nodes.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +import math + +import inkex +from inkex import TextElement, Circle +from inkex.localization import inkex_gettext as _ + + +class NumberNodes(inkex.EffectExtension): + """Replace the selection's nodes with numbered dots according to the options""" + + def add_arguments(self, pars): + pars.add_argument( + "--dotsize", default="10px", help="Size of the dots on the path nodes" + ) + pars.add_argument("--fontsize", default="20px", help="Size of node labels") + pars.add_argument( + "--start", type=int, default=1, help="First number in the sequence" + ) + pars.add_argument( + "--step", type=int, default=1, help="Numbering step between two nodes" + ) + pars.add_argument("--tab", help="The selected UI-tab when OK was pressed") + + def effect(self): + filtered = self.svg.selection.filter(inkex.PathElement) + if not filtered: + raise inkex.AbortExtension(_("Please select at least one path object.")) + for node in filtered: + self.add_dot(node) + + def add_dot(self, node: inkex.PathElement): + """Add a dot label for this path element""" + group: inkex.Group = node.getparent().add(inkex.Group()) + dot_group = group.add(inkex.Group()) + num_group = group.add(inkex.Group()) + path_trans_applied = node.path.transform(node.composed_transform()) + group.transform = -node.getparent().composed_transform() + + style = inkex.Style({"stroke": "none", "fill": "#000"}) + + for step, (x, y) in enumerate(path_trans_applied.end_points): + circle = dot_group.add( + Circle( + cx=str(x), + cy=str(y), + r=str(self.svg.unittouu(self.options.dotsize) / 2), + ) + ) + circle.style = style + num_group.append( + self.add_text( + x + (self.svg.unittouu(self.options.dotsize) / 2), + y - (self.svg.unittouu(self.options.dotsize) / 2), + self.options.start + (self.options.step * step), + ) + ) + + node.delete() + + def add_text(self, x, y, text): + """Add a text label at the given location""" + elem = TextElement(x=str(x), y=str(y)) + elem.text = str(text) + elem.style = { + "font-size": self.svg.unittouu(self.options.fontsize), + "fill-opacity": "1.0", + "stroke": "none", + "font-weight": "normal", + "font-style": "normal", + "fill": "#999", + } + return elem + + +if __name__ == "__main__": + NumberNodes().run() diff --git a/share/extensions/path_to_absolute.inx b/share/extensions/path_to_absolute.inx new file mode 100644 index 0000000..b324b6d --- /dev/null +++ b/share/extensions/path_to_absolute.inx @@ -0,0 +1,14 @@ + + + To Absolute + org.inkscape.path.to_absolute + + all + + + + + + diff --git a/share/extensions/path_to_absolute.py b/share/extensions/path_to_absolute.py new file mode 100755 index 0000000..e2f0d88 --- /dev/null +++ b/share/extensions/path_to_absolute.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2020 Martin Owens +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +Path To Absolute +""" +import inkex + + +class ToAbsolute(inkex.EffectExtension): + """Convert any selected object to absolute/object-to-path/bezier only paths""" + + def effect(self): + """Performs the effect.""" + for node in self.svg.selection.values(): + if not isinstance(node, inkex.PathElement): + node = node.replace_with(node.to_path_element()) + node.path = node.path.to_absolute().to_superpath().to_path() + + +if __name__ == "__main__": + ToAbsolute().run() diff --git a/share/extensions/pathalongpath.inx b/share/extensions/pathalongpath.inx new file mode 100644 index 0000000..732a725 --- /dev/null +++ b/share/extensions/pathalongpath.inx @@ -0,0 +1,42 @@ + + + Pattern along Path + org.inkscape.generate.path_along_path + pathmodifier.py + + + + + + + + + + + + + 0.0 + 0.0 + 0.0 + false + true + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/pathalongpath.py b/share/extensions/pathalongpath.py new file mode 100755 index 0000000..9c4bac5 --- /dev/null +++ b/share/extensions/pathalongpath.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# +# Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +# 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# barraud@math.univ-lille1.fr +# +""" +This script deforms an object (the pattern) along other paths (skeletons)... +The first selected object is the pattern +the last selected ones are the skeletons. + +Imagine a straight horizontal line L in the middle of the bounding box of the pattern. +Consider the normal bundle of L: the collection of all the vertical lines meeting L. +Consider this as the initial state of the plane; in particular, think of the pattern +as painted on these lines. + +Now move and bend L to make it fit a skeleton, and see what happens to the normals: +they move and rotate, deforming the pattern. +""" +import copy +import math + +import inkex +from inkex.bezier import tpoint +from inkex.paths import CubicSuperPath +from inkex.localization import inkex_gettext as _ + +import pathmodifier + + +class PathAlongPath(pathmodifier.PathModifier): + """Deform a path along a second path""" + + def add_arguments(self, pars): + pars.add_argument( + "-n", "--noffset", type=float, default=0.0, help="normal offset" + ) + pars.add_argument( + "-t", "--toffset", type=float, default=0.0, help="tangential offset" + ) + pars.add_argument("-k", "--kind", type=str, default="") + pars.add_argument( + "-c", + "--copymode", + default="Single", + help="repeat the path to fit deformer's length", + ) + pars.add_argument("-p", "--space", type=float, default=0.0) + pars.add_argument( + "-v", + "--vertical", + type=inkex.Boolean, + default=False, + help="reference path is vertical", + ) + pars.add_argument( + "-d", + "--duplicate", + type=inkex.Boolean, + default=True, + help="duplicate pattern before deformation", + ) + pars.add_argument("--tab", help="The selected UI-tab when OK was pressed") + + def apply_diffeomorphism(self, bpt, skelcomp, lengths, isclosed, vects=()): + """ + The kernel of this stuff: + bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. + """ + s = bpt[0] - skelcomp[0][0] + i, t = self.lengthtotime(s, lengths, isclosed) + if i == len(skelcomp) - 1: + x, y = tpoint(skelcomp[i - 1], skelcomp[i], 1 + t) + dx = (skelcomp[i][0] - skelcomp[i - 1][0]) / lengths[-1] + dy = (skelcomp[i][1] - skelcomp[i - 1][1]) / lengths[-1] + else: + x, y = tpoint(skelcomp[i], skelcomp[i + 1], t) + dx = (skelcomp[i + 1][0] - skelcomp[i][0]) / lengths[i] + dy = (skelcomp[i + 1][1] - skelcomp[i][1]) / lengths[i] + + vx = 0 + vy = bpt[1] - skelcomp[0][1] + if self.options.wave: + bpt[0] = x + vx * dx + bpt[1] = y + vy + vx * dy + else: + bpt[0] = x + vx * dx - vy * dy + bpt[1] = y + vx * dy + vy * dx + + for v in vects: + vx = v[0] - skelcomp[0][0] - s + vy = v[1] - skelcomp[0][1] + if self.options.wave: + v[0] = x + vx * dx + v[1] = y + vy + vx * dy + else: + v[0] = x + vx * dx - vy * dy + v[1] = y + vx * dy + vy * dx + + def effect(self): + if len(self.options.ids) < 2: + raise inkex.AbortExtension(_("This extension requires two selected paths.")) + + self.options.wave = self.options.kind == "Ribbon" + if self.options.copymode == "Single": + self.options.repeat = False + self.options.stretch = False + elif self.options.copymode == "Repeated": + self.options.repeat = True + self.options.stretch = False + elif self.options.copymode == "Single, stretched": + self.options.repeat = False + self.options.stretch = True + elif self.options.copymode == "Repeated, stretched": + self.options.repeat = True + self.options.stretch = True + + patterns, skels = self.get_patterns_and_skeletons(True, self.options.duplicate) + bboxes = [pattern.bounding_box() for pattern in patterns.values()] + if None in bboxes: # for texts, we can't compute the bounding box + raise inkex.AbortExtension(_("Please convert texts to path first")) + bbox = sum(bboxes, None) + + if self.options.vertical: + # flipxy(bbox)... + bbox = inkex.BoundingBox(-bbox.y, -bbox.x) + + width = bbox.width + delta_x = width + self.options.space + if delta_x < 0.01: + raise inkex.AbortExtension( + _( + "The total length of the pattern is too small\n" + "Please choose a larger object or set 'Space between copies' > 0" + ) + ) + for pattern in patterns.values(): + if isinstance(pattern, inkex.PathElement): + pattern.apply_transform() + pattern.path = self._do_transform( + skels, pattern.path.to_superpath(), delta_x, bbox + ) + + def _do_transform(self, skeletons, p0, dx, bbox): + if self.options.vertical: + self.flipxy(p0) + newp = [] + for skelnode in skeletons.values(): + skelnode.apply_transform() + cur_skeleton = skelnode.path.to_superpath() + if self.options.vertical: + self.flipxy(cur_skeleton) + for comp in cur_skeleton: + path = copy.deepcopy(p0) + skelcomp, lengths = self.linearize(comp) + + skel_closed = all( + [math.isclose(i, j) for i, j in zip(skelcomp[0], skelcomp[-1])] + ) + + length = sum(lengths) + xoffset = skelcomp[0][0] - bbox.x.minimum + self.options.toffset + yoffset = skelcomp[0][1] - bbox.y.center - self.options.noffset + if self.options.repeat: + nb_copies = max(1, int(round((length + self.options.space) / dx))) + width = dx * nb_copies + if not skel_closed: + width -= self.options.space + bbox.x.maximum = bbox.x.minimum + width + new = [] + for sub in path: + for _ in range(nb_copies): + new.append(copy.deepcopy(sub)) + self.offset(sub, dx, 0) + path = new + + for sub in path: + self.offset(sub, xoffset, yoffset) + + if self.options.stretch: + if not bbox.width: + raise inkex.AbortExtension( + _( + "The 'stretch' option requires that the pattern must " + "have non-zero width :\nPlease edit the pattern width." + ) + ) + for sub in path: + self.stretch(sub, length / bbox.width, 1, skelcomp[0]) + + for sub in path: + for ctlpt in sub: + self.apply_diffeomorphism( + ctlpt[1], + skelcomp, + lengths, + skel_closed, + (ctlpt[0], ctlpt[2]), + ) + + if self.options.vertical: + self.flipxy(path) + newp += path + return CubicSuperPath(newp) + + +if __name__ == "__main__": + PathAlongPath().run() diff --git a/share/extensions/pathmodifier.py b/share/extensions/pathmodifier.py new file mode 100755 index 0000000..e99b4b5 --- /dev/null +++ b/share/extensions/pathmodifier.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +# 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# barraud@math.univ-lille1.fr +# +""" +This code defines a basic class (PathModifier) of effects whose purpose is +to somehow deform given objects: one common tasks for all such effect is to +convert shapes, groups, clones to paths. The class has several functions to +make this (more or less!) easy. +As an example, a second class (Diffeo) is derived from it, +to implement deformations of the form X=f(x,y), Y=g(x,y)... +""" + +import inkex +from inkex import PathElement, Group, Use +from inkex.bezier import pointdistance, beziersplitatt + +# This deprecated API is used by some external extensions. +from inkex.deprecated import zSort # pylint: disable=unused-import + + +class PathModifier(inkex.EffectExtension): + """Select list manipulation""" + + def expand_groups(self, elements, transferTransform=True): + for node_id, node in list(elements.items()): + if isinstance(node, inkex.Group): + mat = node.transform + for child in node: + if transferTransform: + child.transform = mat @ child.transform + elements.update(self.expand_groups({child.get("id"): child})) + if transferTransform and node.get("transform"): + del node.attrib["transform"] + # Group is now replaced, so remove it. + elements.pop(node_id) + return elements + + def expand_clones(self, elements, transferTransform=True, replace=True): + for node_id, node in list(elements.items()): + if isinstance(node, Group): + self.expand_groups(elements, transferTransform) + self.expand_clones(elements, transferTransform, replace) + # Hum... not very efficient if there are many clones of groups... + + elif isinstance(node, Use): + newnode = node.unlink() + elements.pop(node_id) + newid = newnode.get("id") + elements.update( + self.expand_clones({newid: newnode}, transferTransform, replace) + ) + return elements + + def objects_to_paths(self, elements, replace=True): + """Replace all non-paths with path objects""" + for node in list(elements.values()): + elem = node.to_path_element() + if replace: + node.replace_with(elem) + elem.set("id", node.get("id")) + elements[elem.get("id")] = elem + + def effect(self): + raise NotImplementedError("overwrite this method in subclasses") + self.objects_to_paths(self.svg.selection, True) + self.bbox = self.svg.selection.bounding_box() + for node in self.svg.selection.filter(PathElement): + path = node.path.to_superpath() + # do what ever you want with "path"! + node.path = path + + @staticmethod + def lengthtotime(l, lengths, isclosed): + """ + Receives an arc length l, and returns the index of the segment in skelcomp + containing the corresponding point, to gether with the position of the point on this segment. + + If the deformer is closed, do computations modulo the toal length. + """ + if isclosed: + l = l % sum(lengths) + if l <= 0: + return 0, l / lengths[0] + i = 0 + while (i < len(lengths)) and (lengths[i] <= l): + l -= lengths[i] + i += 1 + t = l / lengths[min(i, len(lengths) - 1)] + return i, t + + @staticmethod + def flipxy(path): + """Swaps x and y coordinate of all path vertices""" + for pathcomp in path: + for ctl in pathcomp: + for pt in ctl: + tmp = pt[0] + pt[0] = -pt[1] + pt[1] = -tmp + + @staticmethod + def offset(pathcomp, dx, dy): + """Shifts a subpath by (dx, dy)""" + for ctl in pathcomp: + for pt in ctl: + pt[0] += dx + pt[1] += dy + + @staticmethod + def stretch(pathcomp, xscale, yscale, org): + """Stretches a subpath by (xscale, yscale) relative to origin org""" + for ctl in pathcomp: + for pt in ctl: + pt[0] = org[0] + (pt[0] - org[0]) * xscale + pt[1] = org[1] + (pt[1] - org[1]) * yscale + + @staticmethod + def linearize(p, tolerance=0.001): + """ + This function receives a component of a 'cubicsuperpath' and returns two things: + The path subdivided in many straight segments, and an array containing the length of each segment. + + We could work with bezier path as well, but bezier arc lengths are (re)computed for each point + in the deformed object. For complex paths, this might take a while. + """ + zero = 0.000001 + i = 0 + d = 0 + lengths = [] + while i < len(p) - 1: + box = pointdistance(p[i][1], p[i][2]) + box += pointdistance(p[i][2], p[i + 1][0]) + box += pointdistance(p[i + 1][0], p[i + 1][1]) + chord = pointdistance(p[i][1], p[i + 1][1]) + if (box - chord) > tolerance: + b1, b2 = beziersplitatt( + [p[i][1], p[i][2], p[i + 1][0], p[i + 1][1]], 0.5 + ) + p[i][2][0], p[i][2][1] = b1[1] + p[i + 1][0][0], p[i + 1][0][1] = b2[2] + p.insert( + i + 1, + [[b1[2][0], b1[2][1]], [b1[3][0], b1[3][1]], [b2[1][0], b2[1][1]]], + ) + else: + d = (box + chord) / 2 + lengths.append(d) + i += 1 + new = [p[i][1] for i in range(0, len(p) - 1) if lengths[i] > zero] + new.append(p[-1][1]) + lengths = [l for l in lengths if l > zero] + return new, lengths + + def get_patterns_and_skeletons(self, expand_patterns=False, duplicate=False): + """Gets the pattern node and skeleton (with applied transforms) from selection""" + # first selected->pattern, all but first selected-> skeletons + skeletons = self.svg.selection.rendering_order() + + elem = skeletons.pop() + if duplicate: + elem = elem.duplicate() + + if expand_patterns: + patterns = {elem.get_id(): elem} + self.expand_clones(patterns, True, False) + self.objects_to_paths(patterns) + else: + patterns = elem + + self.expand_clones(skeletons, True, False) + self.objects_to_paths(skeletons) + return patterns, skeletons.id_dict() + + +class Diffeo(PathModifier): + def applyDiffeo(self, bpt, vects=()): + # bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. + # Defaults to identity! + for v in vects: + v[0] -= bpt[0] + v[1] -= bpt[1] + + # -- your transformations go here: + # x,y=bpt + # bpt[0]=f(x,y) + # bpt[1]=g(x,y) + # for v in vects: + # vx,vy=v + # v[0]=df/dx(x,y)*vx+df/dy(x,y)*vy + # v[1]=dg/dx(x,y)*vx+dg/dy(x,y)*vy + # + # -- !caution! y-axis is pointing downward! + + for v in vects: + v[0] += bpt[0] + v[1] += bpt[1] + + def effect(self): + self.expand_clones(self.svg.selection, True) + self.expand_groups(self.svg.selection, True) + self.objects_to_paths(self.svg.selection, True) + self.bbox = self.svg.selection.bounding_box() + for node in self.svg.selection.filter(PathElement): + path = node.path.to_superpath() + for sub in path: + for ctlpt in sub: + self.applyDiffeo(ctlpt[1], (ctlpt[0], ctlpt[2])) + node.path = path diff --git a/share/extensions/pathscatter.inx b/share/extensions/pathscatter.inx new file mode 100644 index 0000000..18893ee --- /dev/null +++ b/share/extensions/pathscatter.inx @@ -0,0 +1,38 @@ + + + Scatter + org.inkscape.path.path_scatter + pathmodifier.py + + + true + false + 0.0 + 0.0 + 0.0 + false + + + + + + false + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/pathscatter.py b/share/extensions/pathscatter.py new file mode 100755 index 0000000..7ffee63 --- /dev/null +++ b/share/extensions/pathscatter.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +# 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# barraud@math.univ-lille1.fr +""" +This script scatters an object (the pattern) along other paths (skeletons)... +The topmost selected object is the pattern +the other selected ones are the skeletons. + +No deformation is applied to the pattern itself. +""" +import random +import math + +import inkex +from inkex import bezier, Transform, BoundingBox, Group, Use +from inkex.localization import inkex_gettext as _ + +import pathmodifier + + +class PathScatter(pathmodifier.Diffeo): + def __init__(self): + super(PathScatter, self).__init__() + self.arg_parser.add_argument( + "-n", + "--noffset", + type=float, + dest="noffset", + default=0.0, + help="normal offset", + ) + self.arg_parser.add_argument( + "-t", + "--toffset", + type=float, + dest="toffset", + default=0.0, + help="tangential offset", + ) + self.arg_parser.add_argument( + "-g", + "--grouppick", + type=inkex.Boolean, + dest="grouppick", + default=False, + help="if pattern is a group then randomly pick group members", + ) + self.arg_parser.add_argument( + "-m", + "--pickmode", + type=str, + dest="pickmode", + default="rand", + help="group pick mode (rand=random seq=sequentially)", + ) + self.arg_parser.add_argument( + "-f", + "--follow", + type=inkex.Boolean, + dest="follow", + default=True, + help="choose between wave or snake effect", + ) + self.arg_parser.add_argument( + "-s", + "--stretch", + type=inkex.Boolean, + dest="stretch", + default=False, + help="repeat the path to fit deformer's length", + ) + self.arg_parser.add_argument( + "-p", "--space", type=float, dest="space", default=0.0 + ) + self.arg_parser.add_argument( + "-r", + "--rotate", + type=inkex.Boolean, + dest="vertical", + default=False, + help="reference path is vertical", + ) + self.arg_parser.add_argument( + "-c", + "--copymode", + type=str, + dest="copymode", + default="move", + help="""How the pattern is duplicated. Default: 'move', + Options: 'clone', 'duplicate', 'move'""", + ) + self.arg_parser.add_argument( + "--tab", + type=str, + dest="tab", + help="The selected UI-tab when OK was pressed", + ) + + def localTransformAt(self, s, skelcomp, lengths, isclosed, follow=True): + """ + receives a length, and returns the corresponding point and tangent of skelcomp + if follow is set to false, returns only the translation + """ + i, t = self.lengthtotime(s, lengths, isclosed) + if i == len(skelcomp) - 1: + x, y = bezier.between_point(skelcomp[i - 1], skelcomp[i], 1 + t) + dx = (skelcomp[i][0] - skelcomp[i - 1][0]) / lengths[-1] + dy = (skelcomp[i][1] - skelcomp[i - 1][1]) / lengths[-1] + else: + x, y = bezier.between_point(skelcomp[i], skelcomp[i + 1], t) + dx = (skelcomp[i + 1][0] - skelcomp[i][0]) / lengths[i] + dy = (skelcomp[i + 1][1] - skelcomp[i][1]) / lengths[i] + if follow: + mat = [[dx, -dy, x], [dy, dx, y]] + else: + mat = [[1, 0, x], [0, 1, y]] + return Transform(mat) + + def center_node_at_origin(self, node): + """Translates a node to the origin and applies translation if requested""" + bbox = node.bounding_box() + mat = Transform([[1, 0, -bbox.center.x], [0, 1, -bbox.center.y]]) + if self.options.vertical: + bbox = BoundingBox(-bbox.y, -bbox.x) + mat = Transform([[0, -1, 0], [1, 0, 0]]) @ mat + mat.add_translate([0, self.options.noffset]) + node.transform = mat @ node.transform + return bbox + + def effect(self): + + if len(self.svg.selection) < 2: + inkex.errormsg(_("This extension requires two selected paths.")) + return + original_pattern_node, skeletons = self.get_patterns_and_skeletons(False, False) + + g_node = Group() + original_pattern_node.getparent().append(g_node) + + if self.options.copymode == "clone": + pattern_node = g_node.add(Use()) + pattern_node.href = original_pattern_node + else: + pattern_node = original_pattern_node.duplicate() + + # We will later compute transforms relative to the origin + bbox = self.center_node_at_origin(pattern_node) + + width = bbox.width + dx = width + self.options.space + if dx < 0.01: + if isinstance(original_pattern_node, inkex.TextElement): + raise inkex.AbortExtension(_("Please convert texts to path first")) + raise inkex.AbortExtension( + _( + "The total length of the pattern is too small\n" + "Please choose a larger object or set 'Space between copies' > 0" + ) + ) + + # check if group and expand it + pattern_list = [] + if self.options.grouppick and isinstance(pattern_node, Group): + mat = pattern_node.transform + for child in pattern_node: + child.transform = mat @ child.transform + pattern_list.append(child) + else: + pattern_list.append(pattern_node) + + self._do_transform(skeletons, width, pattern_list, g_node) + + if self.options.copymode == "move": + original_pattern_node.getparent().remove(original_pattern_node) + # pattern_node was just a temporary copy, definitely remove this + pattern_node.getparent().remove(pattern_node) + + def _do_transform(self, skeletons, width, pattern_list, g_node): + counter = 0 + for skelnode in skeletons.values(): + skelnode.apply_transform() + cur_skeleton = skelnode.path.to_superpath() + for comp in cur_skeleton: + skelcomp, lengths = self.linearize(comp) + skel_closed = all( + [math.isclose(i, j) for i, j in zip(skelcomp[0], skelcomp[-1])] + ) + + length = sum(lengths) + dx = width + self.options.space + if self.options.stretch: + n = int((length + self.options.space) / dx) + if n > 0: + dx = (length) / n + + s = 0 if self.options.stretch else self.options.toffset * 0.01 * dx + while s <= length: + local_transform = self.localTransformAt( + s, skelcomp, lengths, skel_closed, self.options.follow + ) + + pattern_idx = ( + random.randint(0, len(pattern_list) - 1) + if self.options.pickmode == "rand" + else counter % len(pattern_list) + ) + + clone = pattern_list[pattern_idx].copy() + + g_node.append(clone) + + clone.transform = local_transform @ clone.transform + s += dx + counter += 1 + + +if __name__ == "__main__": + PathScatter().run() diff --git a/share/extensions/pdflatex.inx b/share/extensions/pdflatex.inx new file mode 100644 index 0000000..67425c4 --- /dev/null +++ b/share/extensions/pdflatex.inx @@ -0,0 +1,33 @@ + + + Formula (pdflatex) + org.inkscape.generate.pdf_latex + pdflatex + + + + \(\displaystyle\frac{\pi^2}{6}=\lim_{n \to \infty}\sum_{k=1}^n \frac{1}{k^2}\) + 10 + + + true + \usepackage{amsmath}\usepackage{amssymb}\usepackage{amsfonts} + + + + + + all + + + + + + diff --git a/share/extensions/pdflatex.py b/share/extensions/pdflatex.py new file mode 100755 index 0000000..f989191 --- /dev/null +++ b/share/extensions/pdflatex.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2019 Marc Jeanmougin +# +# 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 +# +""" +Generate Latex via a PDF using pdflatex +""" + +import os + +import inkex +from inkex.base import TempDirMixin +from inkex.command import ProgramRunError, call, inkscape +from inkex import load_svg, ShapeElement, Defs +from inkex.units import convert_unit +from inkex.localization import inkex_gettext as _ + + +class PdfLatex(TempDirMixin, inkex.GenerateExtension): + """ + Use pdflatex to generate LaTeX, this whole hack is required because + we don't want to open a LaTeX document as a document, but as a + generated fragment (like import, but done manually). + """ + + def add_arguments(self, pars): + pars.add_argument( + "--formule", + type=str, + default=r"\(\displaystyle\frac{\pi^2}{6}=\lim_{n \to \infty}\sum_{k=1}^n \frac{1}{k^2}\)", + ) + pars.add_argument( + "--preamble", + type=str, + default="".join( + f"\\usepackage{{ams{i}}}" for i in ["math", "symb", "fonts"] + ), + ) + pars.add_argument("--font_size", type=int, default=10) + pars.add_argument("--page", choices=["basic", "advanced"]) + pars.add_argument("--standalone", type=inkex.Boolean, default=True) + + def generate(self): + tex_file = os.path.join(self.tempdir, "input.tex") + pdf_file = os.path.join(self.tempdir, "input.pdf") # Auto-generate by pdflatex + svg_file = os.path.join(self.tempdir, "output.svg") + + with open(tex_file, "w") as fhl: + self.write_latex(fhl) + + try: + call( + "pdflatex", + tex_file, + output_directory=self.tempdir, + halt_on_error=True, + oldie=True, + ) + except ProgramRunError as err: + inkex.errormsg(_("An exception occurred during LaTeX compilation: ") + "\n") + inkex.errormsg(err.stdout.decode("utf8").replace("\r\n", "\n")) + raise inkex.AbortExtension() + + inkscape( + pdf_file, + export_filename=svg_file, + pdf_page=1, + pdf_poppler=True, + export_type="svg", + actions=( + "select-all;page-fit-to-selection;" + "clone-unlink-recursively;vacuum-defs" + ), + ) + + if not os.path.isfile(svg_file): + fn = os.path.basename(svg_file) + if os.path.isfile(fn): + # Inkscape bug detected, file got saved wrong + svg_file = fn + + with open(svg_file, "r") as fhl: + svg: inkex.SvgDocumentElement = load_svg(fhl).getroot() + + scale = convert_unit("1pt", "px") / self.svg.scale + if not self.options.standalone: + scale *= self.options.font_size / 10 + + for child in svg: + if isinstance(child, ShapeElement): + child.transform = inkex.Transform(scale=scale) @ child.transform + yield child + elif isinstance(child, Defs): + for def_child in child: + # The ids of both the imported and the target document should + # be off-limits + def_child.set_random_ids( + backlinks=True, blacklist=self.svg.get_ids() + ) + self.svg.defs.append(def_child) + + def write_latex(self, stream): + """Takes a formula and wraps it in latex""" + if self.options.standalone: + docclass = ( + f"\\documentclass[fontsize={self.options.font_size}pt, " + + "class=scrreprt, preview]{standalone}" + ) + else: + docclass = r"\documentclass{minimal}" + stream.write( + f"""%% processed with pdflatex.py +{docclass} +{self.options.preamble} +\\begin{{document}} +{self.options.formule} +\\end{{document}} +""" + ) + stream.flush() + + +if __name__ == "__main__": + PdfLatex().run() diff --git a/share/extensions/perfectboundcover.inx b/share/extensions/perfectboundcover.inx new file mode 100644 index 0000000..69ed244 --- /dev/null +++ b/share/extensions/perfectboundcover.inx @@ -0,0 +1,41 @@ + + + Perfect-Bound Cover Template + org.inkscape.effects.perfect_bound_cover + + 6 + 9 + 64 + true + + + + + + + + + 0 + + + + + + + + + 0 + .25 + + + all + + + + + + + + diff --git a/share/extensions/perfectboundcover.py b/share/extensions/perfectboundcover.py new file mode 100755 index 0000000..b223364 --- /dev/null +++ b/share/extensions/perfectboundcover.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 John Bintz, jcoswell@cosellproductions.org +# +# 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. +# +""" +Greate perfect bound cover +""" +import textwrap + +import inkex +from inkex import Guide + + +def caliper_to_ppi(caliper): + return 2 / caliper + + +def bond_weight_to_ppi(bond_weight): + return caliper_to_ppi(bond_weight * 0.0002) + + +def points_to_ppi(points): + return caliper_to_ppi(points / 1000.0) + + +class PerfectBoundCover(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument("--width", type=float, default=6.0, help="cover width (in)") + pars.add_argument("--height", type=float, default=9.0, help="cover height (in)") + pars.add_argument("--pages", type=int, default=64, help="number of pages") + pars.add_argument( + "--paperthicknessmeasurement", + default="ppi", + help="""Measurement for determining the thickness of the spine. + Options: 'ppi': pages per inch; 'caliper': caliper (inches); + 'points': caliper in points (1/1000 in); + 'bond_weight': Bond (pounds); + 'width': absolute width of spine (in)""", + ) + pars.add_argument( + "--paperthickness", type=float, default=0.0, help="paper thickness" + ) + pars.add_argument( + "--coverthicknessmeasurement", + default="ppi", + help="Measurement for determining the thickness of the cover. For " + "available options, see --paperthicknessmeasurement", + ) + pars.add_argument( + "--coverthickness", type=float, default=0.0, help="cover thickness" + ) + pars.add_argument("--bleed", type=float, default=0.25, help="cover bleed (in)") + pars.add_argument( + "--removeguides", type=inkex.Boolean, default=False, help="remove guide" + ) + + def effect(self): + switch = { + "ppi": lambda x: x, + "caliper": caliper_to_ppi, + "bond_weight": bond_weight_to_ppi, + "points": points_to_ppi, + "width": lambda x: x, + } + + if self.options.paperthickness > 0: + if self.options.paperthicknessmeasurement == "width": + paper_spine = self.options.paperthickness + else: + paper_spine = self.options.pages / switch[ + self.options.paperthicknessmeasurement + ](self.options.paperthickness) + else: + paper_spine = 0 + + if self.options.coverthickness > 0: + if self.options.coverthicknessmeasurement == "width": + cover_spine = self.options.coverthickness + else: + cover_spine = 4.0 / switch[self.options.coverthicknessmeasurement]( + self.options.coverthickness + ) + else: + cover_spine = 0 + + spine_width = paper_spine + cover_spine + + document_width = (self.options.bleed + self.options.width * 2) + spine_width + document_height = self.options.bleed * 2 + self.options.height + + root = self.document.getroot() + + root.set("width", "%sin" % document_width) + root.set("height", "%sin" % document_height) + + guides = [] + + guides.append(["horizontal", self.options.bleed]) + guides.append(["horizontal", document_height - self.options.bleed]) + guides.append(["vertical", self.options.bleed]) + guides.append(["vertical", document_width - self.options.bleed]) + guides.append(["vertical", (document_width / 2) - (spine_width / 2)]) + guides.append(["vertical", (document_width / 2) + (spine_width / 2)]) + + namedview = self.svg.namedview + if namedview is not None: + if self.options.removeguides: + for node in namedview.get_guides(): + node.delete() + for guide in guides: + newguide = namedview.add(Guide()) + newguide.set("orientation", guide[0]) + newguide.set("position", "%f" % (guide[1] * 96)) + + +if __name__ == "__main__": + PerfectBoundCover().run() diff --git a/share/extensions/perspective.inx b/share/extensions/perspective.inx new file mode 100644 index 0000000..35775a2 --- /dev/null +++ b/share/extensions/perspective.inx @@ -0,0 +1,14 @@ + + + Perspective + org.ekips.filter.perspective + + path + + + + + + diff --git a/share/extensions/perspective.py b/share/extensions/perspective.py new file mode 100755 index 0000000..940e42e --- /dev/null +++ b/share/extensions/perspective.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +""" +Perspective approach & math by Dmitry Platonov, shadowjack@mail.ru, 2006 +""" + +import inkex +from inkex.localization import inkex_gettext as _ + +X, Y = range(2) + +try: + import numpy as np + import numpy.linalg as lin + + FLOAT = np.float64 +except ImportError: + np = None + + +class Perspective(inkex.EffectExtension): + """Apply a perspective to a path/group of paths""" + + def effect(self): + if np is None: + raise inkex.AbortExtension( + _( + "Failed to import the numpy or numpy.linalg modules. " + "These modules are required by this extension. Please install them." + " On a Debian-like system this can be done with the command, " + "sudo apt-get install python-numpy." + ) + ) + if len(self.svg.selection) != 2: + raise inkex.AbortExtension( + _("This extension requires two selected objects.") + ) + + obj, envelope = self.svg.selection + + if isinstance(obj, (inkex.PathElement, inkex.Group)): + if isinstance(envelope, inkex.PathElement): + path = envelope.path.transform( + envelope.composed_transform() + ).to_superpath() + + if len(path) < 1 or len(path[0]) < 4: + raise inkex.AbortExtension( + _( + "This extension requires that the second path be four " + "nodes long." + ) + ) + + dip = np.zeros((4, 2), dtype=FLOAT) + for i in range(4): + dip[i][0] = path[0][i][1][0] + dip[i][1] = path[0][i][1][1] + + # Get bounding box plus any extra composed transform of parents. + bbox = obj.bounding_box(obj.getparent().composed_transform()) + + sip = np.array( + [ + [bbox.left, bbox.bottom], + [bbox.left, bbox.top], + [bbox.right, bbox.top], + [bbox.right, bbox.bottom], + ], + dtype=FLOAT, + ) + else: + if isinstance(envelope, inkex.Group): + raise inkex.AbortExtension( + _( + "The second selected object is a group, not a" + " path.\nTry using Object->Ungroup." + ) + ) + raise inkex.AbortExtension( + _( + "The second selected object is not a path.\nTry using" + " the procedure Path->Object to Path." + ) + ) + else: + raise inkex.AbortExtension( + _( + "The first selected object is neither a path nor a group.\nTry " + "using the procedure Path->Object to Path." + ) + ) + + solmatrix = np.zeros((8, 8), dtype=FLOAT) + free_term = np.zeros(8, dtype=FLOAT) + for i in (0, 1, 2, 3): + solmatrix[i][0] = sip[i][0] + solmatrix[i][1] = sip[i][1] + solmatrix[i][2] = 1 + solmatrix[i][6] = -dip[i][0] * sip[i][0] + solmatrix[i][7] = -dip[i][0] * sip[i][1] + solmatrix[i + 4][3] = sip[i][0] + solmatrix[i + 4][4] = sip[i][1] + solmatrix[i + 4][5] = 1 + solmatrix[i + 4][6] = -dip[i][1] * sip[i][0] + solmatrix[i + 4][7] = -dip[i][1] * sip[i][1] + free_term[i] = dip[i][0] + free_term[i + 4] = dip[i][1] + + res = lin.solve(solmatrix, free_term) + projmatrix = np.array( + [[res[0], res[1], res[2]], [res[3], res[4], res[5]], [res[6], res[7], 1.0]], + dtype=FLOAT, + ) + + self.process_object(obj, projmatrix) + + def process_object(self, obj, matrix): + if isinstance(obj, inkex.PathElement): + self.process_path(obj, matrix) + elif isinstance(obj, inkex.Group): + self.process_group(obj, matrix) + + def process_group(self, group, matrix): + """Go through all groups to process all paths inside them""" + for node in group: + self.process_object(node, matrix) + + def process_path(self, element, matrix): + """Apply the transformation to the selected path""" + point = ( + element.path.to_absolute() + .transform(element.composed_transform()) + .to_superpath() + ) + for subs in point: + for csp in subs: + csp[0] = self.project_point(csp[0], matrix) + csp[1] = self.project_point(csp[1], matrix) + csp[2] = self.project_point(csp[2], matrix) + element.path = inkex.Path(point).transform(-element.composed_transform()) + + @staticmethod + def project_point(point, matrix): + """Apply the matrix to the given point""" + return [ + (point[X] * matrix[0][0] + point[Y] * matrix[0][1] + matrix[0][2]) + / (point[X] * matrix[2][0] + point[Y] * matrix[2][1] + matrix[2][2]), + (point[X] * matrix[1][0] + point[Y] * matrix[1][1] + matrix[1][2]) + / (point[X] * matrix[2][0] + point[Y] * matrix[2][1] + matrix[2][2]), + ] + + +if __name__ == "__main__": + Perspective().run() diff --git a/share/extensions/pixelsnap.inx b/share/extensions/pixelsnap.inx new file mode 100644 index 0000000..a9c3203 --- /dev/null +++ b/share/extensions/pixelsnap.inx @@ -0,0 +1,24 @@ + + + PixelSnap + org.inkscape.filter.pixel_snap + + + true + true + + 0.5 + + + + + + all + + + + + + diff --git a/share/extensions/pixelsnap.py b/share/extensions/pixelsnap.py new file mode 100755 index 0000000..e414af6 --- /dev/null +++ b/share/extensions/pixelsnap.py @@ -0,0 +1,501 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (c) 2009 Bryan Hoyt (MIT License) +# 2011 Nicolas Dufour +# 2013 Johan B. C. Engelen +# 2019 Martin Owens +# +# 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. +# +""" +TODO: mark elements that have previously been snapped, along with the settings + used, so that the same settings can be used for that element next time when + it's selected as part of a group (and add an option to the extension dialog + "Use previous/default settings" which is selected by default) + +TODO: make elem_offset return [x_offset, y_offset] so we can handle non-symetric scaling + => will probably need to take into account non-symetric scaling on stroke-widths, + too (horizontal vs vertical strokes) + +TODO: Transforming points isn't quite perfect, to say the least. In particular, + when translating a point on a bezier curve, we translate the handles by the same amount. + BUT, some handles that are attached to a particular point are conceptually + handles of the prev/next node. + Best way to fix it would be to keep a list of the fractional_offsets[] of + each point, without transforming anything. Then go through each point and + transform the appropriate handle according to the relevant fraction_offset + in the list. + + i.e. calculate first, then modify. + + In fact, that might be a simpler algorithm anyway -- it avoids having + to keep track of all the first_xy/next_xy guff. + +Note: This doesn't work very well on paths which have both straight segments + and curved segments. + The biggest three problems are: + a) we don't take handles into account (segments where the nodes are + aligned are always treated as straight segments, even where the + handles make it curve) + b) when we snap a straight segment right before/after a curve, it + doesn't make any attempt to keep the transition from the straight + segment to the curve smooth. + c) no attempt is made to keep equal widths equal. (or nearly-equal + widths nearly-equal). For example, font strokes. + +Note: Paths that have curves & arcs on some sides of the bounding box won't + be snapped correctly on that side of the bounding box, and nor will they + be translated/resized correctly before the path is modified. Doesn't affect + most applications of this extension, but it highlights the fact that we + take a geometrically simplistic approach to inspecting & modifying the path. +""" + +from __future__ import division +from __future__ import print_function + +import sys + +import inkex +from inkex import PathElement, Group, Image, Rectangle, ShapeElement, Transform +from inkex.localization import inkex_gettext as _ + +Precision = 5 # number of digits of precision for comparing float numbers + + +class TransformError(Exception): + pass + + +def transform_point(transform, pt, inverse=False): + """apply_to_point with inbuilt inverse""" + if inverse: + transform = -transform + return transform.apply_to_point(pt) + + +def transform_dimensions(transform, width=None, height=None, inverse=False): + """Dimensions don't get translated. I'm not sure how much diff rotate/skew + makes in this context, but we currently ignore anything besides scale. + """ + if inverse: + transform = -transform + + if width is not None: + width *= transform.a + if height is not None: + height *= transform.d + + if width is not None and height is not None: + return width, height + if width is not None: + return width + if height is not None: + return height + + +class PixelSnap(inkex.EffectExtension): + """Snap objects to pixels""" + + def add_arguments(self, pars): + """Add inx options""" + pars.add_argument( + "-a", + "--snap_ancestors", + type=inkex.Boolean, + default=True, + help="Snap unselected ancestors' translations " + "(groups, layers, document height) first", + ) + pars.add_argument( + "-t", + "--ancestor_offset", + type=inkex.Boolean, + default=True, + help="Calculate offset relative to unselected ancestors' " + "transforms (includes document height offset)", + ) + pars.add_argument( + "-g", + "--max_gradient", + type=float, + default=0.5, + help="Maximum slope to consider straight (%)", + ) + pars.add_argument( + "-s", + "--snap_to", + default="tl", + choices=["tl", "bl"], + help="Origin of the coordinate system", + ) + + def vertical(self, pt1, pt2): + hlen = abs(pt1[0] - pt2[0]) + vlen = abs(pt1[1] - pt2[1]) + if vlen == 0 and hlen == 0: + return True + elif vlen == 0: + return False + return (hlen / vlen) < self.options.max_gradient / 100 + + def horizontal(self, pt1, pt2): + hlen = round(abs(pt1[0] - pt2[0]), Precision) + vlen = round(abs(pt1[1] - pt2[1]), Precision) + if hlen == 0 and vlen == 0: + return True + elif hlen == 0: + return False + return (vlen / hlen) < self.options.max_gradient / 100 + + def stroke_width_offset(self, elem, parent_transform=None): + """Returns the amount the bounding-box is offset due to the stroke-width. + Transform is taken into account. + """ + stroke_width = self.stroke_width(elem) + if stroke_width == 0: + return 0 # if there's no stroke, no need to worry about the transform + + transform = elem.transform @ Transform(parent_transform) + + if abs(abs(transform.a) - abs(transform.d)) > (10**-Precision): + raise TransformError( + _("Selection contains non-symetric scaling") + ) # *** wouldn't be hard to get around this by calculating vertical_offset & horizontal_offset separately, maybe 1 functions, or maybe returning a tuple + + stroke_width = transform_dimensions(transform, width=stroke_width) + + return stroke_width / 2 + + def stroke_width(self, elem, setval=None): + """Get/set stroke-width in pixels, untransformed""" + style = elem.style + stroke = style("stroke") + + stroke_width = 0 + if stroke and setval is None: + stroke_width = self.svg.to_dimensionless(style("stroke-width").strip()) + + if setval: + style["stroke-width"] = setval + else: + return stroke_width + + def transform_path_node(self, transform, path, i): + """Modifies a segment so that every point is transformed, including handles""" + segtype = path[i][0].lower() + + if segtype == "z": + return + elif segtype == "h": + path[i][1][0] = transform_point(transform, [path[i][1][0], 0])[0] + elif segtype == "v": + path[i][1][0] = transform_point(transform, [0, path[i][1][0]])[1] + else: + first_coordinate = 0 + if segtype == "a": + first_coordinate = 5 # for elliptical arcs, skip the radius x/y, rotation, large-arc, and sweep + for j in range(first_coordinate, len(path[i][1]), 2): + x, y = path[i][1][j], path[i][1][j + 1] + x, y = transform_point(transform, (x, y)) + path[i][1][j] = x + path[i][1][j + 1] = y + + def pathxy(self, path, i, setval=None): + """Return the endpoint of the given path segment. + Inspects the segment type to know which elements are the endpoints. + """ + segtype = path[i][0].lower() + x = y = 0 + + if segtype == "z": + i = 0 + + if segtype == "h": + if setval: + path[i][1][0] = setval[0] + else: + x = path[i][1][0] + + elif segtype == "v": + if setval: + path[i][1][0] = setval[1] + else: + y = path[i][1][0] + else: + if setval and segtype != "z": + path[i][1][-2] = setval[0] + path[i][1][-1] = setval[1] + else: + x = path[i][1][-2] + y = path[i][1][-1] + + if setval is None: + return [x, y] + + def snap_path_scale(self, elem, parent_transform=None): + + path = elem.original_path.to_arrays() + transform = elem.transform @ Transform(parent_transform) + bbox = elem.bounding_box() + + # In case somebody tries to snap a 0-high element, + # or a curve/arc with all nodes in a line, and of course + # because we should always check for divide-by-zero! + if not bbox.width or not bbox.height: + return + + width, height = bbox.width, bbox.height + min_xy, max_xy = bbox.minimum, bbox.maximum + rescale = round(width) / width, round(height) / height + + min_xy = transform_point(transform, min_xy, inverse=True) + max_xy = transform_point(transform, max_xy, inverse=True) + + for i in range(len(path)): + translate = Transform(translate=min_xy) + self.transform_path_node(-translate, path, i) # center transform + self.transform_path_node(Transform(scale=rescale), path, i) + self.transform_path_node(translate, path, i) # uncenter transform + + elem.original_path = path + + def snap_path_pos(self, elem, parent_transform=None): + path = elem.original_path.to_arrays() + transform = elem.transform @ Transform(parent_transform) + bbox = elem.bounding_box() + min_xy, max_xy = bbox.minimum, bbox.maximum + + fractional_offset = ( + min_xy[0] - round(min_xy[0]), + min_xy[1] - round(min_xy[1]) - self.document_offset, + ) + fractional_offset = transform_dimensions( + transform, fractional_offset[0], fractional_offset[1], inverse=True + ) + + for i in range(len(path)): + self.transform_path_node(-Transform(translate=fractional_offset), path, i) + + path = str(inkex.Path(path)) + if elem.get("inkscape:original-d"): + elem.set("inkscape:original-d", path) + else: + elem.set("d", path) + + def snap_transform(self, elem): + # Only snaps the x/y translation of the transform, nothing else. + # Doesn't take any parent_transform into account -- assumes + # that the parent's transform has already been snapped. + transform = elem.transform + # if we've got any skew/rotation, get outta here + if transform.c or transform.b: + raise TransformError( + _("TR: Selection contains transformations with skew/rotation") + ) + + trm = list(transform.to_hexad()) + trm[4] = round(transform.e) + trm[5] = round(transform.f) + elem.transform @= Transform(trm) + + def snap_stroke(self, elem, parent_transform=None): + transform = elem.transform @ Transform(parent_transform) + + stroke_width = self.stroke_width(elem) + if stroke_width == 0: + return # no point raising a TransformError if there's no stroke to snap + + if abs(abs(transform.a) - abs(transform.d)) > (10**-Precision): + raise TransformError( + _("Selection contains non-symetric scaling, can't snap stroke width") + ) + + if stroke_width: + stroke_width = transform_dimensions(transform, width=stroke_width) + stroke_width = round(stroke_width) + stroke_width = transform_dimensions( + transform, width=stroke_width, inverse=True + ) + self.stroke_width(elem, stroke_width) + + def snap_path(self, elem, parent_transform=None): + path = elem.original_path.to_arrays() + + transform = elem.transform @ Transform(parent_transform) + + if transform.c or transform.b: # if we've got any skew/rotation, get outta here + raise TransformError( + _("Path: Selection contains transformations with skew/rotation") + ) + + offset = self.stroke_width_offset(elem, parent_transform) % 1 + + prev_xy = self.pathxy(path, -1) + first_xy = self.pathxy(path, 0) + for i in range(len(path)): + segtype = path[i][0].lower() + xy = self.pathxy(path, i) + if segtype == "z": + xy = first_xy + if (i == len(path) - 1) or ( + (i == len(path) - 2) and path[-1][0].lower() == "z" + ): + next_xy = first_xy + else: + next_xy = self.pathxy(path, i + 1) + + if not (xy and prev_xy and next_xy): + prev_xy = xy + continue + + xy_untransformed = tuple(xy) + xy = list(transform_point(transform, xy)) + prev_xy = transform_point(transform, prev_xy) + next_xy = transform_point(transform, next_xy) + + on_vertical = on_horizontal = False + + if self.horizontal(xy, prev_xy): + # on 2-point paths, first.next==first.prev==last and last.next==last.prev==first + if len(path) > 2 or i == 0: + # make the almost-equal values equal, so they round in the same direction + xy[1] = prev_xy[1] + on_horizontal = True + if self.horizontal(xy, next_xy): + on_horizontal = True + + if self.vertical(xy, prev_xy): # as above + if len(path) > 2 or i == 0: + xy[0] = prev_xy[0] + on_vertical = True + if self.vertical(xy, next_xy): + on_vertical = True + + prev_xy = tuple(xy_untransformed) + + fractional_offset = [0, 0] + if on_vertical: + fractional_offset[0] = xy[0] - (round(xy[0] - offset) + offset) + if on_horizontal: + fractional_offset[1] = ( + xy[1] - (round(xy[1] - offset) + offset) - self.document_offset + ) + + fractional_offset = transform_dimensions( + transform, fractional_offset[0], fractional_offset[1], inverse=True + ) + self.transform_path_node(-Transform(translate=fractional_offset), path, i) + + elem.original_path = path + + def snap_rect(self, elem, parent_transform=None): + transform = elem.transform @ Transform(parent_transform) + + if transform.c or transform.b: # if we've got any skew/rotation, get outta here + raise TransformError( + _("Rect: Selection contains transformations with skew/rotation") + ) + + offset = self.stroke_width_offset(elem, parent_transform) % 1 + + width = self.svg.to_dimensionless(elem.attrib["width"]) + height = self.svg.to_dimensionless(elem.attrib["height"]) + x = self.svg.to_dimensionless(elem.attrib["x"]) + y = self.svg.to_dimensionless(elem.attrib["y"]) + + width, height = transform_dimensions(transform, width, height) + x, y = transform_point(transform, [x, y]) + + # Snap to the nearest pixel + height = round(height) + width = round(width) + x = ( + round(x - offset) + offset + ) # If there's a stroke of non-even width, it's shifted by half a pixel + y = round(y - offset) + offset + + width, height = transform_dimensions(transform, width, height, inverse=True) + x, y = transform_point(transform, [x, y], inverse=True) + y += self.document_offset / transform.d + + # Position the elem at the newly calculate values + elem.attrib["width"] = str(width) + elem.attrib["height"] = str(height) + elem.attrib["x"] = str(x) + elem.attrib["y"] = str(y) + + def snap_image(self, elem, parent_transform=None): + self.snap_rect(elem, parent_transform) + + def pixel_snap(self, elem, parent_transform=None): + if not isinstance(elem, (Group, Image, Rectangle, PathElement)): + return + + if isinstance(elem, Group): + self.snap_transform(elem) + transform = elem.transform * Transform(parent_transform) + for child in elem: + try: + self.pixel_snap(child, transform) + except TransformError as err: + raise inkex.AbortExtension(str(err)) + return + + # If we've been given a parent_transform, we can assume that the + # parents have already been snapped, or don't need to be + if self.options.snap_ancestors and parent_transform is None: + # Loop through ancestors from outermost to innermost, excluding this element. + for child in elem.ancestors(): + self.snap_transform(child) + + # If we haven't been given a parent_transform, then we need to calculate it + if self.options.ancestor_offset and parent_transform is None: + if isinstance(elem.getparent(), ShapeElement): + parent_transform = elem.getparent().composed_transform() + + self.snap_transform(elem) + try: + self.snap_stroke(elem, parent_transform) + except TransformError as err: + raise inkex.AbortExtension(str(err)) + + if isinstance(elem, PathElement): + self.snap_path_scale(elem, parent_transform) + self.snap_path_pos(elem, parent_transform) + self.snap_path( + elem, parent_transform + ) # would be quite useful to make this an option, as scale/pos alone doesn't mess with the path itself, and works well for sans-serif text + elif isinstance(elem, Rectangle): + self.snap_rect(elem, parent_transform) + elif isinstance(elem, Image): + self.snap_image(elem, parent_transform) + + def effect(self): + if self.options.snap_to == "bl": + self.document_offset = ( + self.svg.to_dimensionless(self.svg.get_viewbox()[3]) % 1 + ) + else: + self.document_offset = 0 + for id, elem in self.svg.selection.items(): + try: + self.pixel_snap(elem) + except TransformError as err: + raise inkex.AbortExtension(str(err)) + + +if __name__ == "__main__": + PixelSnap().run() diff --git a/share/extensions/plotter.inx b/share/extensions/plotter.inx new file mode 100644 index 0000000..98e9c16 --- /dev/null +++ b/share/extensions/plotter.inx @@ -0,0 +1,104 @@ + + + Plot + org.ekips.filter.plot + hpgl_decoder.py + hpgl_encoder.py + + + + + + + + /dev/usb/lp2 + COM1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1016.0 + 1016.0 + 1 + 0 + 0 + + + + + + + false + false + false + + + + + 1.00 + 0.25 + true + 1.2 + true + + + + + + path + + + + + + diff --git a/share/extensions/plotter.py b/share/extensions/plotter.py new file mode 100755 index 0000000..25d4c43 --- /dev/null +++ b/share/extensions/plotter.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2013 +# 2018 Martin Owens +# +# 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. +# + +import inkex +from inkex.ports import Serial +from inkex.localization import inkex_gettext as _ + +import hpgl_encoder + + +class Plot(inkex.EffectExtension): + """Generate a plot in HPGL output""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument( + "--parallelPort", default="/dev/usb/lp2", help="Parallel port" + ) + pars.add_argument("--serialPort", default="COM1", help="Serial port") + pars.add_argument("--serialBaudRate", default="9600", help="Serial Baud rate") + pars.add_argument("--serialByteSize", default="eight", help="Serial byte size") + pars.add_argument("--serialStopBits", default="one", help="Serial stop bits") + pars.add_argument("--serialParity", default="none", help="Serial parity") + pars.add_argument("--serialFlowControl", default="xonxoff", help="Flow control") + pars.add_argument( + "--resolutionX", type=float, default=1016.0, help="Resolution X (dpi)" + ) + pars.add_argument( + "--resolutionY", type=float, default=1016.0, help="Resolution Y (dpi)" + ) + pars.add_argument("--pen", type=int, default=1, help="Pen number") + pars.add_argument("--force", type=int, default=0, help="Pen force (g)") + pars.add_argument("--speed", type=int, default=0, help="Pen speed (cm/s)") + pars.add_argument("--orientation", default="0", help="Rotation (Clockwise)") + pars.add_argument( + "--mirrorX", type=inkex.Boolean, default=False, help="Mirror X axis" + ) + pars.add_argument( + "--mirrorY", type=inkex.Boolean, default=False, help="Mirror Y axis" + ) + pars.add_argument( + "--center", type=inkex.Boolean, default=False, help="Center zero point" + ) + pars.add_argument("--overcut", type=float, default=1.0, help="Overcut (mm)") + pars.add_argument( + "--precut", type=inkex.Boolean, default=True, help="Use precut" + ) + pars.add_argument("--flat", type=float, default=1.2, help="Curve flatness") + pars.add_argument( + "--autoAlign", type=inkex.Boolean, default=True, help="Auto align" + ) + pars.add_argument( + "--toolOffset", + type=float, + default=0.25, + help="Tool (Knife) offset correction (mm)", + ) + pars.add_argument( + "--portType", + type=self.arg_method("to"), + default=self.to_serial, + dest="to_port", + help="Port type", + ) + pars.add_argument( + "--commandLanguage", + type=self.arg_method("convert"), + default=self.convert_hpgl, + dest="to_language", + help="Command Language Filter", + ) + + def effect(self): + # get hpgl data + encoder = hpgl_encoder.hpglEncoder(self) + try: + self.options.to_port(self.options.to_language(encoder.getHpgl())) + except hpgl_encoder.NoPathError: + raise inkex.AbortExtension( + _("No paths where found. Please convert objects to paths.") + ) + + def convert_hpgl(self, hpgl): + """Convert raw HPGL to HPGL""" + init = "IN" + # if self.options.force > 0: + # init += ';FS%d' % self.options.force + # if self.options.speed > 0: + # init += ';VS%d' % self.options.speed + return init + hpgl + ";PU0,0;SP0;IN; " + + def convert_dmpl(self, hpgl): + """Convert HPGL to DMPL""" + # ;: = Initialise plotter + # H = Home position + # A = Absolute pen positioning + # Ln = Line type + # Pn = Pen select + # Vn = velocity + # ECn = Coordinate addressing, 1: 0.001 inch, 5: 0.005 inch, M: 0.1 mm + # D = Pen down + # U = Pen up + # Z = Reset plotter + # n,n, = Coordinate pair + hpgl = hpgl.replace(";", ",") + hpgl = hpgl.replace("SP", "P") + hpgl = hpgl.replace("PU", "U") + hpgl = hpgl.replace("PD", "D") + init = ";:HAL0" + if self.options.speed > 0: + init += "V%d" % self.options.speed + init += "EC1" + return init + hpgl[1:] + ",P0,U0,0,Z " + + def convert_knk(self, hpgl): + """Convert HPGL to KNK Plotter Language""" + init = "ZG" + # if self.options.force > 0: + # init += ';FS%d' % self.options.force + # if self.options.speed > 0: + # init += ';VS%d' % self.options.speed + return init + hpgl + ";SP0;PU0,0;@ " + + def to_parallel(self, hpgl): + """Output to hgpl to a parallel port""" + port = open(self.options.parallelPort, "wb") + port.write(hpgl.encode("utf8")) + port.close() + + def to_serial(self, hpgl): + """Output to hgpl to a serial port""" + with Serial( + self.options.serialPort, + baud=self.options.serialBaudRate, + stop=self.options.serialStopBits, + size=self.options.serialByteSize, + flow=self.options.serialFlowControl, + parity=self.options.serialParity, + ) as comx: + comx.write(hpgl.encode("utf8")) + + +if __name__ == "__main__": + Plot().run() diff --git a/share/extensions/poetry.lock b/share/extensions/poetry.lock new file mode 100644 index 0000000..6ce8cec --- /dev/null +++ b/share/extensions/poetry.lock @@ -0,0 +1,1229 @@ +[[package]] +name = "alabaster" +version = "0.7.12" +description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "babel" +version = "2.9.1" +description = "Internationalization utilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +pytz = ">=2015.7" + +[[package]] +name = "beautifulsoup4" +version = "4.10.0" +description = "Screen-scraping library" +category = "dev" +optional = false +python-versions = ">3.0.0" + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "charset-normalizer" +version = "2.0.12" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "coverage" +version = "6.2" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cssselect" +version = "1.1.0" +description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "distlib" +version = "0.3.4" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "docutils" +version = "0.17.1" +description = "Docutils -- Python Documentation Utilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "filelock" +version = "3.4.1" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "imagesize" +version = "1.3.0" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "importlib-metadata" +version = "4.8.3" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] + +[[package]] +name = "importlib-resources" +version = "5.4.0" +description = "Read resources from Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "jinja2" +version = "3.0.3" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "lxml" +version = "4.8.0" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html5 = ["html5lib"] +htmlsoup = ["beautifulsoup4"] +source = ["Cython (>=0.29.7)"] + +[[package]] +name = "markupsafe" +version = "2.0.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "numpy" +version = "1.19.5" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "numpy" +version = "1.22.3" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pillow" +version = "8.4.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "platformdirs" +version = "2.4.0" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycairo" +version = "1.20.1" +description = "Python interface for cairo" +category = "main" +optional = false +python-versions = ">=3.6, <4" + +[[package]] +name = "pydata-sphinx-theme" +version = "0.7.2" +description = "Bootstrap-based Sphinx theme from the PyData community" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +beautifulsoup4 = "*" +docutils = "!=0.17.0" +sphinx = "*" + +[package.extras] +coverage = ["pytest-cov", "codecov", "sphinx", "numpydoc", "recommonmark", "pandas", "pytest", "pytest-regressions", "beautifulsoup4", "sphinx-sitemap", "jupyter-sphinx", "plotly", "numpy", "xarray", "docutils (==0.16)"] +test = ["sphinx", "numpydoc", "recommonmark", "pandas", "pytest", "pytest-regressions", "beautifulsoup4", "sphinx-sitemap", "jupyter-sphinx", "plotly", "numpy", "xarray", "docutils (==0.16)"] + +[[package]] +name = "pygments" +version = "2.11.2" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "pygobject" +version = "3.42.0" +description = "Python bindings for GObject Introspection" +category = "main" +optional = false +python-versions = ">=3.6, <4" + +[package.dependencies] +pycairo = ">=1.16,<2.0" + +[[package]] +name = "pyparsing" +version = "3.0.7" +description = "Python parsing module" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyserial" +version = "3.5" +description = "Python Serial Port Extension" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +cp2110 = ["hidapi"] + +[[package]] +name = "pytest" +version = "7.0.1" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-xvfb" +version = "2.0.0" +description = "A pytest plugin to run Xvfb for tests." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +pytest = ">=2.8.1" +pyvirtualdisplay = ">=1.3" + +[[package]] +name = "pytz" +version = "2021.3" +description = "World timezone definitions, modern and historical" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pyvirtualdisplay" +version = "3.0" +description = "python wrapper for Xvfb, Xephyr and Xvnc" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "requests" +version = "2.27.1" +description = "Python HTTP for Humans." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "scour" +version = "0.37" +description = "Scour SVG Optimizer" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.9.0" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "soupsieve" +version = "2.3.1" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "sphinx" +version = "4.4.0" +description = "Python documentation generator" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.18" +imagesize = "*" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.3" +packaging = "*" +Pygments = ">=2.0" +requests = ">=2.5.0" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "docutils-stubs", "types-typed-ast", "types-requests"] +test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "1.12.0" +description = "Type hints (PEP 484) support for the Sphinx autodoc extension" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +Sphinx = ">=3.0" + +[package.extras] +test = ["pytest (>=3.1.0)", "typing-extensions (>=3.5)", "sphobjinv (>=2.0)", "Sphinx (>=3.2.0)", "dataclasses"] +type_comments = ["typed-ast (>=1.4.0)"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest", "html5lib"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +test = ["pytest", "flake8", "mypy"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "1.2.3" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "tox" +version = "3.24.5" +description = "tox is a generic virtualenv management and test command line tool" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""} +filelock = ">=3.0.0" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +packaging = ">=14" +pluggy = ">=0.12.0" +py = ">=1.4.17" +six = ">=1.14.0" +toml = ">=0.9.4" +virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" + +[package.extras] +docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "psutil (>=5.6.1)", "pathlib2 (>=2.3.3)"] + +[[package]] +name = "typed-ast" +version = "1.5.2" +description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "typing-extensions" +version = "4.1.1" +description = "Backported and Experimental Type Hints for Python 3.6+" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "urllib3" +version = "1.26.8" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "virtualenv" +version = "20.13.3" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +distlib = ">=0.3.1,<1" +filelock = ">=3.2,<4" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""} +platformdirs = ">=2,<3" +six = ">=1.9.0,<2" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] + +[[package]] +name = "zipp" +version = "3.6.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.6" +content-hash = "6bbd24a3d153f9cf03c74f9158438484cda6589e5a71883c03ba841361e481b4" + +[metadata.files] +alabaster = [ + {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, + {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +babel = [ + {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, + {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, +] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, + {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, +] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +coverage = [ + {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, + {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, + {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, + {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, + {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, + {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, + {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, + {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, + {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, + {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, + {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, + {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, + {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, + {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, + {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, + {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, + {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, + {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, + {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, + {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, + {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, + {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, + {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, + {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, + {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, + {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, + {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, + {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, + {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, +] +cssselect = [ + {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, + {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, +] +distlib = [ + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, +] +docutils = [ + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, +] +filelock = [ + {file = "filelock-3.4.1-py3-none-any.whl", hash = "sha256:a4bc51381e01502a30e9f06dd4fa19a1712eab852b6fb0f84fd7cce0793d8ca3"}, + {file = "filelock-3.4.1.tar.gz", hash = "sha256:0f12f552b42b5bf60dba233710bf71337d35494fc8bdd4fd6d9f6d082ad45e06"}, +] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +imagesize = [ + {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, + {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"}, + {file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"}, +] +importlib-resources = [ + {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, + {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +jinja2 = [ + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, +] +lxml = [ + {file = "lxml-4.8.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e1ab2fac607842ac36864e358c42feb0960ae62c34aa4caaf12ada0a1fb5d99b"}, + {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28d1af847786f68bec57961f31221125c29d6f52d9187c01cd34dc14e2b29430"}, + {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b92d40121dcbd74831b690a75533da703750f7041b4bf951befc657c37e5695a"}, + {file = "lxml-4.8.0-cp27-cp27m-win32.whl", hash = "sha256:e01f9531ba5420838c801c21c1b0f45dbc9607cb22ea2cf132844453bec863a5"}, + {file = "lxml-4.8.0-cp27-cp27m-win_amd64.whl", hash = "sha256:6259b511b0f2527e6d55ad87acc1c07b3cbffc3d5e050d7e7bcfa151b8202df9"}, + {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1010042bfcac2b2dc6098260a2ed022968dbdfaf285fc65a3acf8e4eb1ffd1bc"}, + {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa56bb08b3dd8eac3a8c5b7d075c94e74f755fd9d8a04543ae8d37b1612dd170"}, + {file = "lxml-4.8.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:31ba2cbc64516dcdd6c24418daa7abff989ddf3ba6d3ea6f6ce6f2ed6e754ec9"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:31499847fc5f73ee17dbe1b8e24c6dafc4e8d5b48803d17d22988976b0171f03"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5f7d7d9afc7b293147e2d506a4596641d60181a35279ef3aa5778d0d9d9123fe"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a3c5f1a719aa11866ffc530d54ad965063a8cbbecae6515acbd5f0fae8f48eaa"}, + {file = "lxml-4.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6268e27873a3d191849204d00d03f65c0e343b3bcb518a6eaae05677c95621d1"}, + {file = "lxml-4.8.0-cp310-cp310-win32.whl", hash = "sha256:330bff92c26d4aee79c5bc4d9967858bdbe73fdbdbacb5daf623a03a914fe05b"}, + {file = "lxml-4.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:b2582b238e1658c4061ebe1b4df53c435190d22457642377fd0cb30685cdfb76"}, + {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a2bfc7e2a0601b475477c954bf167dee6d0f55cb167e3f3e7cefad906e7759f6"}, + {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a1547ff4b8a833511eeaceacbcd17b043214fcdb385148f9c1bc5556ca9623e2"}, + {file = "lxml-4.8.0-cp35-cp35m-win32.whl", hash = "sha256:a9f1c3489736ff8e1c7652e9dc39f80cff820f23624f23d9eab6e122ac99b150"}, + {file = "lxml-4.8.0-cp35-cp35m-win_amd64.whl", hash = "sha256:530f278849031b0eb12f46cca0e5db01cfe5177ab13bd6878c6e739319bae654"}, + {file = "lxml-4.8.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:078306d19a33920004addeb5f4630781aaeabb6a8d01398045fcde085091a169"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:86545e351e879d0b72b620db6a3b96346921fa87b3d366d6c074e5a9a0b8dadb"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24f5c5ae618395ed871b3d8ebfcbb36e3f1091fd847bf54c4de623f9107942f3"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bbab6faf6568484707acc052f4dfc3802bdb0cafe079383fbaa23f1cdae9ecd4"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7993232bd4044392c47779a3c7e8889fea6883be46281d45a81451acfd704d7e"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d6483b1229470e1d8835e52e0ff3c6973b9b97b24cd1c116dca90b57a2cc613"}, + {file = "lxml-4.8.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ad4332a532e2d5acb231a2e5d33f943750091ee435daffca3fec0a53224e7e33"}, + {file = "lxml-4.8.0-cp36-cp36m-win32.whl", hash = "sha256:db3535733f59e5605a88a706824dfcb9bd06725e709ecb017e165fc1d6e7d429"}, + {file = "lxml-4.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5f148b0c6133fb928503cfcdfdba395010f997aa44bcf6474fcdd0c5398d9b63"}, + {file = "lxml-4.8.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8a31f24e2a0b6317f33aafbb2f0895c0bce772980ae60c2c640d82caac49628a"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:719544565c2937c21a6f76d520e6e52b726d132815adb3447ccffbe9f44203c4"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:c0b88ed1ae66777a798dc54f627e32d3b81c8009967c63993c450ee4cbcbec15"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fa9b7c450be85bfc6cd39f6df8c5b8cbd76b5d6fc1f69efec80203f9894b885f"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9f84ed9f4d50b74fbc77298ee5c870f67cb7e91dcdc1a6915cb1ff6a317476c"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1d650812b52d98679ed6c6b3b55cbb8fe5a5460a0aef29aeb08dc0b44577df85"}, + {file = "lxml-4.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:80bbaddf2baab7e6de4bc47405e34948e694a9efe0861c61cdc23aa774fcb141"}, + {file = "lxml-4.8.0-cp37-cp37m-win32.whl", hash = "sha256:6f7b82934c08e28a2d537d870293236b1000d94d0b4583825ab9649aef7ddf63"}, + {file = "lxml-4.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e1fd7d2fe11f1cb63d3336d147c852f6d07de0d0020d704c6031b46a30b02ca8"}, + {file = "lxml-4.8.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5045ee1ccd45a89c4daec1160217d363fcd23811e26734688007c26f28c9e9e7"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0c1978ff1fd81ed9dcbba4f91cf09faf1f8082c9d72eb122e92294716c605428"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cbf2ff155b19dc4d4100f7442f6a697938bf4493f8d3b0c51d45568d5666b5"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ce13d6291a5f47c1c8dbd375baa78551053bc6b5e5c0e9bb8e39c0a8359fd52f"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11527dc23d5ef44d76fef11213215c34f36af1608074561fcc561d983aeb870"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:60d2f60bd5a2a979df28ab309352cdcf8181bda0cca4529769a945f09aba06f9"}, + {file = "lxml-4.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:62f93eac69ec0f4be98d1b96f4d6b964855b8255c345c17ff12c20b93f247b68"}, + {file = "lxml-4.8.0-cp38-cp38-win32.whl", hash = "sha256:20b8a746a026017acf07da39fdb10aa80ad9877046c9182442bf80c84a1c4696"}, + {file = "lxml-4.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:891dc8f522d7059ff0024cd3ae79fd224752676447f9c678f2a5c14b84d9a939"}, + {file = "lxml-4.8.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b6fc2e2fb6f532cf48b5fed57567ef286addcef38c28874458a41b7837a57807"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:74eb65ec61e3c7c019d7169387d1b6ffcfea1b9ec5894d116a9a903636e4a0b1"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:627e79894770783c129cc5e89b947e52aa26e8e0557c7e205368a809da4b7939"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:545bd39c9481f2e3f2727c78c169425efbfb3fbba6e7db4f46a80ebb249819ca"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5a58d0b12f5053e270510bf12f753a76aaf3d74c453c00942ed7d2c804ca845c"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec4b4e75fc68da9dc0ed73dcdb431c25c57775383fec325d23a770a64e7ebc87"}, + {file = "lxml-4.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5804e04feb4e61babf3911c2a974a5b86f66ee227cc5006230b00ac6d285b3a9"}, + {file = "lxml-4.8.0-cp39-cp39-win32.whl", hash = "sha256:aa0cf4922da7a3c905d000b35065df6184c0dc1d866dd3b86fd961905bbad2ea"}, + {file = "lxml-4.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:dd10383f1d6b7edf247d0960a3db274c07e96cf3a3fc7c41c8448f93eac3fb1c"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:2403a6d6fb61c285969b71f4a3527873fe93fd0abe0832d858a17fe68c8fa507"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:986b7a96228c9b4942ec420eff37556c5777bfba6758edcb95421e4a614b57f9"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6fe4ef4402df0250b75ba876c3795510d782def5c1e63890bde02d622570d39e"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:f10ce66fcdeb3543df51d423ede7e238be98412232fca5daec3e54bcd16b8da0"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:730766072fd5dcb219dd2b95c4c49752a54f00157f322bc6d71f7d2a31fecd79"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8b99ec73073b37f9ebe8caf399001848fced9c08064effdbfc4da2b5a8d07b93"}, + {file = "lxml-4.8.0.tar.gz", hash = "sha256:f63f62fc60e6228a4ca9abae28228f35e1bd3ce675013d1dfb828688d50c6e23"}, +] +markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, + {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, +] +numpy = [ + {file = "numpy-1.19.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76"}, + {file = "numpy-1.19.5-cp36-cp36m-win32.whl", hash = "sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a"}, + {file = "numpy-1.19.5-cp36-cp36m-win_amd64.whl", hash = "sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827"}, + {file = "numpy-1.19.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28"}, + {file = "numpy-1.19.5-cp37-cp37m-win32.whl", hash = "sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7"}, + {file = "numpy-1.19.5-cp37-cp37m-win_amd64.whl", hash = "sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d"}, + {file = "numpy-1.19.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc"}, + {file = "numpy-1.19.5-cp38-cp38-win32.whl", hash = "sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2"}, + {file = "numpy-1.19.5-cp38-cp38-win_amd64.whl", hash = "sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa"}, + {file = "numpy-1.19.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"}, + {file = "numpy-1.19.5-cp39-cp39-win32.whl", hash = "sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e"}, + {file = "numpy-1.19.5-cp39-cp39-win_amd64.whl", hash = "sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e"}, + {file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"}, + {file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"}, + {file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"}, + {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"}, + {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"}, + {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"}, + {file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"}, + {file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"}, + {file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"}, + {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5"}, + {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1"}, + {file = "numpy-1.22.3-cp38-cp38-win32.whl", hash = "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62"}, + {file = "numpy-1.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676"}, + {file = "numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123"}, + {file = "numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802"}, + {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d"}, + {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168"}, + {file = "numpy-1.22.3-cp39-cp39-win32.whl", hash = "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa"}, + {file = "numpy-1.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a"}, + {file = "numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f"}, + {file = "numpy-1.22.3.zip", hash = "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pillow = [ + {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, + {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, + {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, + {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, + {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, + {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, + {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, + {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, + {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, + {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, + {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, + {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, + {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, + {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, + {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, +] +platformdirs = [ + {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, + {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pycairo = [ + {file = "pycairo-1.20.1-cp310-cp310-win32.whl", hash = "sha256:736ffc618e851601e861a630293e5c910ef016b83b2d035a336f83a367bf56ab"}, + {file = "pycairo-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:261c69850d4b2ec03346c9745bad2a835bb8124e4c6961b8ceac503d744eb3b3"}, + {file = "pycairo-1.20.1-cp36-cp36m-win32.whl", hash = "sha256:6db823a18e7be1eb2a29c28961f2f01e84d3b449f06be7338d05ac8f90592cd5"}, + {file = "pycairo-1.20.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5525da2d8de912750dd157752aa96f1f0a42a437c5625e85b14c936b5c6305ae"}, + {file = "pycairo-1.20.1-cp37-cp37m-win32.whl", hash = "sha256:c8c2bb933974d91c5d19e54b846d964de177e7bf33433bf34ac34c85f9b30e94"}, + {file = "pycairo-1.20.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9a32e4a3574a104aa876c35d5e71485dfd6986b18d045534c6ec510c44d5d6a7"}, + {file = "pycairo-1.20.1-cp38-cp38-win32.whl", hash = "sha256:0d7a6754d410d911a46f00396bee4be96500ccd3d178e7e98aef1140e3dd67ae"}, + {file = "pycairo-1.20.1-cp38-cp38-win_amd64.whl", hash = "sha256:b605151cdd23cedb31855b8666371b6e26b80f02753a52c8b8023a916b1df812"}, + {file = "pycairo-1.20.1-cp39-cp39-win32.whl", hash = "sha256:e800486b51fffeb11ed867b4f2220d446e2a60a81a73b7c377123e0cbb72f49d"}, + {file = "pycairo-1.20.1-cp39-cp39-win_amd64.whl", hash = "sha256:f123d3818e30b77b7209d70a6dcfd5b4e34885f9fa539d92dd7ff3e4e2037213"}, + {file = "pycairo-1.20.1.tar.gz", hash = "sha256:1ee72b035b21a475e1ed648e26541b04e5d7e753d75ca79de8c583b25785531b"}, +] +pydata-sphinx-theme = [ + {file = "pydata-sphinx-theme-0.7.2.tar.gz", hash = "sha256:671df35fcdd290eafbd23d0595e6d359dbe90b2e64e6c3f4dc88276eed4a065e"}, + {file = "pydata_sphinx_theme-0.7.2-py3-none-any.whl", hash = "sha256:bc1abc45e103b254c6c7a8f2ddabbaf8aa1f0817d85cae65dd163dd554c52700"}, +] +pygments = [ + {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, + {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, +] +pygobject = [ + {file = "PyGObject-3.42.0.tar.gz", hash = "sha256:b9803991ec0b0b4175e81fee0ad46090fa7af438fe169348a9b18ae53447afcd"}, +] +pyparsing = [ + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, +] +pyserial = [ + {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, + {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, +] +pytest = [ + {file = "pytest-7.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"}, + {file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"}, +] +pytest-cov = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] +pytest-xvfb = [ + {file = "pytest-xvfb-2.0.0.tar.gz", hash = "sha256:c4ba642de05499940db7f65ee111621939be513e3e75c3da9156b7235e2ed8cf"}, + {file = "pytest_xvfb-2.0.0-py3-none-any.whl", hash = "sha256:6d21b46f099c06d6b8b200e73341da3adb73d67e9139c55d617930881779360b"}, +] +pytz = [ + {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, + {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, +] +pyvirtualdisplay = [ + {file = "PyVirtualDisplay-3.0-py3-none-any.whl", hash = "sha256:40d4b8dfe4b8de8552e28eb367647f311f88a130bf837fe910e7f180d5477f0e"}, + {file = "PyVirtualDisplay-3.0.tar.gz", hash = "sha256:09755bc3ceb6eb725fb07eca5425f43f2358d3bf08e00d2a9b792a1aedd16159"}, +] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] +scour = [ + {file = "scour-0.37.tar.gz", hash = "sha256:963113779c6877cbdd99bb6ea30ac0576dbe8b4156459ac62e579f8d22726116"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] +soupsieve = [ + {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, + {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, +] +sphinx = [ + {file = "Sphinx-4.4.0-py3-none-any.whl", hash = "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe"}, + {file = "Sphinx-4.4.0.tar.gz", hash = "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"}, +] +sphinx-autodoc-typehints = [ + {file = "sphinx-autodoc-typehints-1.12.0.tar.gz", hash = "sha256:193617d9dbe0847281b1399d369e74e34cd959c82e02c7efde077fca908a9f52"}, + {file = "sphinx_autodoc_typehints-1.12.0-py3-none-any.whl", hash = "sha256:5e81776ec422dd168d688ab60f034fccfafbcd94329e9537712c93003bddc04a"}, +] +sphinxcontrib-applehelp = [ + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, +] +sphinxcontrib-devhelp = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] +sphinxcontrib-htmlhelp = [ + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, +] +sphinxcontrib-jsmath = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] +sphinxcontrib-qthelp = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] +sphinxcontrib-serializinghtml = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, + {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, +] +tox = [ + {file = "tox-3.24.5-py2.py3-none-any.whl", hash = "sha256:be3362472a33094bce26727f5f771ca0facf6dafa217f65875314e9a6600c95c"}, + {file = "tox-3.24.5.tar.gz", hash = "sha256:67e0e32c90e278251fea45b696d0fef3879089ccbe979b0c556d35d5a70e2993"}, +] +typed-ast = [ + {file = "typed_ast-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:183b183b7771a508395d2cbffd6db67d6ad52958a5fdc99f450d954003900266"}, + {file = "typed_ast-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676d051b1da67a852c0447621fdd11c4e104827417bf216092ec3e286f7da596"}, + {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc2542e83ac8399752bc16e0b35e038bdb659ba237f4222616b4e83fb9654985"}, + {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74cac86cc586db8dfda0ce65d8bcd2bf17b58668dfcc3652762f3ef0e6677e76"}, + {file = "typed_ast-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:18fe320f354d6f9ad3147859b6e16649a0781425268c4dde596093177660e71a"}, + {file = "typed_ast-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:31d8c6b2df19a777bc8826770b872a45a1f30cfefcfd729491baa5237faae837"}, + {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:963a0ccc9a4188524e6e6d39b12c9ca24cc2d45a71cfdd04a26d883c922b4b78"}, + {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb77764ea470f14fcbb89d51bc6bbf5e7623446ac4ed06cbd9ca9495b62e36e"}, + {file = "typed_ast-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:294a6903a4d087db805a7656989f613371915fc45c8cc0ddc5c5a0a8ad9bea4d"}, + {file = "typed_ast-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26a432dc219c6b6f38be20a958cbe1abffcc5492821d7e27f08606ef99e0dffd"}, + {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7407cfcad702f0b6c0e0f3e7ab876cd1d2c13b14ce770e412c0c4b9728a0f88"}, + {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f30ddd110634c2d7534b2d4e0e22967e88366b0d356b24de87419cc4410c41b7"}, + {file = "typed_ast-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8c08d6625bb258179b6e512f55ad20f9dfef019bbfbe3095247401e053a3ea30"}, + {file = "typed_ast-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:90904d889ab8e81a956f2c0935a523cc4e077c7847a836abee832f868d5c26a4"}, + {file = "typed_ast-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbebc31bf11762b63bf61aaae232becb41c5bf6b3461b80a4df7e791fabb3aca"}, + {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29dd9a3a9d259c9fa19d19738d021632d673f6ed9b35a739f48e5f807f264fb"}, + {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:58ae097a325e9bb7a684572d20eb3e1809802c5c9ec7108e85da1eb6c1a3331b"}, + {file = "typed_ast-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:da0a98d458010bf4fe535f2d1e367a2e2060e105978873c04c04212fb20543f7"}, + {file = "typed_ast-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33b4a19ddc9fc551ebabca9765d54d04600c4a50eda13893dadf67ed81d9a098"}, + {file = "typed_ast-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1098df9a0592dd4c8c0ccfc2e98931278a6c6c53cb3a3e2cf7e9ee3b06153344"}, + {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c47c3b43fe3a39ddf8de1d40dbbfca60ac8530a36c9b198ea5b9efac75c09e"}, + {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f290617f74a610849bd8f5514e34ae3d09eafd521dceaa6cf68b3f4414266d4e"}, + {file = "typed_ast-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:df05aa5b241e2e8045f5f4367a9f6187b09c4cdf8578bb219861c4e27c443db5"}, + {file = "typed_ast-1.5.2.tar.gz", hash = "sha256:525a2d4088e70a9f75b08b3f87a51acc9cde640e19cc523c7e41aa355564ae27"}, +] +typing-extensions = [ + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, +] +urllib3 = [ + {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, + {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, +] +virtualenv = [ + {file = "virtualenv-20.13.3-py2.py3-none-any.whl", hash = "sha256:dd448d1ded9f14d1a4bfa6bfc0c5b96ae3be3f2d6c6c159b23ddcfd701baa021"}, + {file = "virtualenv-20.13.3.tar.gz", hash = "sha256:e9dd1a1359d70137559034c0f5433b34caf504af2dc756367be86a5a32967134"}, +] +zipp = [ + {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, + {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, +] diff --git a/share/extensions/polyhedron_3d.inx b/share/extensions/polyhedron_3d.inx new file mode 100644 index 0000000..e7e598e --- /dev/null +++ b/share/extensions/polyhedron_3d.inx @@ -0,0 +1,97 @@ + + + 3D Polyhedron + org.inkscape.render.poly_3d + + + + + + + + + + + + + + + + + + + + + + great_rhombicuboct.obj + + + + false + + + + + + + 0 + + + + + 0 + + + + + 0 + + + + + 0 + + + + + 0 + + + + + 0 + + + 100 + 255 + 0 + 0 + 100 + 100 + 2 + true + 1 + 1 + -2 + + + + + + false + + + + + + + + all + + + + + + diff --git a/share/extensions/polyhedron_3d.py b/share/extensions/polyhedron_3d.py new file mode 100755 index 0000000..40f1c68 --- /dev/null +++ b/share/extensions/polyhedron_3d.py @@ -0,0 +1,439 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 John Beard john.j.beard@gmail.com +# +# 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. +# +""" +This extension draws 3d objects from a Wavefront .obj 3D file stored in a local folder +Many settings for appearance, lighting, rotation, etc are available. + + ^y + | + __--``| |_--``| __-- + __--`` | __--``| |_--`` + | z | | |_--``| + | <----|--------|-----_0-----|---------------- + | | |_--`` | | + | __--`` <-``| |_--`` + |__--`` x |__--``| + IMAGE PLANE SCENE| + | + + Vertices are given as "v" followed by three numbers (x,y,z). + All files need a vertex list + v x.xxx y.yyy z.zzz + + Faces are given by a list of vertices + (vertex 1 is the first in the list above, 2 the second, etc): + f 1 2 3 + + Edges are given by a list of vertices. These will be broken down + into adjacent pairs automatically. + l 1 2 3 + + Faces are rendered according to the painter's algorithm and perhaps + back-face culling, if selected. The parameter to sort the faces by + is user-selectable between max, min and average z-value of the vertices +""" + +import os +from math import acos, cos, floor, pi, sin, sqrt + +import inkex +from inkex.utils import pairwise +from inkex import Group, Circle +from inkex.paths import Move, Line +from inkex.localization import inkex_gettext as _ + +try: + import numpy +except: + numpy = None + + +def draw_circle(r, cx, cy, width, fill, name, parent): + """Draw an SVG circle""" + circle = parent.add(Circle(cx=str(cx), cy=str(cy), r=str(r))) + circle.style = {"stroke": "#000000", "stroke-width": str(width), "fill": fill} + circle.label = name + + +def draw_line(x1, y1, x2, y2, width, name, parent): + elem = parent.add(inkex.PathElement()) + elem.style = { + "stroke": "#000000", + "stroke-width": str(width), + "fill": "none", + "stroke-linecap": "round", + } + elem.set("inkscape:label", name) + elem.path = [Move(x1, y1), Line(x2, y2)] + + +def draw_poly(pts, face, st, name, parent): + """Draw polygone""" + style = { + "stroke": "#000000", + "stroke-width": str(st.th), + "stroke-linejoin": st.linejoin, + "stroke-opacity": st.s_opac, + "fill": st.fill, + "fill-opacity": st.f_opac, + } + path = inkex.Path() + for facet in face: + if not path: # for first point + path.append(Move(pts[facet - 1][0], -pts[facet - 1][1])) + else: + path.append(Line(pts[facet - 1][0], -pts[facet - 1][1])) + path.close() + + poly = parent.add(inkex.PathElement()) + poly.label = name + poly.style = style + poly.path = path + + +def draw_edges(edge_list, pts, st, parent): + for edge in edge_list: # for every edge + pt_1 = pts[edge[0] - 1][0:2] # the point at the start + pt_2 = pts[edge[1] - 1][0:2] # the point at the end + name = "Edge" + str(edge[0]) + "-" + str(edge[1]) + draw_line(pt_1[0], -pt_1[1], pt_2[0], -pt_2[1], st.th, name, parent) + + +def draw_faces(faces_data, pts, obj, shading, fill_col, st, parent): + for face in faces_data: # for every polygon that has been sorted + if shading: + st.fill = get_darkened_colour( + fill_col, face[1] / pi + ) # darken proportionally to angle to lighting vector + else: + st.fill = get_darkened_colour(fill_col, 1) # do not darken colour + + face_no = face[3] # the number of the face to draw + draw_poly(pts, obj.fce[face_no], st, "Face:" + str(face_no), parent) + + +def get_darkened_colour(rgb, factor): + """return a hex triplet of colour, reduced in lightness 0.0-1.0""" + return ( + "#" + + "%02X" % floor(factor * rgb[0]) + + "%02X" % floor(factor * rgb[1]) + + "%02X" % floor(factor * rgb[2]) + ) # make the colour string + + +def make_rotation_log(options): + """makes a string recording the axes and angles of each rotation, so an object can be repeated""" + return ( + options.r1_ax + + str("%.2f" % options.r1_ang) + + ":" + + options.r2_ax + + str("%.2f" % options.r2_ang) + + ":" + + options.r3_ax + + str("%.2f" % options.r3_ang) + + ":" + + options.r1_ax + + str("%.2f" % options.r4_ang) + + ":" + + options.r2_ax + + str("%.2f" % options.r5_ang) + + ":" + + options.r3_ax + + str("%.2f" % options.r6_ang) + ) + + +def normalise(vector): + """return the unit vector pointing in the same direction as the argument""" + length = sqrt(numpy.dot(vector, vector)) + return numpy.array(vector) / length + + +def get_normal(pts, face): + """normal vector for the plane passing though the first three elements of face of pts""" + return numpy.cross( + (numpy.array(pts[face[0] - 1]) - numpy.array(pts[face[1] - 1])), + (numpy.array(pts[face[0] - 1]) - numpy.array(pts[face[2] - 1])), + ).flatten() + + +def get_unit_normal(pts, face, cw_wound): + """ + Returns the unit normal for the plane passing through the + first three points of face, taking account of winding + """ + # if it is clockwise wound, reverse the vector direction + winding = -1 if cw_wound else 1 + return winding * normalise(get_normal(pts, face)) + + +def rotate(matrix, rads, axis): + """choose the correct rotation matrix to use""" + if axis == "x": + trans_mat = numpy.array( + [[1, 0, 0], [0, cos(rads), -sin(rads)], [0, sin(rads), cos(rads)]] + ) + elif axis == "y": + trans_mat = numpy.array( + [[cos(rads), 0, sin(rads)], [0, 1, 0], [-sin(rads), 0, cos(rads)]] + ) + elif axis == "z": + trans_mat = numpy.array( + [[cos(rads), -sin(rads), 0], [sin(rads), cos(rads), 0], [0, 0, 1]] + ) + return numpy.matmul(trans_mat, matrix) + + +class Style(object): # container for style information + def __init__(self, options): + self.th = options.th + self.fill = "#ff0000" + self.col = "#000000" + self.r = 2 + self.f_opac = str(options.f_opac / 100.0) + self.s_opac = str(options.s_opac / 100.0) + self.linecap = "round" + self.linejoin = "round" + + +class WavefrontObj(object): + """Wavefront based 3d object defined by the vertices and the faces (eg a polyhedron)""" + + name = property(lambda self: self.meta.get("name", None)) + + def __init__(self, filename): + self.meta = {"name": os.path.basename(filename).rsplit(".", 1)[0]} + self.vtx = [] + self.edg = [] + self.fce = [] + self._parse_file(filename) + + def _parse_file(self, filename): + if not os.path.isfile(filename): + raise IOError(_("Can't find wavefront object file {}").format(filename)) + with open(filename, "r") as fhl: + for line in fhl: + self._parse_line(line.strip()) + + def _parse_line(self, line): + if line.startswith("#"): + if ":" in line: + name, value = line.split(":", 1) + self.meta[name.lower()] = value + elif line: + (kind, line) = line.split(None, 1) + kind_name = "add_" + kind + if hasattr(self, kind_name): + getattr(self, kind_name)(line) + + @staticmethod + def _parse_numbers(line, typ=str): + # Ignore any slash options and always pick the first one + return [typ(v.split("/")[0]) for v in line.split()] + + def add_v(self, line): + """Add vertex from parsed line""" + vertex = self._parse_numbers(line, float) + if len(vertex) == 3: + self.vtx.append(vertex) + + def add_l(self, line): + """Add line from parsed line""" + vtxlist = self._parse_numbers(line, int) + # we need at least 2 vertices to make an edge + if len(vtxlist) > 1: + # we can have more than one vertex per line - get adjacent pairs + self.edg.extend(pairwise(vtxlist, start=False)) + + def add_f(self, line): + """Add face from parsed line""" + vtxlist = self._parse_numbers(line, int) + # we need at least 3 vertices to make an edge + if len(vtxlist) > 2: + self.fce.append(vtxlist) + + def get_transformed_pts(self, trans_mat): + """translate vertex points according to the matrix""" + transformed_pts = [] + for vtx in self.vtx: + transformed_pts.append( + (numpy.matmul(trans_mat, numpy.array(vtx).T)).T.tolist() + ) + return transformed_pts + + def get_edge_list(self): + """make an edge vertex list from an existing face vertex list""" + edge_list = [] + for face in self.fce: + for j, edge in enumerate(face): + # Ascending order of certices (for duplicate detection) + edge_list.append(sorted([edge, face[(j + 1) % len(face)]])) + return [list(x) for x in sorted(set(tuple(x) for x in edge_list))] + + +class Poly3D(inkex.GenerateExtension): + """Generate a polyhedron from a wavefront 3d model file""" + + def add_arguments(self, pars): + pars.add_argument("--tab", default="common") + + # MODEL FILE SETTINGS + pars.add_argument("--obj", default="cube") + pars.add_argument("--spec_file", default="great_rhombicuboct.obj") + pars.add_argument("--cw_wound", type=inkex.Boolean, default=False) + pars.add_argument("--type", default="face") + # VEIW SETTINGS + pars.add_argument("--r1_ax", default="x") + pars.add_argument("--r2_ax", default="x") + pars.add_argument("--r3_ax", default="x") + pars.add_argument("--r4_ax", default="x") + pars.add_argument("--r5_ax", default="x") + pars.add_argument("--r6_ax", default="x") + pars.add_argument("--r1_ang", type=float, default=0.0) + pars.add_argument("--r2_ang", type=float, default=0.0) + pars.add_argument("--r3_ang", type=float, default=0.0) + pars.add_argument("--r4_ang", type=float, default=0.0) + pars.add_argument("--r5_ang", type=float, default=0.0) + pars.add_argument("--r6_ang", type=float, default=0.0) + pars.add_argument("--scl", type=float, default=100.0) + # STYLE SETTINGS + pars.add_argument("--show", type=self.arg_method("gen")) + pars.add_argument("--shade", type=inkex.Boolean, default=True) + pars.add_argument("--f_r", type=int, default=255) + pars.add_argument("--f_g", type=int, default=0) + pars.add_argument("--f_b", type=int, default=0) + pars.add_argument("--f_opac", type=int, default=100) + pars.add_argument("--s_opac", type=int, default=100) + pars.add_argument("--th", type=float, default=2) + pars.add_argument("--lv_x", type=float, default=1) + pars.add_argument("--lv_y", type=float, default=1) + pars.add_argument("--lv_z", type=float, default=-2) + pars.add_argument("--back", type=inkex.Boolean, default=False) + pars.add_argument( + "--z_sort", type=self.arg_method("z_sort"), default=self.z_sort_min + ) + + def get_filename(self): + """Get the filename for the spec file""" + name = "" + if self.options.obj == "from_file": + name = self.options.spec_file + else: + name = self.options.obj + ".obj" + moddir = self.ext_path() + return os.path.join(moddir, "Poly3DObjects", name) + + def generate(self): + if numpy is None: + raise inkex.AbortExtension(_("This extension requires the numpy library.")) + so = self.options + + obj = WavefrontObj(self.get_filename()) + + scale = self.svg.unittouu("1px") # convert to document units + st = Style(so) # initialise style + + # we will put all the rotations in the object name, so it can be repeated in + poly = Group.new(obj.name + ":" + make_rotation_log(so)) + (pos_x, pos_y) = self.svg.namedview.center + poly.transform.add_translate(pos_x, pos_y) + poly.transform.add_scale(scale) + + # TRANSFORMATION OF THE OBJECT (ROTATION, SCALE, ETC) + trans_mat = numpy.identity(3, float) # init. trans matrix as identity matrix + for i in range(1, 7): # for each rotation + axis = getattr(so, "r{}_ax".format(i)) + angle = getattr(so, "r{}_ang".format(i)) * pi / 180 + trans_mat = rotate(trans_mat, angle, axis) + # scale by linear factor (do this only after the transforms to reduce round-off) + trans_mat = trans_mat * so.scl + + # the points as projected in the z-axis onto the viewplane + transformed_pts = obj.get_transformed_pts(trans_mat) + so.show(obj, st, poly, transformed_pts) + return poly + + def gen_vtx(self, obj, st, poly, transformed_pts): + """Generate Vertex""" + for i, pts in enumerate(transformed_pts): + draw_circle(st.r, pts[0], pts[1], st.th, "#000000", "Point" + str(i), poly) + + def gen_edg(self, obj, st, poly, transformed_pts): + """Generate edges""" + # we already have an edge list + edge_list = obj.edg + if obj.fce: + # we must generate the edge list from the faces + edge_list = obj.get_edge_list() + + draw_edges(edge_list, transformed_pts, st, poly) + + def gen_fce(self, obj, st, poly, transformed_pts): + """Generate face""" + so = self.options + # colour tuple for the face fill + fill_col = (so.f_r, so.f_g, so.f_b) + # unit light vector + lighting = normalise((so.lv_x, -so.lv_y, so.lv_z)) + # we have a face list + if obj.fce: + z_list = [] + + for i, face in enumerate(obj.fce): + # get the normal vector to the face + norm = get_unit_normal(transformed_pts, face, so.cw_wound) + # get the angle between the normal and the lighting vector + angle = acos(numpy.dot(norm, lighting)) + z_sort_param = so.z_sort(transformed_pts, face) + + # include all polygons or just the front-facing ones as needed + if so.back or norm[2] > 0: + # record the maximum z-value of the face and angle to + # light, along with the face ID and normal + z_list.append((z_sort_param, angle, norm, i)) + + z_list.sort( + key=lambda x: x[0] + ) # sort by ascending sort parameter of the face + draw_faces(z_list, transformed_pts, obj, so.shade, fill_col, st, poly) + + else: # we cannot generate a list of faces from the edges without a lot of computation + raise inkex.AbortExtension(_("Face data not found.")) + + @staticmethod + def z_sort_max(pts, face): + """returns the largest z_value of any point in the face""" + return max([pts[facet - 1][2] for facet in face]) + + @staticmethod + def z_sort_min(pts, face): + """returns the smallest z_value of any point in the face""" + return min([pts[facet - 1][2] for facet in face]) + + @staticmethod + def z_sort_cent(pts, face): + """returns the centroid z_value of any point in the face""" + return sum([pts[facet - 1][2] for facet in face]) / len(face) + + +if __name__ == "__main__": + Poly3D().run() diff --git a/share/extensions/prepare_file_save_as.inx b/share/extensions/prepare_file_save_as.inx new file mode 100644 index 0000000..6c8bf86 --- /dev/null +++ b/share/extensions/prepare_file_save_as.inx @@ -0,0 +1,14 @@ + + + Pre-Process File Save As... + org.inkscape.file.pre_process + + path + + + + + + diff --git a/share/extensions/prepare_file_save_as.py b/share/extensions/prepare_file_save_as.py new file mode 100755 index 0000000..57ad83a --- /dev/null +++ b/share/extensions/prepare_file_save_as.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2014 Ryan Lerch (multiple difference) +# 2016 Maren Hachmann (refactoring, extend to multibool) +# 2017 Alvin Penner (apply to 'File Save As...') +# +# This code is based on 'inkscape-extension-multiple-difference' by Ryan Lerch +# see : https://github.com/ryanlerch/inkscape-extension-multiple-difference +# also: https://github.com/Moini/inkscape-extensions-multi-bool +# It will call up a new instance of Inkscape and process the image there, +# so that the original file is left intact. +# +# 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. +# +""" +This extension will pre-process a vector image by applying the operations: +'EditSelectAllInAllLayers' and 'ObjectToPath' +before calling the dialog File->Save As.... +""" + +import inkex +from inkex.base import TempDirMixin +from inkex.command import inkscape_command +from inkex import load_svg + + +class PreProcess(TempDirMixin, inkex.EffectExtension): + def effect(self): + self.document = load_svg( + inkscape_command( + self.svg, + verbs=["EditSelectAllInAllLayers", "EditUnlinkClone", "ObjectToPath"], + ) + ) + + +if __name__ == "__main__": + PreProcess().run() diff --git a/share/extensions/previous_glyph_layer.inx b/share/extensions/previous_glyph_layer.inx new file mode 100644 index 0000000..955bbe1 --- /dev/null +++ b/share/extensions/previous_glyph_layer.inx @@ -0,0 +1,14 @@ + + + View Previous Glyph + org.inkscape.typography.previous_layer + + all + + + + + + diff --git a/share/extensions/previous_glyph_layer.py b/share/extensions/previous_glyph_layer.py new file mode 100755 index 0000000..d7f73e2 --- /dev/null +++ b/share/extensions/previous_glyph_layer.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# + +from next_glyph_layer import NextLayer + + +class PreviousLayer(NextLayer): + """Like next glyph layer, but for the previous""" + + @staticmethod + def process_glyphs(glyphs, current): + glyphs[current].set("style", "display:none") + glyphs[current - 1].set("style", "display:inline") + + +if __name__ == "__main__": + PreviousLayer().run() diff --git a/share/extensions/print_win32_vector.inx b/share/extensions/print_win32_vector.inx new file mode 100644 index 0000000..e86163c --- /dev/null +++ b/share/extensions/print_win32_vector.inx @@ -0,0 +1,15 @@ + + + Win32 Vector Print + com.vaxxine.print.print_win32_vector + org.inkscape.output.svg.inkscape + + all + + + + + + diff --git a/share/extensions/print_win32_vector.py b/share/extensions/print_win32_vector.py new file mode 100755 index 0000000..58e598c --- /dev/null +++ b/share/extensions/print_win32_vector.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2012 Alvin Penner, penner@vaxxine.com +# +# 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. +# +""" +This extension will generate vector graphics printout, specifically for Windows GDI32. + +This is a modified version of the file dxf_outlines.py by Aaron Spike, aaron@ekips.org +It will write only to the default printer. +The printing preferences dialog will be called. +In order to ensure a pure vector output, use a linewidth < 1 printer pixel + +- see http://www.lessanvaezi.com/changing-printer-settings-using-the-windows-api/ +- get GdiPrintSample.zip at http://archive.msdn.microsoft.com/WindowsPrintSample + +""" + +import sys +import ctypes + +import inkex +from inkex import PathElement, Rectangle, Group, Use, Transform +from inkex.paths import Path + +if sys.platform.startswith("win"): + myspool = ctypes.WinDLL("winspool.drv") + mygdi = ctypes.WinDLL("gdi32.dll") +else: + myspool = None + mygdi = None + +LOGBRUSH = ctypes.c_long * 3 +DM_IN_PROMPT = 4 # call printer property sheet +DM_OUT_BUFFER = 2 # write to DEVMODE structure + + +class PrintWin32Vector(inkex.EffectExtension): + def __init__(self): + super(PrintWin32Vector, self).__init__() + self.visibleLayers = True # print only visible layers + + def process_shape(self, node, mat): + """Process shape""" + rgb = (0, 0, 0) # stroke color + fillcolor = None # fill color + stroke = 1 # pen width in printer pixels + # Very NB : If the pen width is greater than 1 then the output will Not be a vector output ! + style = node.style + if style: + if "stroke" in style: + if ( + style["stroke"] + and style["stroke"] != "none" + and style["stroke"][0:3] != "url" + ): + rgb = inkex.Color(style["stroke"]).to_rgb() + if "stroke-width" in style: + stroke = self.svg.unittouu(style["stroke-width"]) / self.svg.unittouu( + "1px" + ) + stroke = int(stroke * self.scale) + if "fill" in style: + if ( + style["fill"] + and style["fill"] != "none" + and style["fill"][0:3] != "url" + ): + fill = inkex.Color(style["fill"]).to_rgb() + fillcolor = fill[0] + 256 * fill[1] + 256 * 256 * fill[2] + color = rgb[0] + 256 * rgb[1] + 256 * 256 * rgb[2] + if isinstance(node, PathElement): + p = node.path.to_superpath() + if not p: + return + elif isinstance(node, Rectangle): + x = float(node.get("x")) + y = float(node.get("y")) + width = float(node.get("width")) + height = float(node.get("height")) + p = [[[x, y], [x, y], [x, y]]] + p.append([[x + width, y], [x + width, y], [x + width, y]]) + p.append( + [ + [x + width, y + height], + [x + width, y + height], + [x + width, y + height], + ] + ) + p.append([[x, y + height], [x, y + height], [x, y + height]]) + p.append([[x, y], [x, y], [x, y]]) + p = [p] + else: + return + mat += node.transform + p = Path(p).transform(Transform(mat)).to_arrays() + hPen = mygdi.CreatePen(0, stroke, color) + mygdi.SelectObject(self.hDC, hPen) + self.emit_path(p) + if fillcolor is not None: + brush = LOGBRUSH(0, fillcolor, 0) + hBrush = mygdi.CreateBrushIndirect(ctypes.addressof(brush)) + mygdi.SelectObject(self.hDC, hBrush) + mygdi.BeginPath(self.hDC) + self.emit_path(p) + mygdi.EndPath(self.hDC) + mygdi.FillPath(self.hDC) + return + + def emit_path(self, p): + for sub in p: + mygdi.MoveToEx(self.hDC, int(sub[0][1][0]), int(sub[0][1][1]), None) + POINTS = ctypes.c_long * (6 * (len(sub) - 1)) + points = POINTS() + for i in range(len(sub) - 1): + points[6 * i] = int(sub[i][2][0]) + points[6 * i + 1] = int(sub[i][2][1]) + points[6 * i + 2] = int(sub[i + 1][0][0]) + points[6 * i + 3] = int(sub[i + 1][0][1]) + points[6 * i + 4] = int(sub[i + 1][1][0]) + points[6 * i + 5] = int(sub[i + 1][1][1]) + mygdi.PolyBezierTo(self.hDC, ctypes.addressof(points), 3 * (len(sub) - 1)) + return + + def process_clone(self, node): + trans = node.get("transform") + x = node.get("x") + y = node.get("y") + mat = Transform([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) + if trans: + mat *= Transform(trans) + if x: + mat *= Transform([[1.0, 0.0, float(x)], [0.0, 1.0, 0.0]]) + if y: + mat *= Transform([[1.0, 0.0, 0.0], [0.0, 1.0, float(y)]]) + # push transform + if trans or x or y: + self.groupmat.append(Transform(self.groupmat[-1]) * mat) + # get referenced node + refnode = node.href + if refnode is not None: + if isinstance(refnode, inkex.Group): + self.process_group(refnode) + elif refnode.tag == "svg:use": + self.process_clone(refnode) + else: + self.process_shape(refnode, self.groupmat[-1]) + # pop transform + if trans or x or y: + self.groupmat.pop() + + def process_group(self, group): + if isinstance(group, inkex.Layer): + style = group.style + if "display" in style: + if style["display"] == "none" and self.visibleLayers: + return + trans = group.get("transform") + if trans: + self.groupmat.append(Transform(self.groupmat[-1]) * Transform(trans)) + for node in group: + if isinstance(node, Group): + self.process_group(node) + elif isinstance(node, Use): + self.process_clone(node) + else: + self.process_shape(node, self.groupmat[-1]) + if trans: + self.groupmat.pop() + + def doc_name(self): + docname = self.svg.xpath("@sodipodi:docname") + if not docname: + docname = ["New document 1"] + return ctypes.create_string_buffer( + ("Inkscape " + docname[0].split("\\")[-1]).encode("ascii", "replace") + ) + + def effect(self): + pcchBuffer = ctypes.c_long() + myspool.GetDefaultPrinterA( + None, ctypes.byref(pcchBuffer) + ) # get length of printer name + pname = ctypes.create_string_buffer(pcchBuffer.value) + myspool.GetDefaultPrinterA(pname, ctypes.byref(pcchBuffer)) # get printer name + hPrinter = ctypes.c_long() + if myspool.OpenPrinterA(pname.value, ctypes.byref(hPrinter), None) == 0: + return inkex.errormsg(_("Failed to open default printer")) + + # get printer properties dialog + + pcchBuffer = myspool.DocumentPropertiesA(0, hPrinter, pname, None, None, 0) + pDevMode = ctypes.create_string_buffer( + pcchBuffer + 100 + ) # allocate extra just in case + pcchBuffer = myspool.DocumentPropertiesA( + 0, + hPrinter, + pname, + ctypes.byref(pDevMode), + None, + DM_IN_PROMPT + DM_OUT_BUFFER, + ) + myspool.ClosePrinter(hPrinter) + if pcchBuffer != 1: # user clicked Cancel + exit() + + # initiallize print document + + lpszDocName = self.doc_name() + DOCINFO = ctypes.c_long * 5 + docInfo = DOCINFO(20, ctypes.addressof(lpszDocName), 0, 0, 0) + self.hDC = mygdi.CreateDCA(None, pname, None, ctypes.byref(pDevMode)) + if mygdi.StartDocA(self.hDC, ctypes.byref(docInfo)) < 0: + exit() # user clicked Cancel + + self.scale = ( + ord(pDevMode[58]) + 256.0 * ord(pDevMode[59]) + ) / 96 # use PrintQuality from DEVMODE + self.scale /= self.svg.unittouu("1px") + h = self.svg.unittouu(self.svg.xpath("@height")[0]) + doc = self.document.getroot() + # process viewBox height attribute to correct page scaling + viewBox = doc.get("viewBox") + if viewBox: + viewBox2 = viewBox.split(",") + if len(viewBox2) < 4: + viewBox2 = viewBox.split(" ") + self.scale *= h / self.svg.unittouu(self.addDocumentUnit(viewBox2[3])) + self.groupmat = [[[self.scale, 0.0, 0.0], [0.0, self.scale, 0.0]]] + self.process_group(doc) + mygdi.EndDoc(self.hDC) + + +if __name__ == "__main__": + PrintWin32Vector().run() diff --git a/share/extensions/printing_marks.inx b/share/extensions/printing_marks.inx new file mode 100644 index 0000000..ab44d0a --- /dev/null +++ b/share/extensions/printing_marks.inx @@ -0,0 +1,49 @@ + + + Printing Marks + org.inkscape.generate.printing_marks + + + + true + false + true + false + true + false + + + + + + + + + + + + + + 5 + + 5 + 5 + 5 + 5 + + + + + all + + + + + + + + + + diff --git a/share/extensions/printing_marks.py b/share/extensions/printing_marks.py new file mode 100755 index 0000000..272bc02 --- /dev/null +++ b/share/extensions/printing_marks.py @@ -0,0 +1,622 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Authors: +# Nicolas Dufour - Association Inkscape-fr +# Aurelio A. Heckert +# +# Copyright (C) 2008 Authors +# +# 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. +# +""" +This extension allows you to draw crop, registration and other +printing marks in Inkscape. +""" + +import math +import inkex +from inkex import Circle, Rectangle, TextElement + + +class PrintingMarks(inkex.EffectExtension): + # Default parameters + stroke_width = 0.25 + + def add_arguments(self, pars): + pars.add_argument("--where", help="Apply crop marks to...", default="canvas") + pars.add_argument( + "--crop_marks", type=inkex.Boolean, default=True, help="Draw crop Marks" + ) + pars.add_argument("--bleed_marks", type=inkex.Boolean, help="Draw Bleed Marks") + pars.add_argument( + "--registration_marks", + type=inkex.Boolean, + dest="reg_marks", + default=True, + help="Draw Registration Marks?", + ) + pars.add_argument("--star_target", type=inkex.Boolean, help="Draw Star Target?") + pars.add_argument( + "--colour_bars", type=inkex.Boolean, help="Draw Colour Bars?", default=True + ) + pars.add_argument( + "--page_info", type=inkex.Boolean, help="Draw Page Information?" + ) + pars.add_argument("--unit", default="px", help="Draw measurement") + pars.add_argument("--crop_offset", type=float, default=5.0, help="Offset") + pars.add_argument("--bleed_top", type=float, default=5.0, help="Bleed Top Size") + pars.add_argument( + "--bleed_bottom", type=float, default=5.0, help="Bleed Bottom Size" + ) + pars.add_argument( + "--bleed_left", type=float, default=5.0, help="Bleed Left Size" + ) + pars.add_argument( + "--bleed_right", type=float, default=5.0, help="Bleed Right Size" + ) + pars.add_argument("--tab", help="The selected UI-tab when OK was pressed") + + def draw_crop_line(self, x1, y1, x2, y2, name, parent): + style = { + "stroke": "#000000", + "stroke-width": str(self.stroke_width), + "fill": "none", + } + line_attribs = { + "style": str(inkex.Style(style)), + "id": name, + "d": "M " + str(x1) + "," + str(y1) + " L " + str(x2) + "," + str(y2), + } + parent.add(inkex.PathElement(**line_attribs)) + + def draw_bleed_line(self, x1, y1, x2, y2, name, parent): + style = { + "stroke": "#000000", + "stroke-width": str(self.stroke_width), + "fill": "none", + "stroke-miterlimit": "4", + "stroke-dasharray": "4, 2, 1, 2", + "stroke-dashoffset": "0", + } + line_attribs = { + "style": str(inkex.Style(style)), + "id": name, + "d": "M " + str(x1) + "," + str(y1) + " L " + str(x2) + "," + str(y2), + } + parent.add(inkex.PathElement(**line_attribs)) + + def draw_reg_circles(self, cx, cy, r, name, colours, parent): + for i in range(len(colours)): + style = { + "stroke": colours[i], + "stroke-width": str(r / len(colours)), + "fill": "none", + } + circle_attribs = { + "style": str(inkex.Style(style)), + "inkscape:label": name, + "cx": str(cx), + "cy": str(cy), + "r": str((r / len(colours)) * (i + 0.5)), + } + parent.add(Circle(**circle_attribs)) + + def draw_reg_marks(self, cx, cy, rotate, name, parent): + colours = ["#000000", "#00ffff", "#ff00ff", "#ffff00", "#000000"] + g = parent.add(inkex.Group(id=name)) + for i in range(len(colours)): + style = {"fill": colours[i], "fill-opacity": "1", "stroke": "none"} + r = self.mark_size / 2 + step = r + stroke = r / len(colours) + regoffset = stroke * i + regmark_attribs = { + "style": str(inkex.Style(style)), + "d": "m" + + " " + + str(-regoffset) + + "," + + str(r) + + " " + + str(-stroke) + + ",0" + + " " + + str(step) + + "," + + str(-r) + + " " + + str(-step) + + "," + + str(-r) + + " " + + str(stroke) + + ",0" + + " " + + str(step) + + "," + + str(r) + + " " + + str(-step) + + "," + + str(r) + + " z", + "transform": "translate(" + + str(cx) + + "," + + str(cy) + + ") rotate(" + + str(rotate) + + ")", + } + g.add(inkex.PathElement(**regmark_attribs)) + + def draw_star_target(self, cx, cy, name, parent): + r = self.mark_size / 2 + style = { + "fill": "#000 device-cmyk(1,1,1,1)", + "fill-opacity": "1", + "stroke": "none", + } + d = " M 0,0" + i = 0 + while i < (2 * math.pi): + i += math.pi / 16 + d += ( + " L 0,0 " + + " L " + + str(math.sin(i) * r) + + "," + + str(math.cos(i) * r) + + " L " + + str(math.sin(i + 0.09) * r) + + "," + + str(math.cos(i + 0.09) * r) + ) + elem = parent.add(inkex.PathElement()) + elem.label = name + elem.transform.add_translate(cx, cy) + elem.path = d + elem.style = inkex.Style(style) + + def draw_coluor_bars(self, cx, cy, rotate, name, parent, bbox): + group = parent.add(inkex.Group(id=name)) + group.transform = inkex.Transform(translate=(cx, cy)) @ inkex.Transform( + rotate=rotate + ) + loc = 0 + if bbox: + loc = min(self.mark_size / 3, max(bbox.width, bbox.height) / 45) + for bar in [ + {"c": "*", "stroke": "#000", "x": 0, "y": -(loc + 1)}, + {"c": "r", "stroke": "#0FF", "x": 0, "y": 0}, + {"c": "g", "stroke": "#F0F", "x": (loc * 11) + 1, "y": -(loc + 1)}, + {"c": "b", "stroke": "#FF0", "x": (loc * 11) + 1, "y": 0}, + ]: + i = 0 + while i <= 1: + color = inkex.Color("white") + if bar["c"] == "r" or bar["c"] == "*": + color.red = 255 * i + if bar["c"] == "g" or bar["c"] == "*": + color.green = 255 * i + if bar["c"] == "b" or bar["c"] == "*": + color.blue = 255 * i + r_att = { + "fill": str(color), + "stroke": bar["stroke"], + "stroke-width": loc / 8, + "x": str((loc * i * 10) + bar["x"]), + "y": str(bar["y"]), + "width": loc, + "height": loc, + } + rect = Rectangle() + for att, value in r_att.items(): + rect.set(att, value) + group.add(rect) + i += 0.1 + + def effect(self): + self.mark_size = self.svg.viewport_to_unit("1cm") + self.min_mark_margin = self.svg.viewport_to_unit("3mm") + + if self.options.where == "selection": + bbox = self.svg.selection.bounding_box() + if bbox is None: + raise inkex.AbortExtension(_("Selection is empty")) + else: + bbox = self.svg.get_page_bbox() + + # Get SVG document dimensions + # self.width must be replaced by bbox.right. same to others. + svg = self.document.getroot() + + # Convert parameters to user unit + offset = self.svg.viewport_to_unit( + str(self.options.crop_offset) + self.options.unit + ) + bt = self.svg.viewport_to_unit(str(self.options.bleed_top) + self.options.unit) + bb = self.svg.viewport_to_unit( + str(self.options.bleed_bottom) + self.options.unit + ) + bl = self.svg.viewport_to_unit(str(self.options.bleed_left) + self.options.unit) + br = self.svg.viewport_to_unit( + str(self.options.bleed_right) + self.options.unit + ) + # Bleed margin + if bt < offset: + bmt = 0 + else: + bmt = bt - offset + if bb < offset: + bmb = 0 + else: + bmb = bb - offset + if bl < offset: + bml = 0 + else: + bml = bl - offset + if br < offset: + bmr = 0 + else: + bmr = br - offset + + # Define the new document limits + offset_left = bbox.left - offset + offset_right = bbox.right + offset + offset_top = bbox.top - offset + offset_bottom = bbox.bottom + offset + + # Get middle positions + middle_vertical = bbox.top + (bbox.height / 2) + middle_horizontal = bbox.left + (bbox.width / 2) + + # Test if printing-marks layer existis + layer = self.svg.xpath( + '//*[@id="printing-marks" and @inkscape:groupmode="layer"]' + ) + if layer: + svg.remove(layer[0]) # remove if it existis + # Create a new layer + layer = svg.add(inkex.Layer.new("Printing Marks")) + layer.set("id", "printing-marks") + layer.set("sodipodi:insensitive", "true") + + # Crop Mark + if self.options.crop_marks: + # Create a group for Crop Mark + g_crops = layer.add(inkex.Group(id="CropMarks")) + g_crops.label = "CropMarks" + + # Top left Mark + self.draw_crop_line( + bbox.left, + offset_top, + bbox.left, + offset_top - self.mark_size, + "cropTL1", + g_crops, + ) + self.draw_crop_line( + offset_left, + bbox.top, + offset_left - self.mark_size, + bbox.top, + "cropTL2", + g_crops, + ) + + # Top right Mark + self.draw_crop_line( + bbox.right, + offset_top, + bbox.right, + offset_top - self.mark_size, + "cropTR1", + g_crops, + ) + self.draw_crop_line( + offset_right, + bbox.top, + offset_right + self.mark_size, + bbox.top, + "cropTR2", + g_crops, + ) + + # Bottom left Mark + self.draw_crop_line( + bbox.left, + offset_bottom, + bbox.left, + offset_bottom + self.mark_size, + "cropBL1", + g_crops, + ) + self.draw_crop_line( + offset_left, + bbox.bottom, + offset_left - self.mark_size, + bbox.bottom, + "cropBL2", + g_crops, + ) + + # Bottom right Mark + self.draw_crop_line( + bbox.right, + offset_bottom, + bbox.right, + offset_bottom + self.mark_size, + "cropBR1", + g_crops, + ) + self.draw_crop_line( + offset_right, + bbox.bottom, + offset_right + self.mark_size, + bbox.bottom, + "cropBR2", + g_crops, + ) + + # Bleed Mark + if self.options.bleed_marks: + # Create a group for Bleed Mark + g_bleed = layer.add(inkex.Group()) + g_bleed.label = "BleedMarks" + g_bleed.set("id", "BleedMarks") + + # Top left Mark + self.draw_bleed_line( + bbox.left - bl, + offset_top - bmt, + bbox.left - bl, + offset_top - bmt - self.mark_size, + "bleedTL1", + g_bleed, + ) + self.draw_bleed_line( + offset_left - bml, + bbox.top - bt, + offset_left - bml - self.mark_size, + bbox.top - bt, + "bleedTL2", + g_bleed, + ) + + # Top right Mark + self.draw_bleed_line( + bbox.right + br, + offset_top - bmt, + bbox.right + br, + offset_top - bmt - self.mark_size, + "bleedTR1", + g_bleed, + ) + self.draw_bleed_line( + offset_right + bmr, + bbox.top - bt, + offset_right + bmr + self.mark_size, + bbox.top - bt, + "bleedTR2", + g_bleed, + ) + + # Bottom left Mark + self.draw_bleed_line( + bbox.left - bl, + offset_bottom + bmb, + bbox.left - bl, + offset_bottom + bmb + self.mark_size, + "bleedBL1", + g_bleed, + ) + self.draw_bleed_line( + offset_left - bml, + bbox.bottom + bb, + offset_left - bml - self.mark_size, + bbox.bottom + bb, + "bleedBL2", + g_bleed, + ) + + # Bottom right Mark + self.draw_bleed_line( + bbox.right + br, + offset_bottom + bmb, + bbox.right + br, + offset_bottom + bmb + self.mark_size, + "bleedBR1", + g_bleed, + ) + self.draw_bleed_line( + offset_right + bmr, + bbox.bottom + bb, + offset_right + bmr + self.mark_size, + bbox.bottom + bb, + "bleedBR2", + g_bleed, + ) + + # Registration Mark + if self.options.reg_marks: + # Create a group for Registration Mark + g_center = layer.add(inkex.Group()) + g_center.label = "RegistrationMarks" + g_center.set("id", "RegistrationMarks") + # Left Mark + cx = max(bml + offset, self.min_mark_margin) + self.draw_reg_marks( + bbox.left - cx - (self.mark_size / 2), + middle_vertical - self.mark_size * 1.5, + "0", + "regMarkL", + g_center, + ) + + # Right Mark + cx = max(bmr + offset, self.min_mark_margin) + self.draw_reg_marks( + bbox.right + cx + (self.mark_size / 2), + middle_vertical - self.mark_size * 1.5, + "180", + "regMarkR", + g_center, + ) + + # Top Mark + cy = max(bmt + offset, self.min_mark_margin) + self.draw_reg_marks( + middle_horizontal, + bbox.top - cy - (self.mark_size / 2), + "90", + "regMarkT", + g_center, + ) + + # Bottom Mark + cy = max(bmb + offset, self.min_mark_margin) + self.draw_reg_marks( + middle_horizontal, + bbox.bottom + cy + (self.mark_size / 2), + "-90", + "regMarkB", + g_center, + ) + + # Star Target + if self.options.star_target: + # Create a group for Star Target + g_center = layer.add(inkex.Group()) + g_center.label = "StarTarget" + g_center.set("id", "StarTarget") + + if bbox.height < bbox.width: + # Left Star + cx = max(bml + offset, self.min_mark_margin) + self.draw_star_target( + bbox.left - cx - (self.mark_size / 2), + middle_vertical, + "starTargetL", + g_center, + ) + # Right Star + cx = max(bmr + offset, self.min_mark_margin) + self.draw_star_target( + bbox.right + cx + (self.mark_size / 2), + middle_vertical, + "starTargetR", + g_center, + ) + else: + # Top Star + cy = max(bmt + offset, self.min_mark_margin) + self.draw_star_target( + middle_horizontal - self.mark_size * 1.5, + bbox.top - cy - (self.mark_size / 2), + "starTargetT", + g_center, + ) + # Bottom Star + cy = max(bmb + offset, self.min_mark_margin) + self.draw_star_target( + middle_horizontal - self.mark_size * 1.5, + bbox.bottom + cy + (self.mark_size / 2), + "starTargetB", + g_center, + ) + + # Colour Bars + if self.options.colour_bars: + # Create a group for Colour Bars + g_center = layer.add(inkex.Group()) + g_center.label = "ColourBars" + g_center.set("id", "PrintingColourBars") + + if bbox.height > bbox.width: + # Left Bars + cx = max(bml + offset, self.min_mark_margin) + self.draw_coluor_bars( + bbox.left - cx - (self.mark_size / 2), + middle_vertical + self.mark_size, + 90, + "PrintingColourBarsL", + g_center, + bbox, + ) + # Right Bars + cx = max(bmr + offset, self.min_mark_margin) + self.draw_coluor_bars( + bbox.right + cx + (self.mark_size / 2), + middle_vertical + self.mark_size, + 90, + "PrintingColourBarsR", + g_center, + bbox, + ) + else: + # Top Bars + cy = max(bmt + offset, self.min_mark_margin) + self.draw_coluor_bars( + middle_horizontal + self.mark_size, + bbox.top - cy - (self.mark_size / 2), + 0, + "PrintingColourBarsT", + g_center, + bbox, + ) + # Bottom Bars + cy = max(bmb + offset, self.min_mark_margin) + self.draw_coluor_bars( + middle_horizontal + self.mark_size, + bbox.bottom + cy + (self.mark_size / 2), + 0, + "PrintingColourBarsB", + g_center, + bbox, + ) + + # Page Information + if self.options.page_info: + # Create a group for Page Information + g_pag_info = layer.add(inkex.Group()) + g_pag_info.label = "PageInformation" + g_pag_info.set("id", "PageInformation") + y_margin = max(bmb + offset, self.min_mark_margin) + font_size = self.svg.viewport_to_unit("9pt") + txt_attribs = { + "style": f"font-size:{font_size}px;font-style:normal;font-weight:normal;fill:#000000;font-family:Bitstream Vera Sans,sans-serif;text-anchor:middle;text-align:center", + "x": str(middle_horizontal), + "y": str(bbox.bottom + y_margin + self.mark_size + 20), + } + txt = g_pag_info.add(TextElement(**txt_attribs)) + txt.text = ( + "Page size: " + + str( + round(self.svg.unit_to_viewport(bbox.width, self.options.unit), 2) + ) + + "x" + + str( + round(self.svg.unit_to_viewport(bbox.height, self.options.unit), 2) + ) + + " " + + self.options.unit + ) + + +if __name__ == "__main__": + PrintingMarks().run() diff --git a/share/extensions/ps_input.inx b/share/extensions/ps_input.inx new file mode 100644 index 0000000..dd378bb --- /dev/null +++ b/share/extensions/ps_input.inx @@ -0,0 +1,23 @@ + + + PostScript Input + org.inkscape.input.postscript_input + org.inkscape.input.pdf + ps2pdf + + + + + + + .ps + image/x-postscript + PostScript (*.ps) + PostScript + + + diff --git a/share/extensions/ps_input.py b/share/extensions/ps_input.py new file mode 100755 index 0000000..1724c70 --- /dev/null +++ b/share/extensions/ps_input.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2008 Stephen Silver +# +# 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 +# +""" +Simple wrapper around ps2pdf +""" + +import sys +import os + +import inkex +from inkex.command import ProgramRunError, call, which +from inkex.localization import inkex_gettext as _ + + +class PostscriptInput(inkex.CallExtension): + """Load Postscript/EPS Files by calling ps2pdf program""" + + input_ext = "ps" + output_ext = "pdf" + multi_inx = True + + def add_arguments(self, pars): + pars.add_argument("--crop", type=inkex.Boolean, default=False) + pars.add_argument( + "--autorotate", choices=["None", "PageByPage", "All"], default="None" + ) + + def call(self, input_file, output_file): + crop = "-dEPSCrop" if self.options.crop else None + if sys.platform == "win32": + params = [ + "-q", + "-P-", + "-dSAFER", + "-dNOPAUSE", + "-dBATCH", + "-sDEVICE#pdfwrite", + "-dCompatibilityLevel#1.4", + crop, + "-sOutputFile#" + output_file, + "-dAutoRotatePages#/" + self.options.autorotate, + input_file, + ] + gs_execs = ["gswin64c", "gswin32c"] + gs_exec = None + for executable in gs_execs: + try: + which(executable) + gs_exec = executable + except: + pass + if gs_exec is None: + if "PYTEST_CURRENT_TEST" in os.environ: + gs_exec = "gswin64c" # In CI, we have neither available, + # but there are mock files for the 64 bit version + else: + raise inkex.AbortExtension(_("No GhostScript executable was found")) + try: + call(gs_exec, *params) + except ProgramRunError as err: + self.handle_gs_error(err) + else: + try: + call( + "ps2pdf", + crop, + "-dAutoRotatePages=/" + self.options.autorotate, + input_file, + output_file, + ) + except ProgramRunError as err: + self.handle_gs_error(err) + + def handle_gs_error(self, err: ProgramRunError): + inkex.errormsg( + _( + "Ghostscript was unable to read the file. \nThe following error message was returned:" + ) + + "\n" + ) + inkex.errormsg(err.stderr.decode("utf8")) + inkex.errormsg(err.stdout.decode("utf8")) + raise inkex.AbortExtension() + + +if __name__ == "__main__": + PostscriptInput().run() diff --git a/share/extensions/pyproject.toml b/share/extensions/pyproject.toml new file mode 100644 index 0000000..1f0c81e --- /dev/null +++ b/share/extensions/pyproject.toml @@ -0,0 +1,51 @@ +[tool.poetry] +name = "inkex" +version = "1.2.0" +description = "Python extensions for Inkscape core, separated out from main repository." +authors = ["Inkscape Authors "] +maintainers = [ + "Martin Owens ", + "Jonathan Neuhauser ", +] +license = "GPL-2.0-or-later" +readme = "README.md" +repository = "https://gitlab.com/inkscape/extensions" +keywords = ["extensions", "graphics", "inkscape", "svg", "vector"] +classifiers=[ + "Development Status :: 6 - Mature", + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Multimedia :: Graphics :: Editors :: Vector-Based", +] + +[tool.poetry.dependencies] +python = "^3.6" +PyGObject = {version = ">=3.36", markers = "platform_system!='Windows'"} +pySerial = "^3.4" +lxml = "^4.5.0" +cssselect = "^1.1.0" +numpy = [ + #numpy incorrectly specifies its required Python version until 1.21.2 + {version = "^1.17.0", python = "^3.6, <3.10"}, + {version = "^1.21.2", python = "^3.10"}, +] +Pillow = ">=7.0.0" # Used by RasterOutputExtension +scour = "^0.37" # Used by Optimized SVG Extension +packaging = ">=20.3" # Used by Optimized SVG Extension to compare scour versions + +[tool.poetry.dev-dependencies] +pytest = "^7.0.1" +pytest-cov = "^3.0.0" +pytest-xvfb = "^2.0.0" +coverage = "^6.2" +tox = "^3.24.5" +# Documentation dependencies +# Move to [tool.poetry.group.docs.dependencies] in the future +Sphinx = "^4.4.0" +sphinx-autodoc-typehints = "^1.12.0" +pydata-sphinx-theme = ">=0.7.2" +typed-ast = "^1.5.2" + +[build-system] +requires = ["poetry_core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/share/extensions/raster_output_jpg.inx b/share/extensions/raster_output_jpg.inx new file mode 100644 index 0000000..c237e98 --- /dev/null +++ b/share/extensions/raster_output_jpg.inx @@ -0,0 +1,40 @@ + + + Export to JPEG + org.inkscape.raster.jpg_output + + + + + raster_output_jpg.svg + + + + + + + + + + 90 + true + + + + + .jpg + image/jpeg + JPEG (*.jpg) + Render to JPEG file format + + + + diff --git a/share/extensions/raster_output_jpg.py b/share/extensions/raster_output_jpg.py new file mode 100644 index 0000000..4235044 --- /dev/null +++ b/share/extensions/raster_output_jpg.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +""" +Convert PNG to Jpeg using Raster Output extension. +""" + +import inkex + + +class JpegOutput(inkex.RasterOutputExtension): + multi_inx = True # XXX Remove this after refactoring + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--quality", type=int, default=90) + pars.add_argument("--progressive", type=inkex.Boolean, default=False) + + def save(self, stream): + self.img.convert("RGB").save( + stream, + format="jpeg", + quality=self.options.quality, + dpi=self.img.info["dpi"], + progressive=self.options.progressive, + ) + + +if __name__ == "__main__": + JpegOutput().run() diff --git a/share/extensions/raster_output_jpg.svg b/share/extensions/raster_output_jpg.svg new file mode 100644 index 0000000..d8497e9 --- /dev/null +++ b/share/extensions/raster_output_jpg.svg @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/share/extensions/raster_output_png.inx b/share/extensions/raster_output_png.inx new file mode 100644 index 0000000..26d053e --- /dev/null +++ b/share/extensions/raster_output_png.inx @@ -0,0 +1,38 @@ + + + Optimized PNG + org.inkscape.raster.png_output + optipng + + + + + false + + + + + + + + + + + + false + false + false + + + + + .png + image/png + Optimized PNG (*.png) + Optimize PNG output for file size. + + + + diff --git a/share/extensions/raster_output_png.py b/share/extensions/raster_output_png.py new file mode 100755 index 0000000..b70baa0 --- /dev/null +++ b/share/extensions/raster_output_png.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +""" +Optimise PNG file using optipng +""" + +import os +import inkex +from inkex.extensions import TempDirMixin +from inkex.command import ProgramRunError, call + + +class PngOutput(TempDirMixin, inkex.RasterOutputExtension): + def add_arguments(self, pars): + pars.add_argument("--tab") + # Lossless options + pars.add_argument("--interlace", type=inkex.Boolean, default=False) + pars.add_argument("--level", type=int, default=0) + # Lossy options + pars.add_argument("--bitdepth", type=inkex.Boolean, default=False) + pars.add_argument("--color", type=inkex.Boolean, default=False) + pars.add_argument("--palette", type=inkex.Boolean, default=False) + + def load(self, stream): + """Load the PNG file (prepare it for optipng)""" + self.png_file = os.path.join(self.tempdir, "input.png") + with open(self.png_file, "wb") as fhl: + fhl.write(stream.read()) + + def save(self, stream): + """Pass the PNG file to optipng with the options""" + options = { + "o": self.options.level, + "i": int(self.options.interlace), + "nb": not self.options.bitdepth, + "nc": not self.options.color, + "np": not self.options.palette, + } + try: + call("optipng", self.png_file, oldie=True, clobber=True, **options) + except ProgramRunError as err: + if "IDAT recoding is necessary" in err.stderr.decode("utf-8"): + raise inkex.AbortExtension( + _( + "The optipng command failed, possibly due to a mismatch of the" + "interlacing and compression level options. Please try to disable " + '"Interlaced" or set "Level" to 1 or higher.' + ) + ) + else: + raise inkex.AbortExtension( + _("The optipng command failed with the following message:") + + "\n" + + err.stderr.decode("utf-8") + ) + + if os.path.isfile(self.png_file): + with open(self.png_file, "rb") as fhl: + stream.write(fhl.read()) + + +if __name__ == "__main__": + PngOutput().run() diff --git a/share/extensions/raster_output_tiff.inx b/share/extensions/raster_output_tiff.inx new file mode 100644 index 0000000..048823f --- /dev/null +++ b/share/extensions/raster_output_tiff.inx @@ -0,0 +1,37 @@ + + + Export to TIFF + org.inkscape.raster.tiff_output + + + + + + + + + + + + + + + + 90 + + + + + .tiff + image/tiff + TIFF (*.tiff) + Render to TIFF file format + + + + diff --git a/share/extensions/raster_output_tiff.py b/share/extensions/raster_output_tiff.py new file mode 100755 index 0000000..1594b7f --- /dev/null +++ b/share/extensions/raster_output_tiff.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +""" +Convert PNG to Tiff using Raster Output extension. +""" + +import io +import inkex + + +class TiffOutput(inkex.RasterOutputExtension): + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--compression", default=None) + pars.add_argument("--quality", type=int, default=90) + + def save(self, stream): + tempstream = io.BytesIO() + self.img.save( + tempstream, + format="tiff", + compression=(self.options.compression or None), + dpi=self.img.info["dpi"], + quality=100, + ) + stream.write(tempstream.getvalue()) + # TODO: Add other fields such as copyright etc. + + +if __name__ == "__main__": + TiffOutput().run() diff --git a/share/extensions/raster_output_webp.inx b/share/extensions/raster_output_webp.inx new file mode 100644 index 0000000..28e22f9 --- /dev/null +++ b/share/extensions/raster_output_webp.inx @@ -0,0 +1,38 @@ + + + Export to WebP + org.inkscape.raster.webp_output + + + + true + 80 + + + + + + + + + + + + + + .webp + image/webp + WebP (*.webp) + Export to WebP file format. + + + + diff --git a/share/extensions/raster_output_webp.py b/share/extensions/raster_output_webp.py new file mode 100755 index 0000000..01d728f --- /dev/null +++ b/share/extensions/raster_output_webp.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +""" +Convert PNG to WebP using Raster Output extension. +""" + +import inkex + + +class WebpOutput(inkex.RasterOutputExtension): + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--quality", type=int, default=80) + pars.add_argument("--speed", type=int, default=0) + pars.add_argument("--lossless", type=inkex.Boolean, default=True) + + def save(self, stream): + self.img.save( + stream, + format="webp", + quality=self.options.quality, + lossless=self.options.lossless, + method=self.options.speed, + ) + + +if __name__ == "__main__": + WebpOutput().run() diff --git a/share/extensions/render_alphabetsoup.inx b/share/extensions/render_alphabetsoup.inx new file mode 100644 index 0000000..22d3127 --- /dev/null +++ b/share/extensions/render_alphabetsoup.inx @@ -0,0 +1,18 @@ + + + Alphabet Soup + org.inkscape.filter.alphabet_soup + render_alphabetsoup_config.py + Inkscape + 8.0 + false + + all + + + + + + diff --git a/share/extensions/render_alphabetsoup.py b/share/extensions/render_alphabetsoup.py new file mode 100755 index 0000000..825c285 --- /dev/null +++ b/share/extensions/render_alphabetsoup.py @@ -0,0 +1,542 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2001-2002 Matt Chisholm matt@theory.org +# Copyright (C) 2008 Joel Holdsworth joel@airwebreathe.org.uk +# for AP +# +# 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. +# + +import cmath +import copy +import math +import os +import random +import re +import sys + +import inkex +from inkex import Vector2d, load_svg + +import render_alphabetsoup_config + +syntax = render_alphabetsoup_config.syntax +alphabet = render_alphabetsoup_config.alphabet +units = render_alphabetsoup_config.units +font = render_alphabetsoup_config.font + + +def load_path(filename): + """Loads a super-path from a given SVG file""" + base = os.path.normpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) + # __file__ is better then sys.argv[0] because this file may be a module + # for another one. + fullpath = os.path.join(base, filename) + tree = load_svg(fullpath) + root = tree.getroot() + elem = root.findone("svg:path") + if elem is None: + return None, 0, 0 + width = float(root.get("width")) + height = float(root.get("height")) + return ( + elem.path.to_arrays(), + width, + height, + ) # Currently we only support a single path + + +def combinePaths(pathA, pathB): + if pathA is None and pathB is None: + return None + elif pathA is None: + return pathB + elif pathB is None: + return pathA + else: + return pathA + pathB + + +def reverseComponent(c): + nc = [] + last = c.pop() + nc.append(["M", last[1][-2:]]) + while c: + this = c.pop() + cmd = last[0] + if cmd == "C": + nc.append([last[0], last[1][2:4] + last[1][:2] + this[1][-2:]]) + else: + nc.append([last[0], this[1][-2:]]) + last = this + return nc + + +def reversePath(sp): + rp = [] + component = [] + for p in sp: + cmd, params = p + if cmd == "Z": + rp.extend(reverseComponent(component)) + rp.append(["Z", []]) + component = [] + else: + component.append(p) + return rp + + +def _lr_cb(p, width): + p.scale(-1, 1) + p.translate(width, 0) + + +def _tp_cb(p, height): + p.scale(1, -1) + p.translate(0, height) + + +def flip(sp, cb, param): + # print('flip before +' + str(sp)) + p = inkex.Path(sp) + cb(p, param) + del sp[:] + + prev = Vector2d() + prev_prev = Vector2d() + first = Vector2d() + + for i, seg in enumerate(p): + if i == 0: + first = seg.end_point(first, prev) + cps = [] + for cp in seg.control_points(first, prev, prev_prev): + prev_prev = prev + prev = cp + cps.extend(cp) + sp.append([seg.letter, cps]) + # print('flip after +' + str(sp)) + + +def flipLeftRight(sp, width): + return flip(sp, _lr_cb, width) + + +def flipTopBottom(sp, height): + return flip(sp, _tp_cb, height) + + +def solveQuadratic(a, b, c): + det = b * b - 4.0 * a * c + if det >= 0: # real roots + sdet = math.sqrt(det) + else: # complex roots + sdet = cmath.sqrt(det) + return (-b + sdet) / (2 * a), (-b - sdet) / (2 * a) + + +def cbrt(x): + if x >= 0: + return x ** (1.0 / 3.0) + else: + return -((-x) ** (1.0 / 3.0)) + + +def findRealRoots(a, b, c, d): + if a != 0: + a, b, c, d = 1, b / float(a), c / float(a), d / float(a) # Divide through by a + t = b / 3.0 + p, q = c - 3 * t**2, d - c * t + 2 * t**3 + u, v = solveQuadratic(1, q, -((p / 3.0) ** 3)) + if isinstance(u, complex): # Complex Cubic Root + r = math.sqrt(u.real**2 + u.imag**2) + w = math.atan2(u.imag, u.real) + y1 = 2 * cbrt(r) * math.cos(w / 3.0) + else: # Complex Real Root + y1 = cbrt(u) + cbrt(v) + + y2, y3 = solveQuadratic(1, y1, p + y1**2) + + if isinstance(y2, complex): # Are y2 and y3 complex? + return [y1 - t] + return [y1 - t, y2 - t, y3 - t] + elif b != 0: + det = c * c - 4.0 * b * d + if det >= 0: + return [ + (-c + math.sqrt(det)) / (2.0 * b), + (-c - math.sqrt(det)) / (2.0 * b), + ] + elif c != 0: + return [-d / c] + return [] + + +def mxfm(image, width, height, stack): # returns possibly transformed image + tbimage = image + if stack[0] == "-": # top-bottom flip + flipTopBottom(tbimage, height) + tbimage = reversePath(tbimage) + stack.pop(0) + + lrimage = tbimage + if stack[0] == "|": # left-right flip + flipLeftRight(tbimage, width) + lrimage = reversePath(lrimage) + stack.pop(0) + return lrimage + + +def comparerule(rule, nodes): # compare node list to nodes in rule + for i in range(0, len(nodes)): # range( a, b ) = (a, a+1, a+2 ... b-2, b-1) + if nodes[i] == rule[i][0]: + pass + else: + return 0 + return 1 + + +def findrule(state, nodes): # find the rule which generated this subtree + ruleset = syntax[state][1] + nodelen = len(nodes) + for rule in ruleset: + rulelen = len(rule) + if (rulelen == nodelen) and (comparerule(rule, nodes)): + return rule + return + + +def generate(state): # generate a random tree (in stack form) + stack = [state] + if len(syntax[state]) == 1: # if this is a stop symbol + return stack + else: + stack.append("[") + path = random.randint( + 0, (len(syntax[state][1]) - 1) + ) # choose randomly from next states + for symbol in syntax[state][1][path]: # recurse down each non-terminal + if symbol != 0: # 0 denotes end of list ### + substack = generate(symbol[0]) # get subtree + for elt in substack: + stack.append(elt) + if symbol[3]: + stack.append("-") # top-bottom flip + if symbol[4]: + stack.append("|") # left-right flip + # else: + # inkex.debug("found end of list in generate( state =", state, ")") # this should be deprecated/never happen + stack.append("]") + return stack + + +def draw(stack): # draw a character based on a tree stack + state = stack.pop(0) + # print state, + + image, width, height = load_path(font + syntax[state][0]) # load the image + if stack[0] != "[": # terminal stack element + if len(syntax[state]) == 1: # this state is a terminal node + return image, width, height + else: + substack = generate(state) # generate random substack + return draw(substack) # draw random substack + else: + # inkex.debug("[") + stack.pop(0) + images = [] # list of daughter images + nodes = [] # list of daughter names + while stack[0] != "]": # for all nodes in stack + newstate = stack[0] # the new state + newimage, width, height = draw(stack) # draw the daughter state + if newimage: + tfimage = mxfm( + newimage, width, height, stack + ) # maybe transform daughter state + images.append([tfimage, width, height]) # list of daughter images + nodes.append(newstate) # list of daughter nodes + else: + # inkex.debug(("recurse on",newstate,"failed")) # this should never happen + return None, 0, 0 + rule = findrule(state, nodes) # find the rule for this subtree + + for i in range(0, len(images)): + currimg, width, height = images[i] + + if currimg: + # box = inkex.Path(currimg).bounding_box() + dx = rule[i][1] * units + dy = rule[i][2] * units + # newbox = ((box[0]+dx),(box[1]+dy),(box[2]+dx),(box[3]+dy)) + currimg = (inkex.Path(currimg).translate(dx, dy)).to_arrays() + image = combinePaths(image, currimg) + + stack.pop(0) + return image, width, height + + +def draw_crop_scale(stack, zoom): # draw, crop and scale letter image + image, width, height = draw(stack) + bbox = inkex.Path(image).bounding_box() + image = (inkex.Path(image).translate(-bbox.x.minimum, 0)).to_arrays() + image = (inkex.Path(image).scale(zoom / units, zoom / units)).to_arrays() + return image, bbox.width, bbox.height + + +def randomize_input_string( + tokens, zoom +): # generate a glyph starting from each token in the input string + imagelist = [] + + stack = None + for i in range(0, len(tokens)): + char = tokens[i] + # if ( re.match("[a-zA-Z0-9?]", char)): + if char in alphabet: + if (i > 0) and ( + char == tokens[i - 1] + ): # if this letter matches previous letter + imagelist.append(imagelist[len(stack) - 1]) # make them the same image + else: # generate image for letter + stack = alphabet[char][ + random.randint(0, (len(alphabet[char]) - 1)) + ].split(".") + # stack = string.split( alphabet[char][random.randint(0,(len(alphabet[char])-2))] , "." ) + imagelist.append(draw_crop_scale(stack, zoom)) + elif char == " ": # add a " " space to the image list + imagelist.append(" ") + else: # this character is not in config.alphabet, skip it + sys.stderr.write('bad character "{}"\n'.format(char)) + return imagelist + + +def generate_random_string( + tokens, zoom +): # generate a totally random glyph for each glyph in the input string + imagelist = [] + for char in tokens: + if char == " ": # add a " " space to the image list + imagelist.append(" ") + else: + if re.match("[a-z]", char): # generate lowercase letter + stack = generate("lc") + elif re.match("[A-Z]", char): # generate uppercase letter + stack = generate("UC") + else: # this character is not in config.alphabet, skip it + sys.stderr.write('bad character"{}"\n'.format(char)) + stack = generate("start") + imagelist.append(draw_crop_scale(stack, zoom)) + + return imagelist + + +def optikern(image, width, zoom): # optical kerning algorithm + left = [] + right = [] + + resolution = 8 + for i in range(0, 18 * resolution): + y = 1.0 / resolution * (i + 0.5) * zoom + xmin = None + xmax = None + + for cmd, params in image: + if cmd == "M": + # A move cannot contribute to the bounding box + last = params[:] + lastctrl = params[:] + elif cmd == "L": + if (last[1] <= y <= params[1]) or (params[1] <= y <= last[1]): + if params[0] == last[0]: + x = params[0] + else: + a = (params[1] - last[1]) / (params[0] - last[0]) + b = last[1] - a * last[0] + if a != 0: + x = (y - b) / a + else: + x = None + + if x: + if xmin is None or x < xmin: + xmin = x + if xmax is None or x > xmax: + xmax = x + + last = params[:] + lastctrl = params[:] + elif cmd == "C": + if last: + bx0, by0 = last[:] + bx1, by1, bx2, by2, bx3, by3 = params[:] + + d = by0 - y + c = -3 * by0 + 3 * by1 + b = 3 * by0 - 6 * by1 + 3 * by2 + a = -by0 + 3 * by1 - 3 * by2 + by3 + + ts = findRealRoots(a, b, c, d) + + for t in ts: + if 0 <= t <= 1: + x = ( + (-bx0 + 3 * bx1 - 3 * bx2 + bx3) * (t**3) + + (3 * bx0 - 6 * bx1 + 3 * bx2) * (t**2) + + (-3 * bx0 + 3 * bx1) * t + + bx0 + ) + if xmin is None or x < xmin: + xmin = x + if xmax is None or x > xmax: + xmax = x + + last = params[-2:] + lastctrl = params[2:4] + + elif cmd == "Q": + # Quadratic beziers are ignored + last = params[-2:] + lastctrl = params[2:4] + + elif cmd == "A": + # Arcs are ignored + last = params[-2:] + lastctrl = params[2:4] + + if xmin is not None and xmax is not None: + left.append(xmin) # distance from left edge of region to left edge of bbox + right.append( + width - xmax + ) # distance from right edge of region to right edge of bbox + else: + left.append(width) + right.append(width) + + return left, right + + +def layoutstring( + imagelist, zoom +): # layout string of letter-images using optical kerning + kernlist = [] + length = zoom + for entry in imagelist: + if entry == " ": # leaving room for " " space characters + length = length + (zoom * render_alphabetsoup_config.space) + else: + image, width, height = entry + length = length + width + zoom # add letter length to overall length + kernlist.append( + optikern(image, width, zoom) + ) # append kerning data for this image + + workspace = None + + position = zoom + for i in range(0, len(kernlist)): + while imagelist[i] == " ": + position = position + (zoom * render_alphabetsoup_config.space) + imagelist.pop(i) + image, width, height = imagelist[i] + + # set the kerning + if i == 0: + kern = 0 # for first image, kerning is zero + else: + kerncompare = [] # kerning comparison array + for j in range(0, len(kernlist[i][0])): + kerncompare.append(kernlist[i][0][j] + kernlist[i - 1][1][j]) + kern = min(kerncompare) + + position = position - kern # move position back by kern amount + thisimage = copy.deepcopy(image) + thisimage = (inkex.Path(thisimage).translate(position, 0)).to_arrays() + workspace = combinePaths(workspace, thisimage) + position = position + width + zoom # advance position by letter width + + return workspace + + +def tokenize(text): + """Tokenize the string, looking for LaTeX style, multi-character tokens in the string, like \\yogh.""" + tokens = [] + i = 0 + while i < len(text): + c = text[i] + i += 1 + if c == "\\": # found the beginning of an escape + t = "" + while i < len(text): # gobble up content of the escape + c = text[i] + if c == "\\": # found another escape, stop this one + break + i += 1 + if c == " ": # a space terminates this escape + break + t += c # stick this character onto the token + if t: + tokens.append(t) + else: + tokens.append(c) + return tokens + + +class AlphabetSoup(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument( + "-t", "--text", default="Inkscape", help="The text for alphabet soup" + ) + pars.add_argument( + "-z", "--zoom", type=float, default=8.0, help="The zoom on the output" + ) + pars.add_argument( + "-r", + "--randomize", + type=inkex.Boolean, + default=False, + help="Generate random (unreadable) text", + ) + + def effect(self): + zoom = self.svg.unittouu(str(self.options.zoom) + "px") + + if self.options.randomize: + imagelist = generate_random_string(self.options.text, zoom) + else: + tokens = tokenize(self.options.text) + imagelist = randomize_input_string(tokens, zoom) + + image = layoutstring(imagelist, zoom) + + if image: + s = {"stroke": "none", "fill": "#000000"} + + new = inkex.PathElement(style=str(inkex.Style(s)), d=str(inkex.Path(image))) + + layer = self.svg.get_current_layer() + layer.append(new) + + # compensate preserved transforms of parent layer + if layer.getparent() is not None: + mat = ( + self.svg.get_current_layer().transform + @ inkex.Transform([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) + ).matrix + new.transform @= -inkex.Transform(mat) + + +if __name__ == "__main__": + AlphabetSoup().run() diff --git a/share/extensions/render_alphabetsoup_config.py b/share/extensions/render_alphabetsoup_config.py new file mode 100755 index 0000000..91b486a --- /dev/null +++ b/share/extensions/render_alphabetsoup_config.py @@ -0,0 +1,902 @@ +# coding=utf-8 +# pylint: disable=invalid-name,line-too-long +# Syntax format: (raise your hand if you know lisp :-) +# +# 'state0': ("file.svg", ( ( ('state1', dx, dy, T-B, L|R),), +# ( ('state2', ...), ('state3', ...),), +# ( ('state4', ...),), +# ) ), +# ) +# +# Translation of the above in CNF: +# state0 -> state1 +# state0 -> state2 state3 +# state0 -> state4 +# +# Semantics at state0: +# Paste subtree image from state1 onto "file.svg". +# Subtree image is translated by (dx, dy) (measured in units, not pixels!). +# Subtree image is flipped top to bottom if v==1. +# Subtree image is flipped left to right if h==1. +# +# Notes: +# Origin (0,0) is at *upper* left corner. +# For optional reflections, add both reflecting and non-reflecting rules +# For 180 degree rotations, set v = 1, h = 1. +# It helps to have an empty "epsilon" image. +# +"""Data for render alphabet soup""" + +syntax = { + "start": ( + "epsilon.svg", + ((("lc", 0, 0, 0, 0),), (("UC", 0, 0, 0, 0),)), # start state + ), + # lowercase + "lc": ( + "epsilon.svg", + ( + (("barsym", 0, 0, 0, 0),), # (2096714) (26) + (("lc2", 0, 0, 0, 0),), # (830) (19) + ), + ), + # uppercase + "UC": ( + "epsilon.svg", + ((("UCb", 0, 0, 0, 0),), (("UCu", 0, -5, 0, 0),)), # (2160) (30) + ), + "UCb": ( + "epsilon.svg", + ( + (("Bar", 0, 0, 0, 0),), # (21) Psi T I KK Phi + (("Bar", 0, 0, 0, 1),), # + (("D", 0, 0, 0, 0),), # (39) D O Q C G + (("D", 0, 0, 0, 1),), # + (("E", 0, 0, 0, 0),), # (373) E B PL 3 3r 8 S Theta Eth/Dyet + (("E", 0, 0, 0, 1),), # + (("F", 0, 0, 0, 0),), # (84) F P R + (("F", 0, 0, 0, 1),), # + (("H", 0, 0, 0, 0),), # (8) H Hblock + (("H", 0, 0, 0, 1),), # + (("L", 0, 0, 0, 0),), # (12) L J U + (("L", 0, 0, 0, 1),), # + (("V", 0, 0, 0, 1),), # (6) A V M Delta Forall W + (("X", 0, 0, 0, 0),), # (172) X N M W Sigma NN + (("X", 0, 0, 0, 0),), # (172) X N M W Sigma NN + ), + ), + "UCu": ("epsilon.svg", ((("UCb", 0, 0, 1, 1),),)), + # for statistical balancing + "lc2": ( + "epsilon.svg", + ( + (("osym", 0, 0, 0, 0),), # (40) o, c, e, ou + (("vsym", 0, 0, 0, 0),), # (40) v, w, ^, y + (("dsym", 0, 0, 0, 1),), # (96) x, z, 7, 2, yogh + (("lc3", 0, 0, 0, 0),), # (928) (5) + ), + ), + "lc3": ( + "epsilon.svg", + ( + (("3sym", 0, 0, 0, 0),), # (40) epsilon + (("ssym", 0, 0, 0, 0),), # (8) s + (("asym", 0, 0, 0, 0),), # (880) a 6 9 + ), + ), + # symmetry rules + "barsym": ( + "epsilon.svg", + ( + (("bar", 0, 0, 0, 0),), + (("bar", 0, 0, 0, 1),), + (("bar", 0, 0, 1, 0),), + (("bar", 0, 0, 1, 1),), + ), + ), + "6sym": ( + "epsilon.svg", + ( + (("6", 0, 0, 0, 0),), + (("6", 0, 0, 0, 1),), + (("6", 0, 0, 1, 0),), + (("6", 0, 0, 1, 1),), + ), + ), + "3sym": ( + "epsilon.svg", + ( + (("3", 0, 0, 0, 0),), + (("3", 0, 0, 0, 1),), + (("3", 0, 0, 1, 0),), + (("3", 0, 0, 1, 1),), + ), + ), + "vsym": ("epsilon.svg", ((("v", 0, 0, 0, 0),), (("v", 0, 0, 1, 1),))), + "osym": ("epsilon.svg", ((("o", 0, 0, 0, 0),), (("o", 0, 0, 0, 1),))), + "ssym": ("epsilon.svg", ((("s", 0, 0, 0, 0),), (("s", 0, 0, 0, 1),))), + "dsym": ( + "epsilon.svg", + ( + (("diag", 0, 0, 0, 0), ("diag", 0, 0, 1, 1)), + (("diag", 0, 0, 0, 1), ("diag", 0, 0, 1, 0)), + (("dstk", 0, 0, 0, 0),), + ), + ), + "dstk": ( + "epsilon.svg", + ( + (("stik", 0, 4, 0, 0), ("z", 0, 0, 1, 1)), + (("stik", 0, 4, 0, 0), ("x", 0, 0, 1, 1)), + (("stik", 0, 4, 0, 1), ("z", 0, 0, 1, 0)), + (("stik", 0, 4, 0, 1), ("x", 0, 0, 1, 0)), + ), + ), + "asym": ( + "epsilon.svg", + ( + (("abase", 0, 0, 0, 0),), + (("abase", 0, 0, 0, 1),), + (("abase", 0, 0, 1, 0),), + (("abase", 0, 0, 1, 1),), + ), + ), + # epsilon rules + "diag": ( + "epsilon.svg", + ( + (("x", 0, 0, 0, 0),), + (("yogh", 0, 0, 1, 1),), + (("z", 0, 0, 0, 0),), + (("7", 0, 0, 0, 0),), + (("2", 0, 0, 0, 0),), + ), + ), + "bar": ( + "bar.svg", + ( + (("vert", 0, 0, 0, 0), ("vert", 0, 0, 1, 0)), # f l i t j glot. + (("k", 0, 0, 0, 0), ("vert", 0, 0, 0, 0), ("vert", 0, 0, 1, 0)), # k + (("b", 0, 0, 0, 0), ("vert", 0, 0, 1, 0)), # h heng + (("n", 0, 0, 0, 0), ("vert", 0, 0, 1, 0)), # n m r eng u uu mu + (("b1", 0, 0, 0, 0), ("b0", 0, 0, 1, 0)), # thorn eject. + (("b1", 0, 0, 0, 0), ("n0", 0, 0, 1, 0)), # b p q d + (("n1", 0, 0, 0, 0), ("n0", 0, 0, 1, 0)), # open-a + ), + ), + "vert": ( + "epsilon.svg", + ( + (("xtnd", 0, 0, 0, 0),), + (("srf", 0, 0, 1, 0),), + # (('xtnd', 0,0,0,1),), + # (('srf', 0,0,1,1),), + ), + ), + "srf": ( + "epsilon.svg", + ( + (("lserif", 0, 0, 0, 0),), + (("lserif", 0, 0, 0, 1),), + (("serif", 0, 0, 0, 0),), + (("tserif", 0, 0, 0, 0),), + (("tserif", 0, 0, 0, 1),), + ), + ), + "xtnd": ( + "epsilon.svg", + ( + (("cross", 0, 0, 0, 0),), # this needs to be L-R flippable + (("cross", 0, 0, 0, 1),), + (("l", 0, 0, 0, 0),), + (("?", 0, 0, 0, 0),), + (("?", 0, 0, 0, 1),), + (("idot", 0, 0, 0, 0),), + ), + ), + "loop": ( + "epsilon.svg", + ((("o0", 5, 0, 0, 1),), (("30", 5, 0, 0, 1),)), # loop-around elts + ), + "elike": ( + "epsilon.svg", + ( + (("e", 0, 0, 0, 0), ("crv", 0, 0, 1, 0)), + (("a", 0, 0, 0, 0), ("crv", 0, 0, 1, 0)), + (("crv", 0, 0, 0, 0), ("crv", 0, 0, 1, 0)), + ), + ), + "loop2": ("epsilon.svg", ((("elike", 0, 0, 0, 0),), (("loop", 0, 0, 0, 0),))), + "hlike": ( + "epsilon.svg", + ( + (("h", 0, 0, 0, 0),), # h-like extensions + (("m", 0, 0, 0, 0),), + (("crv", 0, 0, 0, 0),), + ), + ), + "crv": ( + "epsilon.svg", + ((("r", 0, 0, 0, 0),), (("cserif", 0, 0, 1, 0),)), # curvy things + ), + # image rules + "abase": ( + "abase.svg", + ( + (("n0", 0, 0, 1, 0), ("loop2", 0, 0, 0, 0)), + (("n0", 0, 0, 1, 0), ("loop2", 0, 0, 1, 0)), + (("b0", 0, 0, 1, 0), ("loop2", 0, 0, 0, 0)), + (("b0", 0, 0, 1, 0), ("loop2", 0, 0, 1, 0)), + ), + ), + "v": ( + "v.svg", + ( + (("vserl", 0, 0, 0, 0), ("vserr", 0, 0, 0, 0)), + (("vserl", 0, 0, 0, 0), ("vserr", 0, 0, 0, 0), ("y0", 0, 0, 0, 0)), + (("vserl", 0, 0, 0, 0), ("w", 6, 0, 0, 0)), + (("vserl", 0, 0, 0, 0), ("w", 6, 0, 0, 0), ("y0", 0, 0, 0, 0)), + ), + ), + "w": ( + "v.svg", + ((("vserr", 0, 0, 0, 0),), (("vserr", 0, 0, 0, 0), ("y0", 0, 0, 0, 0))), + ), + "y0": ( + "epsilon.svg", + ((("y", 0, 0, 0, 1),), (("y", 0, 0, 0, 0),), (("gamma", 0, 0, 0, 0),)), + ), + "l": ( + "l.svg", + ((("j", 0, 0, 0, 0),), (("j", 0, 0, 0, 1),), (("srf", 0, -4, 1, 0),)), + ), + "o": ("o.svg", ((("loop2", 0, 0, 0, 0),), (("loop2", 0, 0, 1, 0),))), + "cross": ("cross.svg", ((("t", 0, 0, 0, 0),), (("f0", 0, 0, 0, 0),))), + "f": ( + "f.svg", + ((("j", 0, 0, 0, 0),), (("j", 0, 0, 0, 1),), (("srf", 0, -4, 1, 0),)), + ), + "f0": ("f.svg", ((("j", 0, 0, 0, 0),), (("srf", 0, -4, 1, 0),))), + "idot": ( + "idot.svg", + ( + (("serif", 0, 0, 1, 0),), + (("lserif", 0, 0, 1, 0),), + (("lserif", 0, 0, 1, 1),), + ), + ), + "stik": ( + "f.svg", + ( + (("srf", 0, -4, 1, 0),), + # (('srf', 0,-4,1,1),), + ), + ), + "3": ("3.svg", ((("loop2", 0, 0, 0, 0),),)), + # uppercase + # Bar rules + "X": ( + "epsilon.svg", + ( + (("Xtb", 0, 0, 0, 0), ("Xtb", 0, -5, 1, 1)), + (("Xlr", 0, 0, 0, 0), ("Xlr", 0, -5, 1, 1)), + (("Xtb", 0, 0, 0, 0), ("Xtb2", 0, -5, 1, 1)), + (("Xlr", 0, 0, 0, 0), ("Xlr2", 0, -5, 1, 1)), + (("Xtb2", 0, 0, 0, 0), ("Xtb", 0, -5, 1, 1)), + (("Xlr2", 0, 0, 0, 0), ("Xlr", 0, -5, 1, 1)), + ), + ), + "Xtb": ( + "epsilon.svg", + ( + (("Xnw", 0, 0, 0, 0), ("Xne", 0, 0, 0, 0)), + (("Xne", 0, 0, 0, 0), ("Xh", 0, 0, 0, 0), ("Lterm2", 0, 0, 0, 0)), + (("Xnw", 0, 0, 0, 0), ("Xh", 0, 0, 0, 1), ("Lterm2", 0, 0, 0, 1)), + ( + ("Xne", 0, 0, 0, 0), + ("Xh", 0, 0, 0, 0), + ("Xnw", 0, 0, 0, 0), + ("Xh", 0, 0, 0, 1), + ), + ), + ), + "Xlr": ( + "epsilon.svg", + ( + (("Xne", 0, -5, 1, 1), ("Xnw", 0, 0, 0, 0)), + ( + ("Xne", 0, -5, 1, 1), + ("Xvt", 0, 0, 0, 0), + ("Xvb", 0, 0, 0, 0), + ("ITSerif", 0.5, 0, 0, 0), + ), + ( + ("Xnw", 0, 0, 0, 0), + ("Xvt", 0, 0, 0, 0), + ("Xvt", 0, -5, 1, 0), + ("IBSerif", 0, 0, 0, 0), + ), + ( + ("Xne", 0, -5, 1, 1), + ("Xnw", 0, 0, 0, 0), + ("Xvt", 0, 0, 0, 0), + ("Xvb", 0, 0, 0, 0), + ), + ), + ), + "Xtb2": ("epsilon.svg", ((("Xne", 0, 0, 0, 0),), (("Xnw", 0, 0, 0, 0),))), + "Xlr2": ("epsilon.svg", ((("Xnw", 0, 0, 0, 0),), (("Xne", 0, -5, 1, 1),))), + "Xne": ("Xne.svg",), + "Xnw": ("Xnw.svg",), + "Xh": ("Xh.svg",), + "Xvt": ("Xvt.svg",), + "Xvb": ("Xvb.svg",), + "Bar": ( + "barcap.svg", + ( + (("Bartop", 0, 0, 0, 0), ("Barbot", 0, 0, 0, 0), ("Barmid", 0, 0, 0, 0)), + (("Bartop2", 0, 0, 0, 0), ("Barbot2", 0, 0, 0, 0)), + ), + ), + "Bartop": ("epsilon.svg", ((("ITSerif", 0.5, 0, 0, 0),), (("Tt", 0, 0, 0, 0),))), + "Barbot": ("epsilon.svg", ((("IBSerif", 0, 0, 0, 0),), (("Tb", 0, 0, 0, 0),))), + "Barbot2": ("epsilon.svg", ((("Barbot", 0, 0, 0, 0),), (("Psi", 0, 0, 0, 0),))), + "Bartop2": ("epsilon.svg", ((("Bartop", 0, 0, 0, 0),), (("Psi", 0, -5, 1, 0),))), + "Barmid": ( + "epsilon.svg", + ( + ( + ("Hm", 0, 0, 0, 0), + ("Eserif", 0, 0, 0, 0), + ("Hm", -7.5, 0, 0, 1), + ("Eserif", -7.5, 0, 0, 1), + ), + (("P", -2.5, 3, 0, 0), ("P", -5, 3, 0, 1)), + (("P", -5, 3, 0, 1),), # points left + ), + ), + "Psi": ( + "epsilon.svg", + ((("IBSerif", 0, 0, 0, 0), ("R", -2.5, 0, 0, 0), ("R", -5, 0, 0, 1)),), + ), + # D / E / F / H / L rules + "D": ( + "epsilon.svg", + ( + (("Dterm", 0, 0, 0, 0), ("Dterm", 0, 0, 0, 1)), + (("Dterm", 0, 0, 0, 0), ("Dterm2", 0, 0, 0, 1)), + ), + ), + "E": ( + "epsilon.svg", + ( + (("Eterm", 0, 0, 0, 0), ("Eterm", 0, 0, 0, 1)), + (("Eterm", 0, 0, 0, 0), ("Eterm2", 0, 0, 0, 1)), + (("Eterm2", 0, 0, 0, 1), ("Eterm2", 0, -5, 1, 0)), # for S + ), + ), + "F": ( + "epsilon.svg", + ( + (("Fterm", 0, 0, 0, 0), ("Fterm", 0, 0, 0, 1)), + (("Fterm", 0, 0, 0, 0), ("Fterm2", 0, 0, 0, 1)), + ), + ), + "H": ( + "epsilon.svg", + ( + (("Hterm", 0, 0, 0, 0), ("Hterm", 0, 0, 0, 1)), + (("Hterm", 0, 0, 0, 0), ("Hterm2", 0, 0, 0, 1)), + ), + ), + "L": ( + "epsilon.svg", + ( + (("Lterm", 0, 0, 0, 0), ("Lterm", 0, 0, 0, 1)), + (("Lterm", 0, 0, 0, 0), ("Lterm2", 0, 0, 0, 1)), + ), + ), + "Dterm": ( + "epsilon.svg", + ( + (("Barterm", 0, 0, 0, 0), ("Et", 0, 0, 0, 0), ("Eb", 0, 0, 0, 0)), + (("O", 0, 0, 0, 0),), + ), + ), + "Dterm2": ( + "epsilon.svg", + ((("C", 0, 0, 0, 1),), (("Ltserif", 0, 0, 0, 1), ("Lbserif", 0, 0, 0, 1))), + ), + "Eterm": ( + "epsilon.svg", + ( + ( + ("Barterm", 0, 0, 0, 0), + ("Et", 0, 0, 0, 0), + ("Hm", 0, 0, 0, 0), + ("Eb", 0, 0, 0, 0), + ), + (("B", 0, 0, 0, 1),), + (("O", 0, 0, 0, 0), ("Ocross", 0, 0, 0, 0)), + (("Dterm", 0, 0, 0, 0), ("Eserif", 0, 0, 0, 1)), + (("Dterm2", 0, 0, 0, 0), ("Eserif", 0, 0, 0, 1)), + ), + ), + "Eterm2": ("epsilon.svg", ((("P", 0, 0, 0, 1), ("Lterm2", 0, -5, 1, 0)),)), + "Fterm": ( + "epsilon.svg", + ( + ( + ("Barterm", 0, 0, 0, 0), + ("Et", 0, 0, 0, 0), + ("Hm", 0, 0, 0, 0), + ("IBSerif", 0, 0, 0, 0), + ), + (("Lterm", 0, 0, 0, 0), ("Eserif", 0, 0, 0, 1)), + (("P", 0, 0, 0, 1), ("R", 0, 0, 0, 1)), + (("Ltserif", 0, 0, 0, 1), ("R", 0, 0, 0, 1)), + (("Ltserif", 0, 0, 0, 1), ("Rblock", 0, 0, 0, 1)), + (("Uterm", 0, 0, 0, 0), ("Ocross", 0, 0, 0, 0)), + ), + ), + "Fterm2": ( + "epsilon.svg", + ((("P", 0, 0, 0, 1),), (("Lterm2", 0, 0, 0, 0), ("Eserif", 0, 0, 0, 1))), + ), + "Hterm": ( + "epsilon.svg", + ( + ( + ("Barterm", 0, 0, 0, 0), + ("Hm", 0, 0, 0, 0), + ("ITSerif", 0.5, 0, 0, 0), + ("IBSerif", 0, 0, 0, 0), + ), + (("R", 0, 0, 0, 1), ("R", 0, -5, 1, 1)), + ), + ), + "Hterm2": ("epsilon.svg", ((("R", 0, 0, 0, 1),), (("Rblock", 0, 0, 0, 1),))), + "Lterm": ( + "epsilon.svg", + ( + (("Barterm", 0, 0, 0, 0), ("Et", 0, 0, 0, 0), ("IBSerif", 0, 0, 0, 0)), + (("Uterm", 0, 0, 0, 0),), + ), + ), + "Lterm2": ("epsilon.svg", ((("Ltserif", 0, 0, 0, 1),), (("Cserif", 0, -5, 1, 1),))), + "B": ("epsilon.svg", ((("P", 0, 0, 0, 0), ("P", 0, 6, 0, 0)),)), + "C": ("epsilon.svg", ((("Cserif", 0, 0, 0, 0), ("Cserif", 0, -5, 1, 0)),)), + "Cserif": ( + "epsilon.svg", + ( # (('Ctail', 0,0,0,0),), # I just hate the way these look... + (("Cblob", 0, 0, 0, 0),), + (("Chook", 0, -5, 1, 0),), + (("G", 0, 0, 0, 0),), + ), + ), + "O": ( + "epsilon.svg", + ((("Oterm", 0, 0, 0, 0),), (("Q", 0, 0, 0, 1),), (("Qu", 0, 0, 0, 1),)), + ), + "Qu": ("epsilon.svg", ((("Q", 0, -5, 1, 0),),)), + "Barterm": ("barcap.svg",), + "Ctail": ("Ctail.svg",), + "Chook": ("Chook.svg",), + "Cblob": ("Cblob.svg",), + "G": ("G.svg",), + "Ltserif": ("Lt.svg",), + "Lbserif": ("Lb.svg",), + "Et": ("Et.svg",), + "Eb": ("Eb.svg",), + "Hm": ("hcap.svg",), + "P": ("P.svg",), + "Tb": ("Tb.svg",), + "Tt": ("Tt.svg",), + "Ocross": ("Ocross.svg",), + "Oterm": ("ocap.svg",), + "Q": ("Q.svg",), + "R": ("rcap.svg", ((("IBSerif", -0.5, 0, 0, 1),),)), + "Rblock": ("Rblock.svg", ((("IBSerif", -0.5, 0, 0, 1),),)), + "Uterm": ("U.svg", ((("IBSerif", -0.5, 0, 0, 0),),)), + "IBSerif": ("IBSerif.svg",), + "ITSerif": ("ITSerif.svg",), + "Eserif": ("Eserif.svg",), + # V rules + "V": ( + "vcap.svg", + ((("V2", 0, 0, 0, 0),), (("V2", 0, 0, 0, 0), ("Across", 0, 0, 0, 0))), + ), + "V2": ( + "epsilon.svg", + ((("M", 0, 0, 0, 0),), (("Delta", 0, 0, 0, 0),), (("Vser", 0, 0, 0, 0),)), + ), + "M": ("mcap.svg", ((("IBSerif", -1.5, 0, 0, 0), ("IBSerif", 1.5, 0, 0, 1)),)), + "Delta": ("Delta.svg",), + "Vser": ("Vser.svg",), + "Across": ("acap.svg",), + # single daughter rules + "b": ( + "b.svg", + ( + (("hlike", 0, 0, 0, 0), ("f", 0, 0, 0, 0)), + # (('hlike', 0,0,0,0), ('f', 0,0,0,1),), + ), + ), + "b1": ( + "b.svg", + ( + (("loop", 0, 0, 0, 0), ("f", 0, 0, 0, 0)), + # (('loop', 0,0,0,0), ('f', 0,0,0,1),), + ), + ), + "b0": ( + "b.svg", + ( + (("f", 0, 0, 0, 0),), + # (('f', 0,0,0,1),), + ), + ), + "h": ("h.svg", ((("vert", 5, 0, 1, 0),),)), + "m": ( + "m.svg", + ((("h", 5, 0, 0, 0), ("vert", 5, 0, 1, 0)),), + ), # change later to allow 3 humped m + "n": ("n.svg", ((("hlike", 0, 0, 0, 0),),)), + "n1": ("n.svg", ((("loop", 0, 0, 0, 0),),)), + "s": ("s.svg", ((("crv", 0, 0, 0, 0), ("crv", 5, 0, 1, 1)),)), + "j": ("j.svg", ((("crv", 0, -5, 0, 0),),)), + "?": ("question.svg", ((("crv", -2.5, -5, 0, 0),),)), + "yogh": ("yogh.svg", ((("crv", -2.5, 4, 1, 0),),)), + # terminal rules + "2": ("2.svg",), + "30": ("3.svg",), + "7": ("7.svg",), + "a": ("a.svg",), + "cserif": ("cserif.svg",), + "e": ("e.svg",), + "k": ("k.svg",), + "n0": ("n.svg",), + "o0": ("o.svg",), + "r": ("r.svg",), + "serif": ("serif.svg",), + "tserif": ("tserif.svg",), + "lserif": ("lserif.svg",), + "t": ("t.svg",), + "x": ("x.svg",), + "z": ("z.svg",), + "vserl": ("vserl.svg",), + "vserr": ("vserr.svg",), + "y": ("y.svg",), + "gamma": ("gamma.svg",), +} + +alphabet = { + # Uppercase fix Y make 2) + "1": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Bartop.[.ITSerif.].].Barbot2.[.Barbot.[.IBSerif.].].].].].]", + ), + "33": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.[.C.|.].Eserif.|.].Eterm.[.O.Ocross.].|.].].].]", + ), + "3": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.B.[.P.P.].|.].Eterm.[.Dterm2.[.C.|.].Eserif.|.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.[.C.|.].Eserif.|.].Eterm.[.O.Ocross.].|.].].].]", + ), + "4": ( + "start.[.UC.[.UCu.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm2.[.Rblock.[.IBSerif.|.].|.].|.].].-.|.].].]", + ), + "5": ( + "start.[.UC.[.UCu.[.UCb.[.E.[.Eterm.[.Dterm2.[.Ltserif.|.Lbserif.|.].Eserif.|.].Eterm2.[.P.|.Lterm2.[.Ltserif.|.].-.].|.].|.].-.|.].].]", + ), + "6": ( + "start.[.UC.[.UCu.[.UCb.[.E.[.Eterm.[.Dterm.[.O.].Eserif.|.].Eterm2.[.P.|.Lterm2.-.].|.].|.].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.E.[.Eterm.[.O.Ocross.].Eterm2.[.P.|.Lterm2.-.].|.].|.].-.|.].].]", + ), + "7": ( + "start.[.UC.[.UCb.[.X.[.Xtb.[.Xne.Xh.Lterm2.[.Ltserif.|.].].Xtb2.[.Xne.].-.|.].].].]", + ), + "8": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.B.[.P.P.].|.].Eterm.[.B.[.P.P.].|.].|.].].].]", + ), + "9": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm.[.O.].Eserif.|.].Eterm2.[.P.|.Lterm2.-.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.O.Ocross.].Eterm2.[.P.|.Lterm2.-.].|.].|.].].]", + ), + "0": ("start.[.UC.[.UCb.[.D.[.Dterm.[.O.].Dterm.[.O.].|.].].].]",), + "A": ( + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Barterm.Et.Hm.IBSerif.].|.].].].]", # no flip needed + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Uterm.[.IBSerif.].Ocross.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Uterm.[.IBSerif.].Ocross.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].Fterm.[.Uterm.[.IBSerif.].Ocross.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm.[.Uterm.[.IBSerif.].Ocross.].|.].].].]", + "start.[.UC.[.UCu.[.UCb.[.V.[.V2.[.Vser.].Across.].|.].-.|.].].]", + ), + "B": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.B.[.P.P.].|.].Eterm.|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm.Eserif.|.].Eterm.[.B.[.P.P.].|.].|.].].].]", + ), + "Be": ( + "start.[.UC.[.UCu.[.UCb.[.E.[.Eterm.[.Barterm.Et.Hm.Eb.].Eterm2.[.P.|.Lterm2.-.].|.].|.].-.|.].].]", # cyrillic + "start.[.UC.[.UCu.[.UCb.[.E.[.Eterm.[.Dterm.[.Barterm.Et.Eb.].Eserif.|.].Eterm2.[.P.|.Lterm2.-.].|.].|.].-.|.].].]", + ), + "C": ("start.[.UC.[.UCb.[.D.[.Dterm.[.O.[.Oterm.].].Dterm2.[.C.|.].|.].].].]",), + "D": ( + "start.[.UC.[.UCb.[.D.[.Dterm.Dterm.[.O.[.Oterm.].].|.].].].]", + "start.[.UC.[.UCb.[.D.[.Dterm.[.O.[.Oterm.].].Dterm2.[.Ltserif.|.Lbserif.|.].|.].|.].].].", + "start.[.UC.[.UCb.[.D.[.Dterm.[.Barterm.Et.Eb.].Dterm.[.Barterm.Et.Eb.].|.].].].]", + ), + "Delta": ("start.[.UC.[.UCu.[.UCb.[.V.[.V2.[.Delta.].].|.].-.|.].].]",), # Delta + "De": ( + "start.[.UC.[.UCu.[.UCb.[.D.[.Dterm.[.Barterm.Et.Eb.].Dterm.[.Barterm.Et.Eb.].|.].].-.|.].].]", + ), # Cyrillic + "E": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.Eserif.|.].Eterm.[.Dterm.[.Barterm.Et.Eb.].Eserif.|.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.Eserif.|.].Eterm.[.Dterm.[.O.].Eserif.|.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.Eserif.|.].Eterm.[.B.[.P.P.].|.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.Eserif.|.].Eterm.[.Barterm.Et.Hm.Eb.].|.].|.].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.O.Ocross.].Eterm.[.Dterm2.Eserif.|.].|.].].].]", + ), + "Eth": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm.[.O.].Eserif.|.].Eterm.[.Barterm.Et.Hm.Eb.].|.].|.].].]", + ), + "F": ("start.[.UC.[.UCb.[.F.[.Fterm.Fterm2.[.Lterm2.Eserif.|.].|.].].].]",), + "G": ( + "start.[.UC.[.UCb.[.D.[.Dterm.[.O.].Dterm2.[.C.[.Cserif.[.G.].Cserif.-.].|.].|.].].].]", + ), + "Gamma": ( + "start.[.UC.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm2.|.].].].]", + ), # Gamma + "H": ( + "start.[.UC.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm.[.Barterm.Hm.ITSerif.IBSerif.].|.].].].]", + "start.[.UC.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm2.[.R.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm2.[.Rblock.[.IBSerif.|.].|.].|.].].].]", + ), + "Che": ( + "start.[.UC.[.UCu.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm2.[.Rblock.[.IBSerif.|.].|.].|.].].-.|.].].]", # Cyrillic + "start.[.UC.[.UCu.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm2.[.R.[.IBSerif.|.].|.].|.].].-.|.].].]", + ), + "Heng": ( + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Ltserif.|.R.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm.[.Ltserif.|.Rblock.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm.[.Ltserif.|.R.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm.[.Ltserif.|.Rblock.[.IBSerif.|.].|.].|.].].].]", + ), + "I": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Bartop.[.ITSerif.].].Barbot2.[.Barbot.[.IBSerif.].].].].].]", + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Bartop.[.Tt.].].Barbot2.[.Barbot.[.Tb.].].].].].]", + ), + "J": ( + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Uterm.[.IBSerif.].].Lterm2.|.].].-.|.].].]", + ), + "K": ( + "start.[.UC.[.UCu.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xnw.].Xlr.[.Xne.-.|.Xvt.Xvb.ITSerif.].-.|.].].-.|.].].]", + "start.[.UC.[.UCb.[.H.[.Hterm.[.Barterm.Hm.ITSerif.IBSerif.].Hterm.[.R.[.IBSerif.|.].|.R.[.IBSerif.|.].-.|.].|.].].].]", + ), + "Zhe": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Psi.[.IBSerif.R.[.IBSerif.|.].R.[.IBSerif.|.].|.].-.].Barbot2.[.Psi.[.IBSerif.R.[.IBSerif.|.].R.[.IBSerif.|.].|.].].].].].]", + ), # Cyrillic + "L": ( + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm2.|.].|.].-.|.].].]", + ), + "Lambda": ("start.[.UC.[.UCu.[.UCb.[.V.[.V2.[.Vser.].].|.].-.|.].].]",), # Lambda + "M": ( + "start.[.UC.[.UCu.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xvt.Xvb.ITSerif.].Xlr.[.Xnw.Xvt.Xvt.-.IBSerif.].-.|.].].-.|.].].]", + "start.[.UC.[.UCb.[.V.[.V2.[.M.[.IBSerif.IBSerif.|.].].].|.].].]", + ), + "N": ( + "start.[.UC.[.UCu.[.UCb.[.X.[.Xlr.[.Xnw.Xvt.Xvt.-.IBSerif.].Xlr.[.Xnw.Xvt.Xvt.-.IBSerif.].-.|.].].-.|.].].]", + "start.[.UC.[.UCb.[.L.[.Lterm.[.Uterm.[.IBSerif.].].Lterm.[.Barterm.Et.IBSerif.].|.].|.].].]", + ), + "NN": ( + "start.[.UC.[.UCu.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xvt.Xvb.ITSerif.].Xlr.[.Xne.-.|.Xvt.Xvb.ITSerif.].-.|.].].-.|.].].]", + ), # Cyrillic I + "O": ("start.[.UC.[.UCb.[.D.[.Dterm.[.O.].Dterm.[.O.].|.].].].]",), + "P": ( + "start.[.UC.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm2.[.P.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Ltserif.|.R.[.IBSerif.|.].|.].Fterm2.[.P.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Ltserif.|.Rblock.[.IBSerif.|.].|.].Fterm2.[.P.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm2.[.P.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].Fterm2.[.P.|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm2.[.P.|.].|.].].].]", + ), + "PL": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm.[.Barterm.Et.Eb.].Eserif.|.].Eterm2.[.P.|.Lterm2.-.].|.].].].]", + "start.[.UC.[.UCb.[.E.[.Eterm.[.Barterm.Et.Hm.Eb.].Eterm2.[.P.|.Lterm2.[.Cserif.-.|.].-.].|.].].].]", + ), + "Phi": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop.[.ITSerif.].Barbot.[.IBSerif.].Barmid.[.P.P.|.].].].].]", + ), + "Pi": ( + "start.[.UC.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm.[.Barterm.Et.IBSerif.].|.].].].]", + ), + "Psi": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Psi.[.IBSerif.R.[.IBSerif.|.].R.[.IBSerif.|.].|.].-.].Barbot2.[.Barbot.[.IBSerif.].].].].].]", + ), + "Soft": ( + "start.[.UC.[.UCu.[.UCb.[.F.[.Fterm.[.Barterm.Et.Hm.IBSerif.].Fterm2.[.P.|.].|.].|.].-.|.].].]", # Cyrillic Yeru/Soft/Hard + "start.[.UC.[.UCu.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm2.[.P.|.].|.].|.].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.F.[.Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].Fterm2.[.P.|.].|.].|.].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.F.[.Fterm.[.Ltserif.|.Rblock.[.IBSerif.|.].|.].Fterm2.[.P.|.].|.].|.].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm2.[.P.|.].|.].|.].-.|.].].]", + ), + "Q": ( + "start.[.UC.[.UCb.[.D.[.Dterm.[.O.[.Oterm.].].Dterm.[.O.[.Q.|.].].|.].].].]", + ), + "R": ( + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.P.|.R.[.IBSerif.|.].|.].Fterm.[.Barterm.Et.Hm.IBSerif.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].].].]", + ), + "Ya": ( + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Barterm.Et.IBSerif.].Eserif.|.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Lterm.[.Uterm.[.IBSerif.].].Eserif.|.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].|.].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.P.|.R.[.IBSerif.|.].|.].Fterm.[.Barterm.Et.Hm.IBSerif.].|.].].].]", + "start.[.UC.[.UCb.[.F.[.Fterm.[.Uterm.[.IBSerif.].Ocross.].Fterm.[.P.|.R.[.IBSerif.|.].|.].|.].|.].].]", + ), + "S": ( + "start.[.UC.[.UCb.[.E.[.Eterm2.[.P.|.Lterm2.-.].|.Eterm2.[.P.|.Lterm2.-.].-.].|.].].]", + ), + "Sigma": ( + "start.[.UC.[.UCb.[.X.[.Xtb.[.Xnw.Xh.|.Lterm2.|.].Xtb.[.Xne.Xh.Lterm2.].-.|.].].].]", + ), + "T": ( + "start.[.UC.[.UCb.[.Bar.[.Bartop2.[.Bartop.[.Tt.].].Barbot2.[.Barbot.[.IBSerif.].].].].].]", + "start.[.UC.[.UCb.[.Bar.[.Bartop.[.ITSerif.].Barbot.[.IBSerif.].Barmid.[.Hm.Eserif.Hm.|.Eserif.|.].].].].]", + ), + "Theta": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.O.Ocross.].Eterm.[.O.Ocross.].|.].].].]", + ), + "Thorn": ( + "start.[.UC.[.UCu.[.UCb.[.Bar.[.Bartop.[.ITSerif.].Barbot.[.IBSerif.].Barmid.[.P.|.].].].-.|.].].]", + ), + "U": ( + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm.[.Barterm.Et.IBSerif.].|.].|.].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm.[.Uterm.[.IBSerif.].].|.].].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Uterm.[.IBSerif.].].Lterm.[.Uterm.[.IBSerif.].].|.].].-.|.].].]", + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm.[.Barterm.Et.IBSerif.].|.].].-.|.].].]", + ), + "Tse": ( + "start.[.UC.[.UCu.[.UCb.[.L.[.Lterm.[.Barterm.Et.IBSerif.].Lterm.[.Barterm.Et.IBSerif.].|.].].-.|.].].]", + ), # Cyrillic + "V": ("start.[.UC.[.UCb.[.V.[.V2.[.Vser.].].|.].].]",), + "W": ( + "start.[.UC.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xvt.Xvb.ITSerif.].Xlr.[.Xnw.Xvt.Xvt.-.IBSerif.].-.|.].].].]", + "start.[.UC.[.UCu.[.UCb.[.V.[.V2.[.M.[.IBSerif.IBSerif.|.].].].|.].-.|.].].]", + ), + "X": ( + "start.[.UC.[.UCu.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xnw.].Xlr.[.Xne.-.|.Xnw.].-.|.].].-.|.].].]", + "start.[.UC.[.UCb.[.H.[.Hterm.[.R.|.R.-.|.].Hterm.[.R.|.R.-.|.].|.].].].]", + ), + "Xi": ( + "start.[.UC.[.UCb.[.E.[.Eterm.[.Dterm2.[.Ltserif.|.Lbserif.|.].Eserif.|.].Eterm.[.Dterm2.[.Ltserif.|.Lbserif.|.].Eserif.|.].|.].|.].].]", + ), + "Y": ("start.[.UC.[.UCb.[.X.[.Xlr.[.Xne.-.|.Xnw.].Xlr2.[.Xne.-.|.].-.|.].].].]",), + "Z": ( + "start.[.UC.[.UCb.[.X.[.Xtb.[.Xne.Xh.Lterm2.].Xtb.[.Xne.Xh.Lterm2.].-.|.].].].]", + ), + # Lowercase + "a": ( + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.n0.-.loop2.[.elike.[.a.crv.-.].].-.].|.].].].].]", + "start.[.lc.[.barsym.[.bar.[.n1.[.loop.].n0.-.].-.|.].].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.n0.-.loop2.[.loop.].].|.].].].].]", + ), + "carat": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.vserr.].-.|.].].].]",), + "b": ( + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.].n0.-.].].].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.].-.loop2.[.loop.].].-.].].].].]", + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.|.].n0.-.].].].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.|.].-.loop2.[.loop.].].-.].].].].]", + ), + "c": ( + "start.[.lc.[.lc2.[.osym.[.o.[.loop2.[.elike.[.crv.-.|.crv.|.].|.].].].].].]", + ), + "d": ( + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.].n0.-.].].|.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.].-.loop2.[.loop.].].-.].|.].].].]", + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.|.].n0.-.].].|.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.|.].-.loop2.[.loop.].].-.].|.].].].]", + ), + "e": ( + "start.[.lc.[.lc2.[.osym.[.o.[.loop2.[.elike.[.e.crv.-.].].].].].].]", + "start.[.lc.[.lc2.[.lc3.[.3sym.[.3.[.loop2.[.elike.[.crv.crv.-.].].].].].].].]", + ), + "epsi": ( + "start.[.lc.[.lc2.[.lc3.[.3sym.[.3.[.loop2.[.elike.[.crv.crv.-.].].].].].].].]", + ), + "f": ( + "start.[.lc.[.barsym.[.bar.[.vert.[.xtnd.[.cross.[.f0.[.j.].].].].vert.-.].].].]", + ), + "g": ( + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.[.j.[.crv.].].].n0.-.].-.|.].].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.[.j.].].-.loop2.[.loop.].].-.].-.|.].].].]", + ), + "gamma": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.vserr.y0.[.gamma.].].].].].]",), + "h": ( + "start.[.lc.[.barsym.[.bar.[.b.[.hlike.[.h.].f.].vert.-.].].].]", + "start.[.lc.[.barsym.[.bar.[.b.[.hlike.[.h.].f.|.].vert.-.].].].]", + ), + "heng": ( + "start.[.lc.[.barsym.[.bar.[.b.[.hlike.[.h.[.vert.[.xtnd.[.l.[.j.[.crv.].].].|.].-.].].f.[.j.[.crv.].].].vert.[.srf.-.|.].-.].].].]", + ), + "i": ( + "start.[.lc.[.barsym.[.bar.[.vert.vert.[.xtnd.[.idot.].-.].].-.|.].].]", + "start.[.lc.[.barsym.[.bar.[.vert.vert.[.xtnd.[.idot.].-.].|.].-.|.].].]", + ), + "j": ( + "start.[.lc.[.barsym.[.bar.[.vert.[.xtnd.[.idot.].-.].vert.[.xtnd.[.l.[.j.].].].|.].-.].].]", + ), + "k": ("start.[.lc.[.barsym.[.bar.[.k.vert.vert.-.].].].]",), + "l": ( + "start.[.lc.[.barsym.[.bar.[.vert.vert.[.xtnd.[.l.].-.].|.].-.|.].].]", + "start.[.lc.[.barsym.[.bar.[.vert.vert.[.xtnd.[.l.|.].-.].|.].-.|.].].]", + ), + "lambda": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.vserr.y0.].-.|.].].].]",), + "m": ( + "start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.m.[.h.[.vert.-.].vert.-.].].].vert.-.].].].]", + ), + "mu": ( + "start.[.lc.[.barsym.[.bar.[.b.[.hlike.[.h.[.vert.-.].].f.].vert.-.].-.|.].].]", + ), + "muu": ( + "start.[.lc.[.barsym.[.bar.[.b.[.hlike.[.m.[.h.[.vert.-.].vert.-.].].f.].vert.-.|.].-.|.].].]", + ), + "n": ("start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.h.[.vert.-.].].].vert.-.].].].]",), + "ng": ( + "start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.h.[.vert.[.xtnd.[.l.[.j.].].|.].-.].].].vert.-.].].].]", + ), + "o": ("start.[.lc.[.lc2.[.osym.[.o.[.loop2.[.loop.[.o0.|.].].].].].].]",), + "p": ( + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.].n0.-.].].-.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.].-.loop2.[.loop.].].-.].-.].].].]", + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.|.].n0.-.].].-.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.|.].-.loop2.[.loop.].].-.].-.].].].]", + ), + "q": ( + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.].n0.-.].].-.|.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.].-.loop2.[.loop.].].-.].-.|.].].].]", + "start.[.lc.[.barsym.[.bar.[.b1.[.loop.f.|.].n0.-.].].-.|.].]", + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.|.].-.loop2.[.loop.].].-.].-.|.].].].]", + ), + "r": ("start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.crv.].].vert.-.].].].]",), + "s": ("start.[.lc.[.lc2.[.lc3.[.ssym.[.s.[.crv.crv.-.|.].].].].].]",), + "t": ("start.[.lc.[.barsym.[.bar.[.vert.[.xtnd.[.cross.[.f0.].].].vert.-.].].].]",), + "u": ( + "start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.h.[.vert.-.].].].vert.-.].-.|.].].]", + ), + "uu": ( + "start.[.lc.[.barsym.[.bar.[.n.[.hlike.[.m.[.h.[.vert.-.].vert.-.].].].vert.-.].-.|.].].]", + ), + "v": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.vserr.].].].].]",), + "w": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.w.[.vserr.].].].].].]",), + "x": ("start.[.lc.[.lc2.[.dsym.[.diag.[.x.].-.diag.[.x.].|.].-.].].]",), + "y": ("start.[.lc.[.lc2.[.vsym.[.v.[.vserl.vserr.y0.].].].].]",), + "yogh": ( + "start.[.lc.[.lc2.[.dsym.[.diag.[.z.].|.diag.[.yogh.[.crv.-.].-.|.].-.].].].]", + ), + "z": ("start.[.lc.[.lc2.[.dsym.[.diag.[.z.].diag.[.z.].-.|.].|.].].]",), + "glot": ("start.[.lc.[.barsym.[.bar.[.vert.[.xtnd.[.?.|.].].vert.-.].].].]",), + "1l": ( + "start.[.lc.[.barsym.[.bar.[.vert.[.srf.[.lserif.].].vert.[.srf.[.serif.].-.].|.].].-.].]", + ), + "2l": ("start.[.lc.[.lc2.[.dsym.[.diag.[.2.].diag.[.z.].-.|.].|.].].]",), + "3l": ( + "start.[.lc.[.lc2.[.dsym.[.diag.[.z.].|.diag.[.yogh.[.crv.-.].-.|.].-.].].].]", + ), + "6l": ( + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.[.j.].].-.loop2.[.loop.].-.].-.].].].].]", + ), + "7l": ("start.[.lc.[.lc2.[.dsym.[.diag.[.z.].diag.[.7.].-.|.].|.].].]",), + "8l": ("start.[.lc.[.lc2.[.lc3.[.3sym.[.3.[.loop2.[.loop.[.30.|.].].].].].].].]",), + "9l": ( + "start.[.lc.[.lc2.[.lc3.[.asym.[.abase.[.b0.[.f.[.j.].].-.loop2.[.loop.].-.].|.].].].].]", + ), + "0l": ("start.[.lc.[.lc2.[.osym.[.o.[.loop2.[.loop.[.o0.|.].].].].].].]",), +} + +space = 4 # number of unit boxes to make a " " space in string +units = 36 # pixels per unit box in font +font = "alphabet_soup/" # location of font images diff --git a/share/extensions/render_barcode.inx b/share/extensions/render_barcode.inx new file mode 100644 index 0000000..effde05 --- /dev/null +++ b/share/extensions/render_barcode.inx @@ -0,0 +1,32 @@ + + + Classic + org.inkscape.render.barcode + + + + + + + + + + + + + + + + 30 + + all + + + + + + + + diff --git a/share/extensions/render_barcode.py b/share/extensions/render_barcode.py new file mode 100755 index 0000000..b15f252 --- /dev/null +++ b/share/extensions/render_barcode.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 Martin Owens +# +# 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, USA. +# +""" +Inkscape's general barcode extension. Run from within inkscape or use the +Barcode module provided for outside or scripting. +""" + +import inkex +from barcode import get_barcode + + +class Barcode(inkex.GenerateExtension): + """ + Raw barcode Effect class, see Barcode base class. + """ + + def add_arguments(self, pars): + pars.add_argument("-l", "--height", type=int, default=30, help="Barcode Height") + pars.add_argument("-t", "--type", default="", help="Barcode Type") + pars.add_argument("-d", "--text", default="", help="Text to print on barcode") + + def generate(self): + (pos_x, pos_y) = self.svg.namedview.center + + return get_barcode( + self.options.type, + text=self.options.text, + height=self.options.height, + document=self.document, + x=pos_x, + y=pos_y, + scale=self.svg.unittouu("1px"), + ).generate() + + +if __name__ == "__main__": + Barcode().run() diff --git a/share/extensions/render_barcode_datamatrix.inx b/share/extensions/render_barcode_datamatrix.inx new file mode 100644 index 0000000..6b638e0 --- /dev/null +++ b/share/extensions/render_barcode_datamatrix.inx @@ -0,0 +1,50 @@ + + + Datamatrix + org.inkscape.render.data_matrix + Inkscape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + all + + + + + + + + diff --git a/share/extensions/render_barcode_datamatrix.py b/share/extensions/render_barcode_datamatrix.py new file mode 100755 index 0000000..5b3906c --- /dev/null +++ b/share/extensions/render_barcode_datamatrix.py @@ -0,0 +1,588 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# Copyright (C) 2009 John Beard john.j.beard@gmail.com +# +# 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. +# +""" +This extension renders a DataMatrix 2D barcode, as specified in +BS ISO/IEC 16022:2006. Only ECC200 codes are considered, as these are the only +ones recommended for an "open" system. + +The size of the DataMatrix is variable between 10x10 to 144x144 + +The absolute size of the DataMatrix modules (the little squares) is also +variable. + +If more data is given than can be contained in one DataMatrix, +more than one DataMatrices will be produced. + +Text is encoded as ASCII (the standard provides for other options, but these are +not implemented). Consecutive digits are encoded in a compressed form, halving +the space required to store them. + +The basis processing flow is; + * Convert input string to codewords (modified ASCII and compressed digits) + * Split codewords into blocks of the right size for Reed-Solomon coding + * Interleave the blocks if required + * Apply Reed-Solomon coding + * De-interleave the blocks if required + * Place the codewords into the matrix bit by bit + * Render the modules in the matrix as squares +""" + +import inkex +from inkex import Rectangle +from inkex.localization import inkex_gettext as _ + +INVALID_BIT = 2 + +# return parameters for the selected datamatrix size +# drow number of rows in each data region +# dcol number of cols in each data region +# reg_row number of rows of data regions +# reg_col number of cols of data regions +# nd number of data codewords per reed-solomon block +# nc number of ECC codewords per reed-solomon block +# inter number of interleaved Reed-Solomon blocks +SYMBOLS = { + # 'id': (nrow, ncol, drow, dcol, reg_row, reg_col, nd, nc, inter) + "sq10": (10, 10, 8, 8, 1, 1, 3, 5, 1), + "sq12": (12, 12, 10, 10, 1, 1, 5, 7, 1), + "sq14": (14, 14, 12, 12, 1, 1, 8, 10, 1), + "sq16": (16, 16, 14, 14, 1, 1, 12, 12, 1), + "sq18": (18, 18, 16, 16, 1, 1, 18, 14, 1), + "sq20": (20, 20, 18, 18, 1, 1, 22, 18, 1), + "sq22": (22, 22, 20, 20, 1, 1, 30, 20, 1), + "sq24": (24, 24, 22, 22, 1, 1, 36, 24, 1), + "sq26": (26, 26, 24, 24, 1, 1, 44, 28, 1), + "sq32": (32, 32, 14, 14, 2, 2, 62, 36, 1), + "sq36": (36, 36, 16, 16, 2, 2, 86, 42, 1), + "sq40": (40, 40, 18, 18, 2, 2, 114, 48, 1), + "sq44": (44, 44, 20, 20, 2, 2, 144, 56, 1), + "sq48": (48, 48, 22, 22, 2, 2, 174, 68, 1), + "sq52": (52, 52, 24, 24, 2, 2, 102, 42, 2), + "sq64": (64, 64, 14, 14, 4, 4, 140, 56, 2), + "sq72": (72, 72, 16, 16, 4, 4, 92, 36, 4), + "sq80": (80, 80, 18, 18, 4, 4, 114, 48, 4), + "sq88": (88, 88, 20, 20, 4, 4, 144, 56, 4), + "sq96": (96, 96, 22, 22, 4, 4, 174, 68, 4), + "sq104": (104, 104, 24, 24, 4, 4, 136, 56, 6), + "sq120": (120, 120, 18, 18, 6, 6, 175, 68, 6), + "sq132": (132, 132, 20, 20, 6, 6, 163, 62, 8), + # there are two separate sections of the data matrix with different interleaving + # and reed-solomon parameters. this will be handled separately. + "sq144": (144, 144, 22, 22, 6, 6, 0, 0, 0), + "rect8x18": (8, 18, 6, 16, 1, 1, 5, 7, 1), + "rect8x32": (8, 32, 6, 14, 1, 2, 10, 11, 1), + "rect12x26": (12, 26, 10, 24, 1, 1, 16, 14, 1), + "rect12x36": (12, 36, 10, 16, 1, 2, 22, 18, 1), + "rect16x36": (16, 36, 14, 16, 1, 2, 32, 24, 1), + "rect16x48": (16, 48, 14, 22, 1, 2, 49, 28, 1), +} + + +# CODEWORD STREAM GENERATION ========================================= +# take the text input and return the codewords, +# including the Reed-Solomon error-correcting codes. +# ===================================================================== + + +def get_codewords(text, nd, nc, inter, size144): + # convert the data to the codewords + data = list(encode_to_ascii(text)) + + if not size144: # render a "normal" datamatrix + data_blocks = partition_data( + data, nd * inter + ) # partition into data blocks of length nd*inter -> inter Reed-Solomon block + + data_blocks = interleave( + data_blocks, inter + ) # interleave consecutive inter blocks if required + + data_blocks = reed_solomon( + data_blocks, nd, nc + ) # generate and append the Reed-Solomon codewords + + data_blocks = combine_interleaved( + data_blocks, inter, nd, nc, False + ) # concatenate Reed-Solomon blocks bound for the same datamatrix + + else: # we have a 144x144 datamatrix + data_blocks = partition_data( + data, 1558 + ) # partition the data into datamtrix-sized chunks (1558 =156*8 + 155*2 ) + + for i in range(len(data_blocks)): # for each datamtrix + + inter = 8 + nd = 156 + nc = 62 + block1 = data_blocks[i][0 : 156 * 8] + block1 = interleave([block1], inter) # interleave into 8 blocks + block1 = reed_solomon( + block1, nd, nc + ) # generate and append the Reed-Solomon codewords + + inter = 2 + nd = 155 + nc = 62 + block2 = data_blocks[i][156 * 8 :] + block2 = interleave([block2], inter) # interleave into 2 blocks + block2 = reed_solomon( + block2, nd, nc + ) # generate and append the Reed-Solomon codewords + + blocks = block1 + blocks.extend(block2) + + blocks = combine_interleaved(blocks, 10, nd, nc, True) + + data_blocks[i] = blocks[0] + + return data_blocks + + +# Takes a codeword stream and splits up into "inter" blocks. +# eg interleave( [1,2,3,4,5,6], 2 ) -> [1,3,5], [2,4,6] +def interleave(blocks, inter): + if inter == 1: # if we don't have to interleave, just return the blocks + return blocks + else: + result = [] + for block in blocks: # for each codeword block in the stream + block_length = int(len(block) / inter) # length of each interleaved block + inter_blocks = [ + [0] * block_length for i in range(inter) + ] # the interleaved blocks + + for i in range(block_length): # for each element in the interleaved blocks + for j in range(inter): # for each interleaved block + inter_blocks[j][i] = block[i * inter + j] + + result.extend(inter_blocks) # add the interleaved blocks to the output + + return result + + +# Combine interleaved blocks into the groups for the same datamatrix +# +# e.g combine_interleaved( [[d1, d3, d5, e1, e3, e5], [d2, d4, d6, e2, e4, e6]], 2, 3, 3 ) +# --> [[d1, d2, d3, d4, d5, d6, e1, e2, e3, e4, e5, e6]] +def combine_interleaved(blocks, inter, nd, nc, size144): + if inter == 1: # the blocks aren't interleaved + return blocks + else: + result = [] + for i in range( + len(blocks) // inter + ): # for each group of "inter" blocks -> one full datamatrix + data_codewords = [] # interleaved data blocks + + if size144: + nd_range = 1558 # 1558 = 156*8 + 155*2 + nc_range = 620 # 620 = 62*8 + 62*2 + else: + nd_range = nd * inter + nc_range = nc * inter + + for j in range(nd_range): # for each codeword in the final list + data_codewords.append(blocks[i * inter + j % inter][j // inter]) + + for j in range(nc_range): # for each block, add the ecc codewords + data_codewords.append(blocks[i * inter + j % inter][nd + j // inter]) + + result.append(data_codewords) + return result + + +def encode_to_ascii(text): + """Encode this text into chunks, ascii or digits""" + i = 0 + while i < len(text): + # check for double digits, if the next char is also a digit + if text[i].isdigit() and (i < len(text) - 1) and text[i + 1].isdigit(): + yield int(text[i] + text[i + 1]) + 130 + i += 2 # move on 2 characters + else: # encode as a normal ascii, + yield ord(text[i]) + 1 # codeword is ASCII value + 1 (ISO 16022:2006 5.2.3) + i += 1 # next character + + +# partition data into blocks of the appropriate size to suit the +# Reed-Solomon block being used. +# e.g. partition_data([1,2,3,4,5], 3) -> [[1,2,3],[4,5,PAD]] +def partition_data(data, rs_data): + PAD_VAL = 129 # PAD codeword (ISO 16022:2006 5.2.3) + data_blocks = [] + i = 0 + while i < len(data): + if len(data) >= i + rs_data: # we have a whole block in our data + data_blocks.append(data[i : i + rs_data]) + i = i + rs_data + else: # pad out with the pad codeword + data_block = data[i : len(data)] # add any remaining data + pad_pos = len(data) + padded = False + while ( + len(data_block) < rs_data + ): # and then pad with randomised pad codewords + if not padded: + data_block.append(PAD_VAL) # add a normal pad codeword + padded = True + else: + data_block.append(randomise_pad_253(PAD_VAL, pad_pos)) + pad_pos += 1 + data_blocks.append(data_block) + break + + return data_blocks + + +# Pad character randomisation, to prevent regular patterns appearing +# in the data matrix +def randomise_pad_253(pad_value, pad_position): + pseudo_random_number = ((149 * pad_position) % 253) + 1 + randomised = pad_value + pseudo_random_number + if randomised <= 254: + return randomised + else: + return randomised - 254 + + +# REED-SOLOMON ENCODING ROUTINES ===================================== + +# "prod(x,y,log,alog,gf)" returns the product "x" times "y" +def prod(x, y, log, alog, gf): + if x == 0 or y == 0: + return 0 + else: + result = alog[(log[x] + log[y]) % (gf - 1)] + return result + + +# generate the log & antilog lists: +def gen_log_alog(gf, pp): + log = [0] * gf + alog = [0] * gf + + log[0] = 1 - gf + alog[0] = 1 + + for i in range(1, gf): + alog[i] = alog[i - 1] * 2 + + if alog[i] >= gf: + alog[i] = alog[i] ^ pp + + log[alog[i]] = i + + return log, alog + + +# generate the generator polynomial coefficients: +def gen_poly_coeffs(nc, log, alog, gf): + c = [0] * (nc + 1) + c[0] = 1 + + for i in range(1, nc + 1): + c[i] = c[i - 1] + + j = i - 1 + while j >= 1: + c[j] = c[j - 1] ^ prod(c[j], alog[i], log, alog, gf) + j -= 1 + + c[0] = prod(c[0], alog[i], log, alog, gf) + + return c + + +# "ReedSolomon(wd,nd,nc)" takes "nd" data codeword values in wd[] +# and adds on "nc" check codewords, all within GF(gf) where "gf" is a +# power of 2 and "pp" is the value of its prime modulus polynomial */ +def reed_solomon(data, nd, nc): + # parameters of the polynomial arithmetic + gf = 256 # operating on 8-bit codewords -> Galois field = 2^8 = 256 + pp = 301 # prime modulus polynomial for ECC-200 is 0b100101101 = 301 (ISO 16022:2006 5.7.1) + + log, alog = gen_log_alog(gf, pp) + c = gen_poly_coeffs(nc, log, alog, gf) + + for block in data: # for each block of data codewords + + block.extend([0] * (nc + 1)) # extend to make space for the error codewords + + # generate "nc" checkwords in the list block + for i in range(0, nd): + k = block[nd] ^ block[i] + + for j in range(0, nc): + block[nd + j] = block[nd + j + 1] ^ prod( + k, c[nc - j - 1], log, alog, gf + ) + + block.pop() + + return data + + +# MODULE PLACEMENT ROUTINES=========================================== +# These routines take a steam of codewords, and place them into the +# DataMatrix in accordance with Annex F of BS ISO/IEC 16022:2006 + + +def bit(byte, bit_ch): + """bit() returns the bit'th bit of the byte""" + # the MSB is bit 1, LSB is bit 8 + return (byte >> (8 - bit_ch)) % 2 + + +def module(array, nrow, ncol, row, col, bit_ch): + """place a given bit with appropriate wrapping within array""" + if row < 0: + row = row + nrow + col = col + 4 - ((nrow + 4) % 8) + + if col < 0: + col = col + ncol + row = row + 4 - ((ncol + 4) % 8) + + array[row][col] = bit_ch + + +def place_square(case, array, nrow, ncol, row, col, char): + """Populate corner cases (0-3) and utah case (-1)""" + for i in range(8): + x, y = [ + [ + (row - 1, 0), + (row - 1, 1), + (row - 1, 2), + (0, col - 2), + (0, col - 1), + (1, col - 1), + (2, col - 1), + (3, col - 1), + ], + [ + (row - 3, 0), + (row - 2, 0), + (row - 1, 0), + (0, col - 4), + (0, col - 3), + (0, col - 2), + (0, col - 1), + (1, col - 1), + ], + [ + (row - 3, 0), + (row - 2, 0), + (row - 1, 0), + (0, col - 2), + (0, col - 1), + (1, col - 1), + (2, col - 1), + (3, col - 1), + ], + [ + (row - 1, 0), + (row - 1, col - 1), + (0, col - 3), + (0, col - 2), + (0, col - 1), + (1, col - 3), + (1, col - 2), + (1, col - 1), + ], + # "utah" places the 8 bits of a utah-shaped symbol character in ECC200 + [ + (row - 2, col - 2), + (row - 2, col - 1), + (row - 1, col - 2), + (row - 1, col - 1), + (row - 1, col), + (row, col - 2), + (row, col - 1), + (row, col), + ], + ][case][i] + module(array, nrow, ncol, x, y, bit(char, i + 1)) + return 1 + + +def place_bits(data, nrow, ncol): + """fill an nrow x ncol array with the bits from the codewords in data.""" + # initialise and fill with -1's (invalid value) + array = [[INVALID_BIT] * ncol for i in range(nrow)] + # Starting in the correct location for character #1, bit 8,... + char = 0 + row = 4 + col = 0 + while True: + + # first check for one of the special corner cases, then... + if (row == nrow) and (col == 0): + char += place_square(0, array, nrow, ncol, nrow, ncol, data[char]) + elif (row == nrow - 2) and (col == 0) and (ncol % 4): + char += place_square(1, array, nrow, ncol, nrow, ncol, data[char]) + elif (row == nrow - 2) and (col == 0) and (ncol % 8 == 4): + char += place_square(2, array, nrow, ncol, nrow, ncol, data[char]) + elif (row == nrow + 4) and (col == 2) and ((ncol % 8) == 0): + char += place_square(3, array, nrow, ncol, nrow, ncol, data[char]) + + # sweep upward diagonally, inserting successive characters,... + while (row >= 0) and (col < ncol): + if (row < nrow) and (col >= 0) and (array[row][col] == INVALID_BIT): + char += place_square(-1, array, nrow, ncol, row, col, data[char]) + row -= 2 + col += 2 + + row += 1 + col += 3 + + # & then sweep downward diagonally, inserting successive characters,... + while (row < nrow) and (col >= 0): + if (row >= 0) and (col < ncol) and (array[row][col] == INVALID_BIT): + char += place_square(-1, array, nrow, ncol, row, col, data[char]) + row += 2 + col -= 2 + + row += 3 + col += 1 + + # ... until the entire array is scanned + if not ((row < nrow) or (col < ncol)): + break + + # Lastly, if the lower righthand corner is untouched, fill in fixed pattern */ + if array[nrow - 1][ncol - 1] == INVALID_BIT: + array[nrow - 1][ncol - 2] = 0 + array[nrow - 1][ncol - 1] = 1 + array[nrow - 2][ncol - 1] = 0 + array[nrow - 2][ncol - 2] = 1 + + return array # return the array of 1's and 0's + + +def add_finder_pattern(array, data_nrow, data_ncol, reg_row, reg_col): + # get the total size of the datamatrix + nrow = (data_nrow + 2) * reg_row + ncol = (data_ncol + 2) * reg_col + + datamatrix = [[0] * ncol for i in range(nrow)] # initialise and fill with 0's + + for i in range(reg_col): # for each column of data regions + for j in range(nrow): + datamatrix[j][i * (data_ncol + 2)] = 1 # vertical black bar on left + datamatrix[j][i * (data_ncol + 2) + data_ncol + 1] = ( + j % 2 + ) # alternating blocks + + for i in range(reg_row): # for each row of data regions + for j in range(ncol): + datamatrix[i * (data_nrow + 2) + data_nrow + 1][ + j + ] = 1 # horizontal black bar at bottom + datamatrix[i * (data_nrow + 2)][j] = (j + 1) % 2 # alternating blocks + + for i in range(data_nrow * reg_row): + for j in range(data_ncol * reg_col): + # offset by 1, plus two for every addition block + dest_col = j + 1 + 2 * (j // data_ncol) + dest_row = i + 1 + 2 * (i // data_nrow) + + datamatrix[dest_row][dest_col] = array[i][ + j + ] # transfer from the plain bit array + + return datamatrix + + +class DataMatrix(inkex.GenerateExtension): + container_label = "DataMatrix" + + def add_arguments(self, pars): + pars.add_argument("--text", default="Inkscape") + pars.add_argument("--symbol", type=self.arg_symbols, required=True) + pars.add_argument("--size", type=int, default=4) + + @staticmethod + def arg_symbols(value): + """Turn a symbol key into matrix metrics""" + try: + return SYMBOLS[value] + except KeyError: + raise inkex.AbortExtension(_("Invalid symbol size.")) + + def generate(self): + size = str(self.options.size) + style = inkex.Style({"stroke": "none", "stroke-width": "1", "fill": "#000000"}) + attribs = {"style": str(style), "height": size, "width": size} + + if not self.options.text: + raise inkex.AbortExtension(_("Please enter an input string.")) + + # create a 2d list corresponding to the 1's and 0s of the DataMatrix + encoded = self.encode(self.options.text, *self.options.symbol) + for x, y in self.render_data_matrix(encoded): + attribs.update({"x": str(x), "y": str(y)}) + yield Rectangle(**attribs) + + def encode( + self, text, nrow, ncol, data_nrow, data_ncol, reg_row, reg_col, nd, nc, inter + ): + """ + Take an input string and convert it to a sequence (or sequences) + of codewords as specified in ISO/IEC 16022:2006 (section 5.2.3) + """ + # generate the codewords including padding and ECC + codewords = get_codewords(text, nd, nc, inter, nrow == 144) + + # break up into separate arrays if more than one DataMatrix is needed + module_arrays = [] + for codeword_stream in codewords: # for each datamatrix + # place the codewords' bits across the array as modules + bit_array = place_bits( + codeword_stream, data_nrow * reg_row, data_ncol * reg_col + ) + # add finder patterns around the modules + module_arrays.append( + add_finder_pattern(bit_array, data_nrow, data_ncol, reg_row, reg_col) + ) + + return module_arrays + + def render_data_matrix(self, module_arrays): + """turn a 2D array of 1's and 0's into a set of black squares""" + ncol = self.options.symbol[1] + size = self.options.size + spacing = ncol * size * 1.5 + for i, line in enumerate(module_arrays): + height = len(line) + width = len(line[0]) + + for y in range(height): # loop over all the modules in the datamatrix + for x in range(width): + if line[y][x] == 1: # A binary 1 is a filled square + yield (x * size + i * spacing, y * size) + elif line[y][x] == INVALID_BIT: # we have an invalid bit value + inkex.errormsg(_("Invalid bit value, {}!").format(line[y][x])) + + +if __name__ == "__main__": + DataMatrix().run() diff --git a/share/extensions/render_barcode_qrcode.inx b/share/extensions/render_barcode_qrcode.inx new file mode 100644 index 0000000..3acea3c --- /dev/null +++ b/share/extensions/render_barcode_qrcode.inx @@ -0,0 +1,107 @@ + + + QR Code + org.inkscape.qr_code + https://inkscape.org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + 4 + + + + + + + + + + + + + + + + + + + + + + 0.2 + + + + + + all + + + + + + + + diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py new file mode 100755 index 0000000..5593b5e --- /dev/null +++ b/share/extensions/render_barcode_qrcode.py @@ -0,0 +1,1352 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 Kazuhiko Arase (http://www.d-project.com/) +# 2010 Bulia Byak +# 2018 Kirill Okhotnikov +# +# 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, USA. +# +""" +Provide the QR Code rendering. +""" + +from __future__ import print_function + +from itertools import product + +import inkex +from inkex import Group, Rectangle, Use, PathElement +from inkex.localization import inkex_gettext as _ + + +class QRLengthError(Exception): + def __init__(self, message): + self.message = message + + +class QRCode(object): + PAD0 = 0xEC + PAD1 = 0x11 + + def __init__(self, correction): + self.typeNumber = 1 + self.errorCorrectLevel = correction + self.qrDataList = [] + self.modules = [] + self.moduleCount = 0 + + def getTypeNumber(self): + return self.typeNumber + + def setTypeNumber(self, typeNumber): + self.typeNumber = typeNumber + + def clearData(self): + self.qrDataList = [] + + def addData(self, data): + self.qrDataList.append(data) + + def getDataCount(self): + return len(self.qrDataList) + + def getData(self, index): + return self.qrDataList[index] + + def isDark(self, row, col): + return self.modules[row][col] if self.modules[row][col] is not None else False + + def getModuleCount(self): + return self.moduleCount + + def make(self): + self._make(False, self._getBestMaskPattern()) + + def _getBestMaskPattern(self): + minLostPoint = 0 + pattern = 0 + for i in range(8): + self._make(True, i) + lostPoint = QRUtil.getLostPoint(self) + if i == 0 or minLostPoint > lostPoint: + minLostPoint = lostPoint + pattern = i + return pattern + + def _make(self, test, maskPattern): + + self.moduleCount = self.typeNumber * 4 + 17 + self.modules = [[None] * self.moduleCount for i in range(self.moduleCount)] + + self._setupPositionProbePattern(0, 0) + self._setupPositionProbePattern(self.moduleCount - 7, 0) + self._setupPositionProbePattern(0, self.moduleCount - 7) + + self._setupPositionAdjustPattern() + self._setupTimingPattern() + + self._setupTypeInfo(test, maskPattern) + + if self.typeNumber >= 7: + self._setupTypeNumber(test) + + data = QRCode._createData( + self.typeNumber, self.errorCorrectLevel, self.qrDataList + ) + + self._mapData(data, maskPattern) + + def _mapData(self, data, maskPattern): + + rows = list(range(self.moduleCount)) + cols = [ + col - 1 if col <= 6 else col for col in range(self.moduleCount - 1, 0, -2) + ] + maskFunc = QRUtil.getMaskFunction(maskPattern) + + byteIndex = 0 + bitIndex = 7 + + for col in cols: + rows.reverse() + for row in rows: + for c in range(2): + if self.modules[row][col - c] is None: + + dark = False + if byteIndex < len(data): + dark = ((data[byteIndex] >> bitIndex) & 1) == 1 + if maskFunc(row, col - c): + dark = not dark + self.modules[row][col - c] = dark + + bitIndex -= 1 + if bitIndex == -1: + byteIndex += 1 + bitIndex = 7 + + def _setupPositionAdjustPattern(self): + pos = QRUtil.getPatternPosition(self.typeNumber) + for row in pos: + for col in pos: + if self.modules[row][col] is not None: + continue + for r in range(-2, 3): + for c in range(-2, 3): + self.modules[row + r][col + c] = ( + r == -2 + or r == 2 + or c == -2 + or c == 2 + or (r == 0 and c == 0) + ) + + def _setupPositionProbePattern(self, row, col): + for r in range(-1, 8): + for c in range(-1, 8): + if ( + row + r <= -1 + or self.moduleCount <= row + r + or col + c <= -1 + or self.moduleCount <= col + c + ): + continue + self.modules[row + r][col + c] = ( + (0 <= r <= 6 and (c == 0 or c == 6)) + or (0 <= c <= 6 and (r == 0 or r == 6)) + or (2 <= r <= 4 and 2 <= c <= 4) + ) + + def _setupTimingPattern(self): + for r in range(8, self.moduleCount - 8): + if self.modules[r][6] is not None: + continue + self.modules[r][6] = r % 2 == 0 + for c in range(8, self.moduleCount - 8): + if self.modules[6][c] is not None: + continue + self.modules[6][c] = c % 2 == 0 + + def _setupTypeNumber(self, test): + bits = QRUtil.getBCHTypeNumber(self.typeNumber) + for i in range(18): + self.modules[i // 3][i % 3 + self.moduleCount - 8 - 3] = ( + not test and ((bits >> i) & 1) == 1 + ) + for i in range(18): + self.modules[i % 3 + self.moduleCount - 8 - 3][i // 3] = ( + not test and ((bits >> i) & 1) == 1 + ) + + def _setupTypeInfo(self, test, maskPattern): + + data = (self.errorCorrectLevel << 3) | maskPattern + bits = QRUtil.getBCHTypeInfo(data) + + # vertical + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 6: + self.modules[i][8] = mod + elif i < 8: + self.modules[i + 1][8] = mod + else: + self.modules[self.moduleCount - 15 + i][8] = mod + + # horizontal + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 8: + self.modules[8][self.moduleCount - i - 1] = mod + elif i < 9: + self.modules[8][15 - i - 1 + 1] = mod + else: + self.modules[8][15 - i - 1] = mod + + # fixed + self.modules[self.moduleCount - 8][8] = not test + + @staticmethod + def _createData(typeNumber, errorCorrectLevel, dataArray): + + rsBlocks = RSBlock.getRSBlocks(typeNumber, errorCorrectLevel) + + buffer = BitBuffer() + + for data in dataArray: + buffer.put(data.getMode(), 4) + buffer.put(data.getLength(), data.getLengthInBits(typeNumber)) + data.write(buffer) + + totalDataCount = sum(rsBlock.getDataCount() for rsBlock in rsBlocks) + + if buffer.getLengthInBits() > totalDataCount * 8: + raise QRLengthError( + "code length overflow. (%s>%s)" + % (buffer.getLengthInBits(), totalDataCount * 8) + ) + + # end code + if buffer.getLengthInBits() + 4 <= totalDataCount * 8: + buffer.put(0, 4) + + # padding + while buffer.getLengthInBits() % 8 != 0: + buffer.put(False, 1) + + # padding + while True: + if buffer.getLengthInBits() >= totalDataCount * 8: + break + buffer.put(QRCode.PAD0, 8) + if buffer.getLengthInBits() >= totalDataCount * 8: + break + buffer.put(QRCode.PAD1, 8) + + return QRCode._createBytes(buffer, rsBlocks) + + @staticmethod + def _createBytes(buffer, rsBlocks): + + offset = 0 + + maxDcCount = 0 + maxEcCount = 0 + + dcdata = [None] * len(rsBlocks) + ecdata = [None] * len(rsBlocks) + + for r in range(len(rsBlocks)): + + dcCount = rsBlocks[r].getDataCount() + ecCount = rsBlocks[r].getTotalCount() - dcCount + + maxDcCount = max(maxDcCount, dcCount) + maxEcCount = max(maxEcCount, ecCount) + + dcdata[r] = [0] * dcCount + for i in range(len(dcdata[r])): + dcdata[r][i] = 0xFF & buffer.getBuffer()[i + offset] + offset += dcCount + + rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount) + rawPoly = Polynomial(dcdata[r], rsPoly.getLength() - 1) + + modPoly = rawPoly.mod(rsPoly) + ecdata[r] = [0] * (rsPoly.getLength() - 1) + for i in range(len(ecdata[r])): + modIndex = i + modPoly.getLength() - len(ecdata[r]) + ecdata[r][i] = modPoly.get(modIndex) if modIndex >= 0 else 0 + + totalCodeCount = sum(rsBlock.getTotalCount() for rsBlock in rsBlocks) + + data = [0] * totalCodeCount + + index = 0 + + for i in range(maxDcCount): + for r in range(len(rsBlocks)): + if i < len(dcdata[r]): + data[index] = dcdata[r][i] + index += 1 + + for i in range(maxEcCount): + for r in range(len(rsBlocks)): + if i < len(ecdata[r]): + data[index] = ecdata[r][i] + index += 1 + + return data + + @staticmethod + def getMinimumQRCode(data, errorCorrectLevel): + qr = QRCode(correction=errorCorrectLevel) + qr.addData(data) + lv = 1 + rv = 40 + while rv - lv > 0: + mid = (3 * lv + rv) // 4 + qr.setTypeNumber(mid) + try: + qr.make() + except QRLengthError: + if mid == 40: + raise inkex.AbortExtension( + _("The string is too large to represent as QR code") + ) + lv = mid + 1 + else: + rv = mid + + qr.setTypeNumber(rv) + qr.make() + return qr + + +class Mode(object): + MODE_NUMBER = 1 << 0 + MODE_ALPHA_NUM = 1 << 1 + MODE_8BIT_BYTE = 1 << 2 + MODE_KANJI = 1 << 3 + + +class MaskPattern(object): + PATTERN000 = 0 + PATTERN001 = 1 + PATTERN010 = 2 + PATTERN011 = 3 + PATTERN100 = 4 + PATTERN101 = 5 + PATTERN110 = 6 + PATTERN111 = 7 + + +class QRUtil(object): + @staticmethod + def getPatternPosition(typeNumber): + return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1] + + PATTERN_POSITION_TABLE = [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170], + ] + + @staticmethod + def getErrorCorrectPolynomial(errorCorrectLength): + a = Polynomial([1]) + for i in range(errorCorrectLength): + a = a.multiply(Polynomial([1, QRMath.gexp(i)])) + return a + + @staticmethod + def getMaskFunction(maskPattern): + return { + MaskPattern.PATTERN000: lambda i, j: (i + j) % 2 == 0, + MaskPattern.PATTERN001: lambda i, j: i % 2 == 0, + MaskPattern.PATTERN010: lambda i, j: j % 3 == 0, + MaskPattern.PATTERN011: lambda i, j: (i + j) % 3 == 0, + MaskPattern.PATTERN100: lambda i, j: (i // 2 + j // 3) % 2 == 0, + MaskPattern.PATTERN101: lambda i, j: (i * j) % 2 + (i * j) % 3 == 0, + MaskPattern.PATTERN110: lambda i, j: ((i * j) % 2 + (i * j) % 3) % 2 == 0, + MaskPattern.PATTERN111: lambda i, j: ((i * j) % 3 + (i + j) % 2) % 2 == 0, + }[maskPattern] + + @staticmethod + def getLostPoint(qrcode): + + moduleCount = qrcode.getModuleCount() + lostPoint = 0 + + # LEVEL1 + for row in range(moduleCount): + for col in range(moduleCount): + sameCount = 0 + dark = qrcode.isDark(row, col) + for r in range(-1, 2): + if row + r < 0 or moduleCount <= row + r: + continue + for c in range(-1, 2): + if col + c < 0 or moduleCount <= col + c: + continue + if r == 0 and c == 0: + continue + if dark == qrcode.isDark(row + r, col + c): + sameCount += 1 + if sameCount > 5: + lostPoint += 3 + sameCount - 5 + + # LEVEL2 + for row in range(moduleCount - 1): + for col in range(moduleCount - 1): + count = 0 + if qrcode.isDark(row, col): + count += 1 + if qrcode.isDark(row + 1, col): + count += 1 + if qrcode.isDark(row, col + 1): + count += 1 + if qrcode.isDark(row + 1, col + 1): + count += 1 + if count == 0 or count == 4: + lostPoint += 3 + + # LEVEL3 + for row in range(moduleCount): + for col in range(moduleCount - 6): + if ( + qrcode.isDark(row, col) + and not qrcode.isDark(row, col + 1) + and qrcode.isDark(row, col + 2) + and qrcode.isDark(row, col + 3) + and qrcode.isDark(row, col + 4) + and not qrcode.isDark(row, col + 5) + and qrcode.isDark(row, col + 6) + ): + lostPoint += 40 + + for col in range(moduleCount): + for row in range(moduleCount - 6): + if ( + qrcode.isDark(row, col) + and not qrcode.isDark(row + 1, col) + and qrcode.isDark(row + 2, col) + and qrcode.isDark(row + 3, col) + and qrcode.isDark(row + 4, col) + and not qrcode.isDark(row + 5, col) + and qrcode.isDark(row + 6, col) + ): + lostPoint += 40 + + # LEVEL4 + darkCount = 0 + for col in range(moduleCount): + for row in range(moduleCount): + if qrcode.isDark(row, col): + darkCount += 1 + + ratio = abs(100 * darkCount // moduleCount // moduleCount - 50) // 5 + lostPoint += ratio * 10 + + return lostPoint + + G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) + G18 = ( + (1 << 12) + | (1 << 11) + | (1 << 10) + | (1 << 9) + | (1 << 8) + | (1 << 5) + | (1 << 2) + | (1 << 0) + ) + G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) + + @staticmethod + def getBCHTypeInfo(data): + d = data << 10 + while QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0: + d ^= QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)) + return ((data << 10) | d) ^ QRUtil.G15_MASK + + @staticmethod + def getBCHTypeNumber(data): + d = data << 12 + while QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0: + d ^= QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)) + return (data << 12) | d + + @staticmethod + def getBCHDigit(data): + digit = 0 + while data != 0: + digit += 1 + data >>= 1 + return digit + + +class QRData(object): + def __init__(self, mode, data): + self._mode = mode + self.data = data + + def getMode(self): + return self._mode + + def getData(self): + return self.data + + def getLength(self): + return len(self.data) + + # @abstractmethod + def write(self, buffer): + pass + + def getLengthInBits(self, type): + if 1 <= type < 10: # 1 - 9 + return { + Mode.MODE_NUMBER: 10, + Mode.MODE_ALPHA_NUM: 9, + Mode.MODE_8BIT_BYTE: 8, + Mode.MODE_KANJI: 8, + }[self._mode] + + elif type < 27: # 10 - 26 + return { + Mode.MODE_NUMBER: 12, + Mode.MODE_ALPHA_NUM: 11, + Mode.MODE_8BIT_BYTE: 16, + Mode.MODE_KANJI: 10, + }[self._mode] + + elif type < 41: # 27 - 40 + return { + Mode.MODE_NUMBER: 14, + Mode.MODE_ALPHA_NUM: 13, + Mode.MODE_8BIT_BYTE: 16, + Mode.MODE_KANJI: 12, + }[self._mode] + + else: + raise Exception("type:%s" % type) + + +class QR8BitByte(QRData): + def __init__(self, data): + super(QR8BitByte, self).__init__(Mode.MODE_8BIT_BYTE, data) + if isinstance(data, str): + data = data.encode("ascii", "ignore") + if not isinstance(data, bytes): + raise ValueError("Data must be in bytes!") + + def write(self, buffer): + for d in self.data: + buffer.put(ord(d), 8) + + +class QRAlphaNum(QRData): + def __init__(self, data): + super(QRAlphaNum, self).__init__(Mode.MODE_ALPHA_NUM, data) + + def write(self, buffer): + i = 0 + while i + 1 < len(self.data): + buffer.put( + QRAlphaNum._getCode(self.data[i]) * 45 + + QRAlphaNum._getCode(self.data[i + 1]), + 11, + ) + i += 2 + if i < len(self.data): + buffer.put(QRAlphaNum._getCode(self.data[i]), 6) + + @staticmethod + def _getCode(c): + if "0" <= c and c <= "9": + return ord(c) - ord("0") + elif "A" <= c and c <= "Z": + return ord(c) - ord("A") + 10 + else: + dct = { + " ": 36, + "$": 37, + "%": 38, + "*": 39, + "+": 40, + "-": 41, + ".": 42, + "/": 43, + ":": 44, + } + if c in dct.keys(): + return dct[c] + else: + raise inkex.AbortExtension( + _( + "Wrong symbol '{}' in alphanumeric representation: Should be [A-Z, 0-9] or {}" + ).format(c, dct.keys()) + ) + + +class QRNumber(QRData): + def __init__(self, data): + super(QRNumber, self).__init__(Mode.MODE_NUMBER, data) + + def write(self, buffer): + i = 0 + try: + while i + 2 < len(self.data): + num = int(self.data[i : i + 3]) + buffer.put(num, 10) + i += 3 + + if i < len(self.data): + ln = 4 if len(self.data) - i == 1 else 7 + buffer.put(int(self.data[i:]), ln) + except: + raise ValueError("The string '{}' is not a valid number".format(self.data)) + + +class QRKanji(QRData): + def __init__(self, data): + super(QRKanji, self).__init__(Mode.MODE_KANJI, data) + raise RuntimeError("Class QRKanji is not implemented") + + +class QRMath(object): + EXP_TABLE = None + LOG_TABLE = None + + @staticmethod + def _init(): + + QRMath.EXP_TABLE = [0] * 256 + for i in range(256): + QRMath.EXP_TABLE[i] = ( + 1 << i + if i < 8 + else QRMath.EXP_TABLE[i - 4] + ^ QRMath.EXP_TABLE[i - 5] + ^ QRMath.EXP_TABLE[i - 6] + ^ QRMath.EXP_TABLE[i - 8] + ) + + QRMath.LOG_TABLE = [0] * 256 + for i in range(255): + QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i + + @staticmethod + def glog(n): + if n < 1: + raise Exception("log(%s)" % n) + return QRMath.LOG_TABLE[n] + + @staticmethod + def gexp(n): + while n < 0: + n += 255 + while n >= 256: + n -= 255 + return QRMath.EXP_TABLE[n] + + +# initialize statics +QRMath._init() + + +class Polynomial(object): + def __init__(self, num, shift=0): + offset = 0 + length = len(num) + while offset < length and num[offset] == 0: + offset += 1 + self.num = num[offset:] + [0] * shift + + def get(self, index): + return self.num[index] + + def getLength(self): + return len(self.num) + + def __repr__(self): + return ",".join([str(self.get(i)) for i in range(self.getLength())]) + + def toLogString(self): + return ",".join( + [str(QRMath.glog(self.get(i))) for i in range(self.getLength())] + ) + + def multiply(self, e): + num = [0] * (self.getLength() + e.getLength() - 1) + for i in range(self.getLength()): + for j in range(e.getLength()): + num[i + j] ^= QRMath.gexp( + QRMath.glog(self.get(i)) + QRMath.glog(e.get(j)) + ) + return Polynomial(num) + + def mod(self, e): + if self.getLength() - e.getLength() < 0: + return self + ratio = QRMath.glog(self.get(0)) - QRMath.glog(e.get(0)) + num = self.num[:] + for i in range(e.getLength()): + num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio) + return Polynomial(num).mod(e) + + +class RSBlock(object): + RS_BLOCK_TABLE = [ + # L + # M + # Q + # H + # 1 + [1, 26, 19], + [1, 26, 16], + [1, 26, 13], + [1, 26, 9], + # 2 + [1, 44, 34], + [1, 44, 28], + [1, 44, 22], + [1, 44, 16], + # 3 + [1, 70, 55], + [1, 70, 44], + [2, 35, 17], + [2, 35, 13], + # 4 + [1, 100, 80], + [2, 50, 32], + [2, 50, 24], + [4, 25, 9], + # 5 + [1, 134, 108], + [2, 67, 43], + [2, 33, 15, 2, 34, 16], + [2, 33, 11, 2, 34, 12], + # 6 + [2, 86, 68], + [4, 43, 27], + [4, 43, 19], + [4, 43, 15], + # 7 + [2, 98, 78], + [4, 49, 31], + [2, 32, 14, 4, 33, 15], + [4, 39, 13, 1, 40, 14], + # 8 + [2, 121, 97], + [2, 60, 38, 2, 61, 39], + [4, 40, 18, 2, 41, 19], + [4, 40, 14, 2, 41, 15], + # 9 + [2, 146, 116], + [3, 58, 36, 2, 59, 37], + [4, 36, 16, 4, 37, 17], + [4, 36, 12, 4, 37, 13], + # 10 + [2, 86, 68, 2, 87, 69], + [4, 69, 43, 1, 70, 44], + [6, 43, 19, 2, 44, 20], + [6, 43, 15, 2, 44, 16], + # 11 + [4, 101, 81], + [1, 80, 50, 4, 81, 51], + [4, 50, 22, 4, 51, 23], + [3, 36, 12, 8, 37, 13], + # 12 + [2, 116, 92, 2, 117, 93], + [6, 58, 36, 2, 59, 37], + [4, 46, 20, 6, 47, 21], + [7, 42, 14, 4, 43, 15], + # 13 + [4, 133, 107], + [8, 59, 37, 1, 60, 38], + [8, 44, 20, 4, 45, 21], + [12, 33, 11, 4, 34, 12], + # 14 + [3, 145, 115, 1, 146, 116], + [4, 64, 40, 5, 65, 41], + [11, 36, 16, 5, 37, 17], + [11, 36, 12, 5, 37, 13], + # 15 + [5, 109, 87, 1, 110, 88], + [5, 65, 41, 5, 66, 42], + [5, 54, 24, 7, 55, 25], + [11, 36, 12, 7, 37, 13], + # 16 + [5, 122, 98, 1, 123, 99], + [7, 73, 45, 3, 74, 46], + [15, 43, 19, 2, 44, 20], + [3, 45, 15, 13, 46, 16], + # 17 + [1, 135, 107, 5, 136, 108], + [10, 74, 46, 1, 75, 47], + [1, 50, 22, 15, 51, 23], + [2, 42, 14, 17, 43, 15], + # 18 + [5, 150, 120, 1, 151, 121], + [9, 69, 43, 4, 70, 44], + [17, 50, 22, 1, 51, 23], + [2, 42, 14, 19, 43, 15], + # 19 + [3, 141, 113, 4, 142, 114], + [3, 70, 44, 11, 71, 45], + [17, 47, 21, 4, 48, 22], + [9, 39, 13, 16, 40, 14], + # 20 + [3, 135, 107, 5, 136, 108], + [3, 67, 41, 13, 68, 42], + [15, 54, 24, 5, 55, 25], + [15, 43, 15, 10, 44, 16], + # 21 + [4, 144, 116, 4, 145, 117], + [17, 68, 42], + [17, 50, 22, 6, 51, 23], + [19, 46, 16, 6, 47, 17], + # 22 + [2, 139, 111, 7, 140, 112], + [17, 74, 46], + [7, 54, 24, 16, 55, 25], + [34, 37, 13], + # 23 + [4, 151, 121, 5, 152, 122], + [4, 75, 47, 14, 76, 48], + [11, 54, 24, 14, 55, 25], + [16, 45, 15, 14, 46, 16], + # 24 + [6, 147, 117, 4, 148, 118], + [6, 73, 45, 14, 74, 46], + [11, 54, 24, 16, 55, 25], + [30, 46, 16, 2, 47, 17], + # 25 + [8, 132, 106, 4, 133, 107], + [8, 75, 47, 13, 76, 48], + [7, 54, 24, 22, 55, 25], + [22, 45, 15, 13, 46, 16], + # 26 + [10, 142, 114, 2, 143, 115], + [19, 74, 46, 4, 75, 47], + [28, 50, 22, 6, 51, 23], + [33, 46, 16, 4, 47, 17], + # 27 + [8, 152, 122, 4, 153, 123], + [22, 73, 45, 3, 74, 46], + [8, 53, 23, 26, 54, 24], + [12, 45, 15, 28, 46, 16], + # 28 + [3, 147, 117, 10, 148, 118], + [3, 73, 45, 23, 74, 46], + [4, 54, 24, 31, 55, 25], + [11, 45, 15, 31, 46, 16], + # 29 + [7, 146, 116, 7, 147, 117], + [21, 73, 45, 7, 74, 46], + [1, 53, 23, 37, 54, 24], + [19, 45, 15, 26, 46, 16], + # 30 + [5, 145, 115, 10, 146, 116], + [19, 75, 47, 10, 76, 48], + [15, 54, 24, 25, 55, 25], + [23, 45, 15, 25, 46, 16], + # 31 + [13, 145, 115, 3, 146, 116], + [2, 74, 46, 29, 75, 47], + [42, 54, 24, 1, 55, 25], + [23, 45, 15, 28, 46, 16], + # 32 + [17, 145, 115], + [10, 74, 46, 23, 75, 47], + [10, 54, 24, 35, 55, 25], + [19, 45, 15, 35, 46, 16], + # 33 + [17, 145, 115, 1, 146, 116], + [14, 74, 46, 21, 75, 47], + [29, 54, 24, 19, 55, 25], + [11, 45, 15, 46, 46, 16], + # 34 + [13, 145, 115, 6, 146, 116], + [14, 74, 46, 23, 75, 47], + [44, 54, 24, 7, 55, 25], + [59, 46, 16, 1, 47, 17], + # 35 + [12, 151, 121, 7, 152, 122], + [12, 75, 47, 26, 76, 48], + [39, 54, 24, 14, 55, 25], + [22, 45, 15, 41, 46, 16], + # 36 + [6, 151, 121, 14, 152, 122], + [6, 75, 47, 34, 76, 48], + [46, 54, 24, 10, 55, 25], + [2, 45, 15, 64, 46, 16], + # 37 + [17, 152, 122, 4, 153, 123], + [29, 74, 46, 14, 75, 47], + [49, 54, 24, 10, 55, 25], + [24, 45, 15, 46, 46, 16], + # 38 + [4, 152, 122, 18, 153, 123], + [13, 74, 46, 32, 75, 47], + [48, 54, 24, 14, 55, 25], + [42, 45, 15, 32, 46, 16], + # 39 + [20, 147, 117, 4, 148, 118], + [40, 75, 47, 7, 76, 48], + [43, 54, 24, 22, 55, 25], + [10, 45, 15, 67, 46, 16], + # 40 + [19, 148, 118, 6, 149, 119], + [18, 75, 47, 31, 76, 48], + [34, 54, 24, 34, 55, 25], + [20, 45, 15, 61, 46, 16], + ] + + def __init__(self, totalCount, dataCount): + self.totalCount = totalCount + self.dataCount = dataCount + + def getDataCount(self): + return self.dataCount + + def getTotalCount(self): + return self.totalCount + + def __repr__(self): + return "(total=%s,data=%s)" % (self.totalCount, self.dataCount) + + @staticmethod + def getRSBlocks(typeNumber, errorCorrectLevel): + rsBlock = RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel) + length = len(rsBlock) // 3 + list = [] + for i in range(length): + count = rsBlock[i * 3 + 0] + totalCount = rsBlock[i * 3 + 1] + dataCount = rsBlock[i * 3 + 2] + list += [RSBlock(totalCount, dataCount)] * count + return list + + @staticmethod + def getRsBlockTable(typeNumber, errorCorrectLevel): + return { + 1: RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0], + 0: RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1], + 3: RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2], + 2: RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3], + }[errorCorrectLevel] + + +class BitBuffer(object): + def __init__(self, inclements=32): + self.inclements = inclements + self.buffer = [0] * self.inclements + self.length = 0 + + def getBuffer(self): + return self.buffer + + def getLengthInBits(self): + return self.length + + def get(self, index): + return ((self.buffer[index // 8] >> (7 - index % 8)) & 1) == 1 + + def putBit(self, bit): + if self.length == len(self.buffer) * 8: + self.buffer += [0] * self.inclements + if bit: + self.buffer[self.length // 8] |= 0x80 >> (self.length % 8) + self.length += 1 + + def put(self, num, length): + for i in range(length): + self.putBit(((num >> (length - i - 1)) & 1) == 1) + + def __repr__(self): + return "".join( + "1" if self.get(i) else "0" for i in range(self.getLengthInBits()) + ) + + +class GridDrawer(object): + """Mechanism to draw grids of boxes""" + + def __init__(self, invert_code, smooth_factor): + self.invert_code = invert_code + self.smoothFactor = smooth_factor + self.grid = None + + def set_grid(self, grid): + if len({len(g) for g in grid}) != 1: + raise Exception("The array is not rectangular") + else: + self.grid = grid + + def row_count(self): + return len(self.grid) if self.grid is not None else 0 + + def col_count(self): + return len(self.grid[0]) if self.row_count() > 0 else 0 + + def isDark(self, col, row): + inside = col >= 0 and 0 <= row < self.row_count() and col < self.col_count() + return False if not inside else self.grid[row][col] != self.invert_code + + @staticmethod + def moveByDirection(xyd): + dm = {0: (1, 0), 1: (0, -1), 2: (-1, 0), 3: (0, 1)} + return xyd[0] + dm[xyd[2]][0], xyd[1] + dm[xyd[2]][1] + + @staticmethod + def makeDirectionsTable(): + result = [] + for cfg in product(range(2), repeat=4): + result.append([]) + for d in range(4): + if cfg[3 - d] == 0 and cfg[3 - (d - 1) % 4] != 0: + result[-1].append(d) + return result + + def createVertexesForAdvDrawer(self): + dirTable = self.makeDirectionsTable() + result = [] + # Create vertex + for row in range(self.row_count() + 1): + for col in range(self.col_count() + 1): + indx = ( + (2**0 if self.isDark(col - 0, row - 1) else 0) + + (2**1 if self.isDark(col - 1, row - 1) else 0) + + (2**2 if self.isDark(col - 1, row - 0) else 0) + + (2**3 if self.isDark(col - 0, row - 0) else 0) + ) + + for d in dirTable[indx]: + result.append((col, row, d, len(dirTable[indx]) > 1)) + + return result + + def getSmoothPosition(self, v, extraSmoothFactor=1.0): + vn = self.moveByDirection(v) + sc = extraSmoothFactor * self.smoothFactor / 2.0 + sc1 = 1.0 - sc + return (v[0] * sc1 + vn[0] * sc, v[1] * sc1 + vn[1] * sc), ( + v[0] * sc + vn[0] * sc1, + v[1] * sc + vn[1] * sc1, + ) + + +class QrCode(inkex.GenerateExtension): + """Generate QR Code Extension""" + + def add_arguments(self, pars): + pars.add_argument("--text", default="https://inkscape.org") + pars.add_argument("--typenumber", type=int, default=0) + pars.add_argument("--correctionlevel", type=int, default=0) + pars.add_argument("--qrmode", type=int, default=0) + pars.add_argument("--encoding", default="latin_1") + pars.add_argument("--modulesize", type=float, default=4.0) + pars.add_argument("--invert", type=inkex.Boolean, default="false") + pars.add_argument( + "--drawtype", + default="smooth", + choices=["smooth", "pathpreset", "selection", "symbol"], + ) + pars.add_argument( + "--smoothness", default="neutral", choices=["neutral", "greedy", "proud"] + ) + pars.add_argument("--pathtype", default="simple", choices=["simple", "circle"]) + pars.add_argument("--smoothval", type=float, default=0.2) + pars.add_argument("--symbolid", default="") + pars.add_argument("--groupid", default="") + + def generate(self): + + scale = self.svg.unittouu("1px") # convert to document units + opt = self.options + + if not opt.text: + raise inkex.AbortExtension(_("Please enter an input text")) + elif opt.drawtype == "symbol" and opt.symbolid == "": + raise inkex.AbortExtension(_("Please enter symbol id")) + + # for Python 3 ugly hack to represent bytes as str for Python2 compatibility + text_str = str(opt.text) + cmode = [QR8BitByte, QRNumber, QRAlphaNum, QRKanji][opt.qrmode] + text_data = cmode(bytes(opt.text, opt.encoding).decode("latin_1")) + + grp = Group() + grp.set("inkscape:label", "QR Code: " + text_str) + if opt.groupid: + grp.set("id", opt.groupid) + pos_x, pos_y = self.svg.namedview.center + grp.transform.add_translate(pos_x, pos_y) + if scale: + grp.transform.add_scale(scale) + + # GENERATE THE QRCODE + if opt.typenumber == 0: + # Automatic QR code size` + code = QRCode.getMinimumQRCode(text_data, opt.correctionlevel) + else: + # Manual QR code size + code = QRCode(correction=opt.correctionlevel) + code.setTypeNumber(int(opt.typenumber)) + code.addData(text_data) + code.make() + + self.boxsize = opt.modulesize + self.invert_code = opt.invert + self.margin = 4 + self.draw = GridDrawer(opt.invert, opt.smoothval) + self.draw.set_grid(code.modules) + self.render_svg(grp, opt.drawtype) + return grp + + def render_adv(self, greedy): + + verts = self.draw.createVertexesForAdvDrawer() + qrPathStr = "" + while len(verts) > 0: + vertsIndexStart = len(verts) - 1 + vertsIndexCur = vertsIndexStart + ringIndexes = [] + ci = {} + for i, v in enumerate(verts): + ci.setdefault(v[0], []).append(i) + while True: + ringIndexes.append(vertsIndexCur) + nextPos = self.draw.moveByDirection(verts[vertsIndexCur]) + nextIndexes = [i for i in ci[nextPos[0]] if verts[i][1] == nextPos[1]] + if len(nextIndexes) == 0 or len(nextIndexes) > 2: + raise Exception("Vertex " + str(next_c) + " has no connections") + elif len(nextIndexes) == 1: + vertsIndexNext = nextIndexes[0] + else: + if {verts[nextIndexes[0]][2], verts[nextIndexes[1]][2]} != { + (verts[vertsIndexCur][2] - 1) % 4, + (verts[vertsIndexCur][2] + 1) % 4, + }: + raise Exception( + "Bad next vertex directions " + + str(verts[nextIndexes[0]]) + + str(verts[nextIndexes[1]]) + ) + + # Greedy - CCW turn, proud and neutral CW turn + vertsIndexNext = ( + nextIndexes[0] + if (greedy == "g") + == ( + verts[nextIndexes[0]][2] + == (verts[vertsIndexCur][2] + 1) % 4 + ) + else nextIndexes[1] + ) + + if vertsIndexNext == vertsIndexStart: + break + + vertsIndexCur = vertsIndexNext + + posStart, _ = self.draw.getSmoothPosition(verts[ringIndexes[0]]) + qrPathStr += "M %f,%f " % self.get_svg_pos(posStart[0], posStart[1]) + for ri in range(len(ringIndexes)): + vc = verts[ringIndexes[ri]] + vn = verts[ringIndexes[(ri + 1) % len(ringIndexes)]] + if vn[2] != vc[2]: + if (greedy != "n") or not vn[3]: + # Add bezier + # Opt length http://spencermortensen.com/articles/bezier-circle/ + # c = 0.552284749 + ex = 1 - 0.552284749 + _, bs = self.draw.getSmoothPosition(vc) + _, bp1 = self.draw.getSmoothPosition(vc, ex) + bp2, _ = self.draw.getSmoothPosition(vn, ex) + bf, _ = self.draw.getSmoothPosition(vn) + qrPathStr += "L %f,%f " % self.get_svg_pos(bs[0], bs[1]) + qrPathStr += "C %f,%f %f,%f %f,%f " % ( + self.get_svg_pos(bp1[0], bp1[1]) + + self.get_svg_pos(bp2[0], bp2[1]) + + self.get_svg_pos(bf[0], bf[1]) + ) + else: + # Add straight + qrPathStr += "L %f,%f " % self.get_svg_pos(vn[0], vn[1]) + + qrPathStr += "z " + + # Delete already processed vertex + for i in sorted(ringIndexes, reverse=True): + del verts[i] + + path = PathElement() + path.set("d", qrPathStr) + return path + + def render_obsolete(self): + for row in range(self.draw.row_count()): + for col in range(self.draw.col_count()): + if self.draw.isDark(col, row): + x, y = self.get_svg_pos(col, row) + return Rectangle.new(x, y, self.boxsize, self.boxsize) + + def render_path(self, pointStr): + singlePath = self.get_icon_path_str(pointStr) + pathStr = "" + for row in range(self.draw.row_count()): + for col in range(self.draw.col_count()): + if self.draw.isDark(col, row): + x, y = self.get_svg_pos(col, row) + pathStr += "M %f,%f " % (x, y) + singlePath + " z " + + path = PathElement() + path.set("d", pathStr) + return path + + def render_selection(self): + if len(self.svg.selection) > 0: + self.options.symbolid = self.svg.selection.first().get_id() + else: + raise inkex.AbortExtension(_("Please select an element to clone")) + return self.render_symbol() + + def render_symbol(self): + symbol = self.svg.getElementById(self.options.symbolid) + if symbol is None: + raise inkex.AbortExtension( + _("Can't find symbol {}").format(self.options.symbolid) + ) + bbox = symbol.path.bounding_box() + transform = inkex.Transform( + scale=( + float(self.boxsize) / bbox.width, + float(self.boxsize) / bbox.height, + ) + ) + result = Group() + for row in range(self.draw.row_count()): + for col in range(self.draw.col_count()): + if self.draw.isDark(col, row): + x, y = self.get_svg_pos(col, row) + # Inkscape doesn't support width/height on use tags + result.append( + Use.new( + symbol, + x / transform.a, + y / transform.d, + transform=transform, + ) + ) + return result + + def render_pathpreset(self): + if self.options.pathtype == "simple": + return self.render_path("h 1 v 1 h -1") + else: + s = ( + "m 0.5,0.5 " + "c 0.2761423745,0 0.5,0.2238576255 0.5,0.5 " + "c 0,0.2761423745 -0.2238576255,0.5 -0.5,0.5 " + "c -0.2761423745,0 -0.5,-0.2238576255 -0.5,-0.5 " + "c 0,-0.2761423745 0.2238576255,-0.5 0.5,-0.5" + ) + return self.render_path(s) + + render_smooth = lambda self: self.render_adv(self.options.smoothness[0]) + + def render_svg(self, grp, drawtype): + """Render to svg""" + drawer = getattr(self, f"render_{drawtype}", self.render_obsolete) + if drawer is None: + raise Exception("Unknown draw type: " + drawtype) + + canvas_width = (self.draw.col_count() + 2 * self.margin) * self.boxsize + canvas_height = (self.draw.row_count() + 2 * self.margin) * self.boxsize + + # white background providing margin: + rect = grp.add(Rectangle.new(0, 0, canvas_width, canvas_height)) + rect.style["stroke"] = "none" + rect.style["fill"] = "black" if self.invert_code else "white" + + qrg = grp.add(Group()) + qrg.style["stroke"] = "none" + qrg.style["fill"] = "white" if self.invert_code else "black" + qrg.add(drawer()) + + def get_svg_pos(self, col, row): + return (col + self.margin) * self.boxsize, (row + self.margin) * self.boxsize + + def get_icon_path_str(self, pointStr): + result = "" + digBuffer = "" + for c in pointStr: + if c.isdigit() or c == "-" or c == ".": + digBuffer += c + else: + if len(digBuffer) > 0: + result += str(float(digBuffer) * self.boxsize) + digBuffer = "" + result += c + + if len(digBuffer) > 0: + result += str(float(digBuffer) * self.boxsize) + + return result + + +if __name__ == "__main__": + QrCode().run() diff --git a/share/extensions/render_gear_rack.inx b/share/extensions/render_gear_rack.inx new file mode 100644 index 0000000..13a744f --- /dev/null +++ b/share/extensions/render_gear_rack.inx @@ -0,0 +1,19 @@ + + + Rack Gear + org.inkscape.render.rack_gear + 100. + 10.0 + 20.0 + + all + + + + + + + + diff --git a/share/extensions/render_gear_rack.py b/share/extensions/render_gear_rack.py new file mode 100755 index 0000000..229713c --- /dev/null +++ b/share/extensions/render_gear_rack.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# +# Copyright (C) 2013 Brett Graham (hahahaha @ hahaha.org) +# +# 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. +# +""" +Generate a gear rack as SVG. +""" + +from math import acos, cos, radians, sin, sqrt, tan + +import inkex + + +def involute_intersect_angle(Rb, R): + Rb, R = float(Rb), float(R) + return (sqrt(R**2 - Rb**2) / Rb) - (acos(Rb / R)) + + +def point_on_circle(radius, angle): + x = radius * cos(angle) + y = radius * sin(angle) + return x, y + + +def points_to_svgd(p): + """ + p: list of 2 tuples (x, y coordinates) + """ + f = p[0] + p = p[1:] + svgd = "M{:.3f},{:.3f}".format(f[0], f[1]) + for x in p: + svgd += "L{:.3f},{:.3f}".format(x[0], x[1]) + return svgd + + +class RackGear(inkex.GenerateExtension): + container_label = "Rendered Gear Rack" + + def add_arguments(self, pars): + pars.add_argument("--length", type=float, default=100.0, help="Rack Length") + pars.add_argument("--spacing", type=float, default=10.0, help="Tooth Spacing") + pars.add_argument("--angle", type=float, default=20.0, help="Contact Angle") + + def generate(self): + length = self.svg.unittouu(str(self.options.length) + "px") + spacing = self.svg.unittouu(str(self.options.spacing) + "px") + angle = radians(self.options.angle) + + # generate points: list of (x, y) pairs + points = [] + x = 0 + tas = tan(angle) * spacing + while x < length: + # move along path, generating the next 'tooth' + points.append((x, 0)) + points.append((x + tas, spacing)) + points.append((x + spacing, spacing)) + points.append((x + spacing + tas, 0)) + x += spacing * 2.0 + + path = points_to_svgd(points) + + # Create SVG Path for gear + style = { + "stroke": "#000000", + "fill": "none", + "stroke-width": str(self.svg.unittouu("1px")), + } + yield inkex.PathElement(style=str(inkex.Style(style)), d=str(path)) + + +if __name__ == "__main__": + RackGear().run() diff --git a/share/extensions/render_gears.inx b/share/extensions/render_gears.inx new file mode 100644 index 0000000..94623d9 --- /dev/null +++ b/share/extensions/render_gears.inx @@ -0,0 +1,26 @@ + + + Gear + org.ekips.filter.gears + 24 + 20.0 + 20.0 + 20.0 + + + + + + + + all + + + + + + + + diff --git a/share/extensions/render_gears.py b/share/extensions/render_gears.py new file mode 100755 index 0000000..b160bc0 --- /dev/null +++ b/share/extensions/render_gears.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# +# Copyright (C) 2007 Aaron Spike (aaron @ ekips.org) +# Copyright (C) 2007 Tavmjong Bah (tavmjong @ free.fr) +# +# 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. +# +""" +Generate gears in SVG +""" + +from math import acos, cos, pi, radians, sin, sqrt + +import inkex +from inkex import PathElement + + +def involute_intersect_angle(Rb, R): + Rb, R = float(Rb), float(R) + return (sqrt(R**2 - Rb**2) / Rb) - (acos(Rb / R)) + + +def point_on_circle(radius, angle): + x = radius * cos(angle) + y = radius * sin(angle) + return x, y + + +def points_to_svgd(p): + f = p[0] + p = p[1:] + svgd = "M{:.5f},{:.5f}".format(f[0], f[1]) + for x in p: + svgd += " L{:.5f},{:.5f}".format(x[0], x[1]) + svgd += "z" + return svgd + + +class Gears(inkex.GenerateExtension): + container_label = "Rendered Gears" + + def add_arguments(self, pars): + pars.add_argument("--teeth", type=int, default=24, help="Number of teeth") + pars.add_argument("--pitch", type=float, default=20.0, help="Circular Pitch") + pars.add_argument("--angle", type=float, default=20.0, help="Pressure Angle") + pars.add_argument( + "--centerdiameter", type=float, default=20.0, help="Diameter of hole" + ) + pars.add_argument( + "--unit", default="px", help="unit for pitch and center diameter" + ) + + def generate(self): + teeth = self.options.teeth + pitch = self.svg.unittouu(str(self.options.pitch) + self.options.unit) + angle = ( + self.options.angle + ) # Angle of tangent to tooth at circular pitch wrt radial line. + centerdiameter = self.svg.unittouu( + str(self.options.centerdiameter) + self.options.unit + ) + + # print >>sys.stderr, "Teeth: %s\n" % teeth + + two_pi = 2.0 * pi + + # Pitch (circular pitch): Length of the arc from one tooth to the next) + # Pitch diameter: Diameter of pitch circle. + pitch_diameter = float(teeth) * pitch / pi + pitch_radius = pitch_diameter / 2.0 + + # Base Circle + base_diameter = pitch_diameter * cos(radians(angle)) + base_radius = base_diameter / 2.0 + + # Diametrial pitch: Number of teeth per unit length. + pitch_diametrial = float(teeth) / pitch_diameter + + # Addendum: Radial distance from pitch circle to outside circle. + addendum = 1.0 / pitch_diametrial + + # Outer Circle + outer_radius = pitch_radius + addendum + outer_diameter = outer_radius * 2.0 + + # Tooth thickness: Tooth width along pitch circle. + tooth = (pi * pitch_diameter) / (2.0 * float(teeth)) + + # Undercut? + undercut = 2.0 / (sin(radians(angle)) ** 2) + needs_undercut = teeth < undercut + + # Clearance: Radial distance between top of tooth on one gear to bottom of gap on another. + clearance = 0.0 + + # Dedendum: Radial distance from pitch circle to root diameter. + dedendum = addendum + clearance + + # Root diameter: Diameter of bottom of tooth spaces. + root_radius = pitch_radius - dedendum + root_diameter = root_radius * 2.0 + + half_thick_angle = two_pi / (4.0 * float(teeth)) + pitch_to_base_angle = involute_intersect_angle(base_radius, pitch_radius) + pitch_to_outer_angle = ( + involute_intersect_angle(base_radius, outer_radius) - pitch_to_base_angle + ) + + centers = [(x * two_pi / float(teeth)) for x in range(teeth)] + + points = [] + + for c in centers: + + # Angles + pitch1 = c - half_thick_angle + base1 = pitch1 - pitch_to_base_angle + outer1 = pitch1 + pitch_to_outer_angle + + pitch2 = c + half_thick_angle + base2 = pitch2 + pitch_to_base_angle + outer2 = pitch2 - pitch_to_outer_angle + + # Points + b1 = point_on_circle(base_radius, base1) + p1 = point_on_circle(pitch_radius, pitch1) + o1 = point_on_circle(outer_radius, outer1) + + b2 = point_on_circle(base_radius, base2) + p2 = point_on_circle(pitch_radius, pitch2) + o2 = point_on_circle(outer_radius, outer2) + + if root_radius > base_radius: + pitch_to_root_angle = pitch_to_base_angle - involute_intersect_angle( + base_radius, root_radius + ) + root1 = pitch1 - pitch_to_root_angle + root2 = pitch2 + pitch_to_root_angle + r1 = point_on_circle(root_radius, root1) + r2 = point_on_circle(root_radius, root2) + p_tmp = [r1, p1, o1, o2, p2, r2] + else: + r1 = point_on_circle(root_radius, base1) + r2 = point_on_circle(root_radius, base2) + p_tmp = [r1, b1, p1, o1, o2, p2, b2, r2] + + points.extend(p_tmp) + + path = points_to_svgd(points) + + # Create SVG Path for gear + style = { + "stroke": "#000000", + "fill": "none", + "stroke-width": str(self.svg.unittouu("1px")), + } + gear = PathElement() + gear.style = style + gear.path = path + yield gear + + if centerdiameter > 0.0: + arc = PathElement.arc((0, 0), centerdiameter / 2) + arc.style = style + yield arc + + +if __name__ == "__main__": + Gears().run() diff --git a/share/extensions/replace_font.inx b/share/extensions/replace_font.inx new file mode 100644 index 0000000..01fd456 --- /dev/null +++ b/share/extensions/replace_font.inx @@ -0,0 +1,36 @@ + + + Replace font + org.inkscape.replace_font + + org.inkscape.output.svg.inkscape + + + + + + + + + + + + + + + + + + + + + all + + + + + + + diff --git a/share/extensions/replace_font.py b/share/extensions/replace_font.py new file mode 100755 index 0000000..37b5bde --- /dev/null +++ b/share/extensions/replace_font.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2010 Craig Marshall, craig9 [at] gmail.com +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +This script finds all fonts in the current drawing that match the +specified find font, and replaces them with the specified replacement +font. + +It can also replace all fonts indiscriminately, and list all fonts +currently being used. +""" +import inkex +from inkex.localization import inkex_gettext as _ + +text_tags = [ + "{http://www.w3.org/2000/svg}tspan", + "{http://www.w3.org/2000/svg}text", + "{http://www.w3.org/2000/svg}flowRoot", + "{http://www.w3.org/2000/svg}flowPara", + "{http://www.w3.org/2000/svg}flowSpan", +] +font_attributes = ["font-family", "-inkscape-font-specification"] + + +def set_font(node, new_font, style=None): + """ + Sets the font attribute in the style attribute of node, using the + font name stored in new_font. If the style dict is open already, + it can be passed in, otherwise it will be optned anyway. + + Returns a dirty boolean flag + """ + dirty = False + if not style: + style = node.style + if style: + for att in font_attributes: + if att in style: + style[att] = new_font + node.style = style + dirty = True + return dirty + + +def find_replace_font(node, find, replace): + """ + Searches the relevant font attributes/styles of node for find, and + replaces them with replace. + + Returns a dirty boolean flag + """ + dirty = False + style = node.style + if style: + for att in font_attributes: + if style(att).strip().lower() == find: + set_font(node, replace, style) + dirty = True + return dirty + + +def is_styled_text(node): + """ + Returns true if the tag in question is a "styled" element that + can hold text. + """ + return node.tag in text_tags and "style" in node.attrib + + +def is_text(node): + """ + Returns true if the tag in question is an element that + can hold text. + """ + return node.tag in text_tags + + +def get_fonts(node): + """ + Given a node, returns a list containing all the fonts that + the node is using. + """ + fonts = [] + s = node.style + if not s: + return fonts + for a in font_attributes: + if a in s: + fonts.append(s[a]) + return fonts + + +def report_replacements(num): + """ + Sends a message to the end user showing success of failure + of the font replacement + """ + if num == 0: + inkex.errormsg( + _( + "Couldn't find anything using that font, please ensure the spelling " + "and spacing is correct." + ) + ) + + +def report_findings(findings): + """ + Tells the user which fonts were found, if any + """ + if len(findings) == 0: + inkex.errormsg(_("Didn't find any fonts in this document/selection.")) + else: + if len(findings) == 1: + inkex.errormsg(_("Found the following font only: %s") % findings[0]) + else: + inkex.errormsg(_("Found the following fonts:\n%s") % "\n".join(findings)) + + +class ReplaceFont(inkex.EffectExtension): + """ + Replaces all instances of one font with another + """ + + def add_arguments(self, pars): + pars.add_argument("--fr_find") + pars.add_argument("--fr_replace") + pars.add_argument("--r_replace") + pars.add_argument("--action") + pars.add_argument("--scope") + + def find_child_text_items(self, node): + """ + Recursive method for appending all text-type elements + to self.selected_items + """ + if is_text(node): + yield node + + for child in node: + for textchild in self.find_child_text_items(child): + yield textchild + + def relevant_items(self, scope): + """ + Depending on the scope, returns all text elements, or all + selected text elements including nested children + """ + items = [] + to_return = [] + + selected = self.svg + if scope == "selection_only": + selected = self.svg.selection.values() + + for item in selected: + items.extend(self.find_child_text_items(item)) + + if not items: + return inkex.errormsg(_("There was nothing selected")) + + return items + + def find_replace(self, nodes, find, replace): + """ + Walks through nodes, replacing fonts as it goes according + to find and replace + """ + replacements = 0 + for node in nodes: + if find_replace_font(node, find, replace): + replacements += 1 + report_replacements(replacements) + + def replace_all(self, nodes, replace): + """ + Walks through nodes, setting fonts indiscriminately. + """ + replacements = 0 + for node in nodes: + if set_font(node, replace): + replacements += 1 + report_replacements(replacements) + + def list_all(self, nodes): + """ + Walks through nodes, building a list of all fonts found, then + reports to the user with that list + """ + fonts_found = [] + for node in nodes: + for f in get_fonts(node): + if not f in fonts_found: + fonts_found.append(f) + report_findings(sorted(fonts_found)) + + def effect(self): + if not self.options.action: + return inkex.errormsg(_("Nothing to do, no action specified.")) + action = self.options.action.strip( + '"' + ) # TODO Is this a bug? (Extra " characters) + scope = self.options.scope + + relevant_items = self.relevant_items(scope) + + if action == "find_replace": + find = self.options.fr_find + if find is None or find == "": + return inkex.errormsg( + _("Please enter a search string in the find box.") + ) + find = find.strip().lower() + replace = self.options.fr_replace + if replace is None or replace == "": + return inkex.errormsg( + _("Please enter a replacement font in the replace with box.") + ) + self.find_replace(relevant_items, find, replace) + elif action == "replace_all": + replace = self.options.r_replace + if replace is None or replace == "": + return inkex.errormsg( + _("Please enter a replacement font in the replace all box.") + ) + self.replace_all(relevant_items, replace) + elif action == "list_only": + self.list_all(relevant_items) + + +if __name__ == "__main__": + ReplaceFont().run() diff --git a/share/extensions/restack.inx b/share/extensions/restack.inx new file mode 100644 index 0000000..161ad00 --- /dev/null +++ b/share/extensions/restack.inx @@ -0,0 +1,63 @@ + + + Restack + org.inkscape.filter.restack + + + + + + + + + + + + + + + + 0.00 + + + + + + + + + + + + + + + + + + + + + + + + + + path + + + + + + diff --git a/share/extensions/restack.py b/share/extensions/restack.py new file mode 100755 index 0000000..0f991e1 --- /dev/null +++ b/share/extensions/restack.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# +# Copyright (C) 2007-2011 Rob Antonishen; rob.antonishen@gmail.com +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +import random + +import inkex +from inkex.utils import KeyDict +from inkex import SvgDocumentElement +from inkex.localization import inkex_gettext as _ + +# Old settings, supported because users click 'ok' without looking. +XAN = KeyDict({"l": "left", "r": "right", "m": "center_x"}) +YAN = KeyDict({"t": "top", "b": "bottom", "m": "center_y"}) +CUSTOM_DIRECTION = {270: "tb", 90: "bt", 0: "lr", 360: "lr", 180: "rl"} + + +class Restack(inkex.EffectExtension): + """Change the z-order of objects based on their position on the canvas""" + + restack_help = staticmethod(lambda: None) + + def add_arguments(self, pars): + pars.add_argument( + "--tab", type=self.arg_method("restack"), default=self.restack_positional + ) + pars.add_argument("--direction", default="lr", help="direction to restack") + pars.add_argument("--angle", type=float, default=0.0, help="arbitrary angle") + pars.add_argument("--xanchor", default="l", help="horizontal point to compare") + pars.add_argument("--yanchor", default="t", help="vertical point to compare") + pars.add_argument( + "--zsort", default="rev", help="Restack mode based on Z-Order" + ) + pars.add_argument("--nb_direction", default="", help="Direction tab") + + def effect(self): + if not self.svg.selection: + raise inkex.AbortExtension(_("There is no selection to restack.")) + + # process selection to get list of objects to be arranged + parentnode = None + for node in self.svg.selection.filter(SvgDocumentElement): + parentnode = node + self.svg.set_selection(*list(node)) + + if parentnode is None: + parentnode = self.svg.get_current_layer() + + self.options.tab(parentnode) + + def restack_positional(self, parentnode): + """Restack based on canvas position""" + # move them to the top of the object stack in this order. + for node in sorted(self.svg.selection.values(), key=self._sort): + parentnode.append(node) + return True + + def _sort(self, node): + x, y = self.options.xanchor, self.options.yanchor + selbox = self.svg.selection.bounding_box() + direction = self.options.direction + if "custom" in self.options.nb_direction: + direction = self.options.angle + return node.bounding_box().get_anchor(x, y, direction, selbox) + + def restack_z_order(self, parentnode): + """Restack based on z-order""" + objects = list(self.svg.selection.rendering_order()) + if self.options.zsort == "rev": + objects.reverse() + elif self.options.zsort == "rand": + random.shuffle(objects) + if parentnode is not None: + for item in objects: + parentnode.append(item) + return True + + +if __name__ == "__main__": + Restack().run() diff --git a/share/extensions/rtree.inx b/share/extensions/rtree.inx new file mode 100644 index 0000000..7c3efbd --- /dev/null +++ b/share/extensions/rtree.inx @@ -0,0 +1,17 @@ + + + Random Tree + org.ekips.filter.turtle_rtree + 100.0 + 40.0 + false + + all + + + + + + diff --git a/share/extensions/rtree.py b/share/extensions/rtree.py new file mode 100755 index 0000000..728d931 --- /dev/null +++ b/share/extensions/rtree.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# Copyright (C) 2015 su_v, suv-sf@users.sf.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import inkex +from inkex import turtle as pturtle + + +class TurtleRtree(inkex.GenerateExtension): + """Create RTree Turtle path""" + + def add_arguments(self, pars): + pars.add_argument( + "--size", type=float, default=100.0, help="initial branch size" + ) + pars.add_argument( + "--minimum", type=float, default=40.0, help="minimum branch size" + ) + pars.add_argument( + "--pentoggle", + type=inkex.Boolean, + default=False, + help="Lift pen for backward steps", + ) + + def generate(self): + self.options.size = self.svg.unittouu(str(self.options.size) + "px") + self.options.minimum = self.svg.unittouu(str(self.options.minimum) + "px") + point = self.svg.namedview.center + + style = inkex.Style( + { + "stroke-linejoin": "miter", + "stroke-width": str(self.svg.unittouu("1px")), + "stroke-opacity": "1.0", + "fill-opacity": "1.0", + "stroke": "#000000", + "stroke-linecap": "butt", + "fill": "none", + } + ) + tur = pturtle.pTurtle() + tur.pu() + tur.setpos(point) + tur.pd() + tur.rtree(self.options.size, self.options.minimum, self.options.pentoggle) + return inkex.PathElement(d=tur.getPath(), style=str(style)) + + +if __name__ == "__main__": + TurtleRtree().run() diff --git a/share/extensions/rubberstretch.inx b/share/extensions/rubberstretch.inx new file mode 100644 index 0000000..63a67f7 --- /dev/null +++ b/share/extensions/rubberstretch.inx @@ -0,0 +1,16 @@ + + + Rubber Stretch + org.inkscape.path.rubber_stretch + 25 + 25 + + path + + + + + + diff --git a/share/extensions/rubberstretch.py b/share/extensions/rubberstretch.py new file mode 100755 index 0000000..eb1baf9 --- /dev/null +++ b/share/extensions/rubberstretch.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr +# +# 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. +# +""" +Distorts selected paths, stretching it vertically while squeezing horizontally. + +Amount is controlled by ratio parameter. + +Curve gives further effect by bunching the surface towards the ends. +""" + +from inkex.utils import X, Y +from pathmodifier import Diffeo +import inkex + + +class RubberStretch(Diffeo): + """Distort selected paths""" + + ratio = property(lambda self: -(self.options.ratio / 100)) + curve = property(lambda self: min(self.options.curve / 100, 0.99)) + + def add_arguments(self, pars): + pars.add_argument("-r", "--ratio", type=float, default=25) + pars.add_argument("-c", "--curve", type=float, default=25) + + def applyDiffeo(self, bpt, vects=()): + for vect in vects: + vect[0] -= bpt[0] + vect[1] -= bpt[1] + vect[1] *= -1 + bpt[1] *= -1 + bx0 = self.bbox.center.x + by0 = -self.bbox.center.y + + x, y = (bpt[0] - bx0), (bpt[1] - by0) + sx1 = ( + 1 + + self.curve + * (x / (self.bbox.width / 2) + 1) + * (x / (self.bbox.width / 2) - 1) + ) * 2**self.ratio + sy1 = ( + 1 + + self.curve + * (y / (self.bbox.height / 2) + 1) + * (y / (self.bbox.height / 2) - 1) + ) * 2**self.ratio + bpt[0] = bx0 + x * sy1 + bpt[1] = by0 + y / sx1 + for vect in vects: + dx_dx = sy1 + dx_dy = ( + x + * 2 + * self.curve + * y + / self.bbox.height + / self.bbox.height + * 2**self.ratio + ) + dy_dx = ( + -y + * 2 + * self.curve + * x + / self.bbox.width + / self.bbox.width + * 2**self.ratio + / sx1 + / sx1 + ) + dy_dy = 1 / sx1 + vect[0] = dx_dx * vect[X] + dx_dy * vect[Y] + vect[1] = dy_dx * vect[X] + dy_dy * vect[Y] + + # --spherify + # s=((x*x+y*y)/(w*w+h*h))**(-a/2) + # bpt[0]=x0+s*x + # bpt[1]=y0+s*y + # for v in vects: + # dx,dy=v + # v[0]=(1-a/2/(x*x+y*y)*2*x*x)*s*dx+( -a/2/(x*x+y*y)*2*y*x)*s*dy + # v[1]=( -a/2/(x*x+y*y)*2*x*y)*s*dx+(1-a/2/(x*x+y*y)*2*y*y)*s*dy + + for vect in vects: + vect[0] += bpt[0] + vect[1] += bpt[1] + vect[1] *= -1 + bpt[1] *= -1 + + +if __name__ == "__main__": + RubberStretch().run() diff --git a/share/extensions/scribus_export_pdf.inx b/share/extensions/scribus_export_pdf.inx new file mode 100644 index 0000000..0e054fb --- /dev/null +++ b/share/extensions/scribus_export_pdf.inx @@ -0,0 +1,41 @@ + + + Export to PDF via Scribus + com.activdesign.export.scribus + scribus_export_pdf.py + scribus + + + + + + + + + 0 + false + false + + + + + + + + + + + .pdf + application/pdf + Scribus CMYK PDF (*.PDF) + Exports the document to PDF using Scribus + + + + diff --git a/share/extensions/scribus_export_pdf.py b/share/extensions/scribus_export_pdf.py new file mode 100644 index 0000000..36cde58 --- /dev/null +++ b/share/extensions/scribus_export_pdf.py @@ -0,0 +1,199 @@ +#!/bin/env python3 +# coding=utf-8 +# +# Copyright (C) 2019 Marc Jeanmougin, Cédric Gémy, a-l-e +# +# 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 +# + + +import os +import re +import sys +import inkex +from inkex import AbortExtension +from inkex.base import TempDirMixin +from inkex.command import take_snapshot, call +from inkex.localization import inkex_gettext as _ + + +SCRIBUS_EXE = "scribus" +VERSION_REGEX = re.compile(r"(\d+)\.(\d+)\.(\d+)") + + +# several things could be taken into consideration here : +# - the fact that openDoc works on svg files is a workaround +# - the commented parts should be the correct way to do things +# and even include a possibility to add margins +# BUT currently fails to place the SVG document +# (object placed top-left instead of SVG placed top-left) +class Scribus(TempDirMixin, inkex.OutputExtension): + def add_arguments(self, arg_parser): + arg_parser.add_argument( + "--pdf-version", + type=int, + dest="pdfVersion", + default=11, + help="PDF version (e.g. integer numbers between 11 and 15, see Scribus documentation for details)", + ) + arg_parser.add_argument( + "--bleed", type=float, dest="bleed", default=0.0, help="Bleed value" + ) + arg_parser.add_argument( + "--bleed-marks", + type=inkex.Boolean, + dest="bleedMarks", + default=False, + help="Draw bleed marks", + ) + arg_parser.add_argument( + "--color-marks", + type=inkex.Boolean, + dest="colorMarks", + default=False, + help="Draw color Marks", + ) + arg_parser.add_argument( + "--intent", + type=int, + dest="intent", + default=0, + help="Rendering intent. Options: 0: Perceptual, 1: Relative Colorimetric, 2: Saturation, 3: Absolute Colorimetric", + ) + arg_parser.add_argument( + "--title", + type=str, + dest="title", + default="", + help="PDF title, required for PDF/X", + ) + # arg_parser.add_argument("--fonts", type=int, dest="fonts", default="1", + # help="Embed fonts : 0 for embedding, 1 to convert to path, 2 to prevent embedding") + + def generate_script(self, stream, width, height, icc): + margin = self.options.bleed + pdfVersion = self.options.pdfVersion + embedFonts = 1 # self.options.fonts + bleedMarks = self.options.bleedMarks + colorMarks = self.options.colorMarks + if (bleedMarks or colorMarks) and margin < 7: + raise AbortExtension( + _("You need at least 7mm bleed to show cutting marks or color marks") + ) + if bleedMarks or colorMarks: + margin = ( + margin - 7 + ) # because scribus is weird. At the time of 1.5.5, it adds 7 when those are set. + stream.write( + f""" +import scribus +import sys +icc = "{icc}" +margin = {margin} +class exportPDF(): + def __init__(self, svg=sys.argv[1], o=sys.argv[2]): + #scribus.newDocument(({width},{height}), (margin,margin,margin,margin), + # PORTRAIT, 1, UNIT_MILLIMETERS, PAGE_1, 0, 1) + #scribus.placeSVG(svg, 0, 0) + scribus.openDoc(svg) + pdf = scribus.PDFfile() + scribus.setUnit(UNIT_MILLIMETERS) + pdf.bleedl = margin + pdf.bleedr = margin + pdf.bleedt = margin + pdf.bleedb = margin + pdf.useDocBleeds = False + pdf.cropMarks = {bleedMarks} + pdf.bleedMarks = {bleedMarks} + pdf.colorMarks = {colorMarks} + pdf.version = {pdfVersion} + pdf.allowAnnots = True + pdf.allowChange = True + pdf.allowCopy = True + pdf.allowPrinting = True + pdf.noembicc = False #embed icc ! + pdf.solidpr = icc + pdf.imagepr = icc + pdf.printprofc = icc + pdf.intenti = {self.options.intent} + pdf.intents = {self.options.intent} + pdf.info = "{self.options.title}" + pdf.profiles = True + pdf.profilei = True + pdf.outdst = 1 # output destination : 0=screen, 1=printer + pdf.file = o + pdf.compress = True + pdf.compressmtd = 0 # 0 = automatic, 1 = jpeg ; 2 = zip, 3 = none + pdf.quality = 0 #max + pdf.fontEmbedding = {embedFonts} + pdf.thumbnails = True + + pdf.save() +exportPDF()""" + ) + + def save(self, stream): + scribus_version = call(SCRIBUS_EXE, "-g", "--version") + version_match = VERSION_REGEX.search(scribus_version) + if version_match is None: + raise AbortExtension( + _("Could not detect Scribus version ()").format(scribus_version) + ) + major = int(version_match.group(1)) + minor = int(version_match.group(2)) + point = int(version_match.group(3)) + if (major < 1) or (major == 1 and minor < 5): + raise AbortExtension( + _("Found Scribus {}. This extension requires Scribus 1.5.x.").format( + version_match.group(0) + ) + ) + + input_file = self.options.input_file + py_file = os.path.join(self.tempdir, "scribus.py") + svg_file = os.path.join(self.tempdir, "in.svg") + profiles = self.svg.defs.findall("svg:color-profile") + if len(profiles) == 0: + raise AbortExtension( + _("Please select a color profile in the document settings.") + ) + elif len(profiles) > 1: + raise AbortExtension( + _( + "Please only link a single color profile in the document settings. " + "No output generated." + ) + ) + iccPath = profiles[0].get("xlink:href") + + with open(input_file) as f: + with open(svg_file, "w") as f1: + for line in f: + f1.write(line) + f.close() + + pdf_file = os.path.join(self.tempdir, "out.pdf") + width = self.svg.unittouu(self.svg.get("width")) + height = self.svg.unittouu(self.svg.get("height")) + + with open(py_file, "w") as fhl: + self.generate_script(fhl, width, height, iccPath) + call(SCRIBUS_EXE, "-g", "-py", py_file, svg_file, pdf_file) + with open(pdf_file, "rb") as fhl: + stream.write(fhl.read()) + + +if __name__ == "__main__": + Scribus().run() diff --git a/share/extensions/seamless_pattern.svg b/share/extensions/seamless_pattern.svg new file mode 100644 index 0000000..c90fff0 --- /dev/null +++ b/share/extensions/seamless_pattern.svg @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Seamless pattern + Use the layers "Pattern Foreground" and "Pattern Background" on the pattern page to create your design. The separation into two layers will make it easier for you to create and edit overlapping content like a foreground drawing with a background fill. The layer named "Pattern" is for using the seamless pattern, copying it to other documents, adding opacity etc. Select the group on the page, and use Object->Pattern->Objects to Pattern to convert your creation into a fill pattern. The layer "Preview Background" provides an easy way to preview your creation if it contains transparency.Changing this layer's visibility will not alter the pattern. If an object is moved outside the pattern/page limits, it will be difficult to select it. To move it back onto the page, select the object using the rubberband selection (click and drag a selection box) with the selection tool.Then move it back onto the page, using the arrow keys or the "Align and Distribute" dialog (Shift+Ctrl+A). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Seamless Pattern + Seamless Pattern + Seamless Pattern + + diff --git a/share/extensions/setup_typography_canvas.inx b/share/extensions/setup_typography_canvas.inx new file mode 100644 index 0000000..5109962 --- /dev/null +++ b/share/extensions/setup_typography_canvas.inx @@ -0,0 +1,19 @@ + + + 1 - Setup Typography Canvas + org.inkscape.typography.setup_typography_canvas + 1000 + 750 + 700 + 500 + 250 + + all + + + + + + diff --git a/share/extensions/setup_typography_canvas.py b/share/extensions/setup_typography_canvas.py new file mode 100755 index 0000000..54599bf --- /dev/null +++ b/share/extensions/setup_typography_canvas.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# + +from typing import Union + +import inkex +from inkex.localization import inkex_gettext as _ + + +class SetupTypographyCanvas(inkex.EffectExtension): + """Resizes the canvas and creates typography-relevant guidelines""" + + def add_arguments(self, pars): + pars.add_argument("-e", "--emsize", type=int, default=1000) + pars.add_argument("-c", "--caps", type=int, default=700, help="Caps Height") + pars.add_argument("-x", "--xheight", type=int, default=500) + pars.add_argument("-a", "--ascender", type=int, default=750) + pars.add_argument("-d", "--descender", type=int, default=250) + + def create_horizontal_guideline( + self, name: str, position: Union[int, float] + ) -> inkex.BaseElement: + """Create a horizontal guideline with name and position + + Args: + name (str): the name of the guideline + position (Union[int, float]): the vertical position of the guideline + + Returns: + inkex.BaseElement: the created guideline + """ + return self.svg.namedview.add( + inkex.Guide().move_to(0, position, (0, 1)).update(inkscape__label=name) + ) + + def effect(self): + # Get all the options + emsize = self.options.emsize + ascender = self.options.ascender + caps = self.options.caps + xheight = self.options.xheight + descender = self.options.descender + + # Get access to main SVG document element + self.svg.set("width", str(emsize)) + self.svg.set("height", str(emsize)) + self.svg.set("viewBox", "0 0 " + str(emsize) + " " + str(emsize)) + + baseline = descender + # Create guidelines + self.create_horizontal_guideline(_("baseline"), baseline) + self.create_horizontal_guideline(_("ascender"), baseline + ascender) + self.create_horizontal_guideline(_("caps"), baseline + caps) + self.create_horizontal_guideline(_("xheight"), baseline + xheight) + self.create_horizontal_guideline(_("descender"), baseline - descender) + + namedview = self.svg.namedview + namedview.set("inkscape:document-units", "px") + namedview.set("inkscape:cx", str(emsize / 2.0)) + namedview.set("inkscape:cy", str(emsize / 2.0)) + + +if __name__ == "__main__": + SetupTypographyCanvas().run() diff --git a/share/extensions/spirograph.inx b/share/extensions/spirograph.inx new file mode 100644 index 0000000..bf5e764 --- /dev/null +++ b/share/extensions/spirograph.inx @@ -0,0 +1,23 @@ + + + Spirograph + org.ekips.filter.spirograph + 100.0 + 60.0 + 50.0 + + + + + 0.0 + 16 + + all + + + + + + diff --git a/share/extensions/spirograph.py b/share/extensions/spirograph.py new file mode 100755 index 0000000..69e6995 --- /dev/null +++ b/share/extensions/spirograph.py @@ -0,0 +1,152 @@ +#! /usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 Joel Holdsworth joel@airwebreathe.org.uk +# +# 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. +# + +import math +import inkex + + +class Spirograph(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument( + "--primaryr", type=float, default=100.0, help="The radius of the outer gear" + ) + pars.add_argument( + "--secondaryr", + type=float, + default=60.0, + help="The radius of the inner gear", + ) + pars.add_argument( + "--penr", + type=float, + default=50.0, + help="The distance of the pen from the inner gear", + ) + pars.add_argument( + "--gearplacement", + default="inside", + help="Selects whether the gear is inside or outside the ring", + ) + pars.add_argument( + "--rotation", + type=float, + default=0.0, + help="The number of degrees to rotate the image by", + ) + pars.add_argument( + "--quality", + type=int, + default=16, + help="The quality of the calculated output", + ) + + def effect(self): + self.options.primaryr = self.svg.unittouu(str(self.options.primaryr) + "px") + self.options.secondaryr = self.svg.unittouu(str(self.options.secondaryr) + "px") + self.options.penr = self.svg.unittouu(str(self.options.penr) + "px") + + if self.options.secondaryr == 0: + return + if self.options.quality == 0: + return + + if self.options.gearplacement.strip(" ").lower().startswith("outside"): + a = self.options.primaryr + self.options.secondaryr + flip = -1 + else: + a = self.options.primaryr - self.options.secondaryr + flip = 1 + + ratio = a / self.options.secondaryr + if ratio == 0: + return + scale = 2 * math.pi / (ratio * self.options.quality) + + rotation = -math.pi * self.options.rotation / 180 + + new = inkex.PathElement() + new.style = inkex.Style(stroke="#000000", fill="none", stroke_width="1.0") + + path_string = "" + maxPointCount = 1000 + + for i in range(maxPointCount): + + theta = i * scale + + view_center = self.svg.namedview.center + x = ( + a * math.cos(theta + rotation) + + self.options.penr * math.cos(ratio * theta + rotation) * flip + + view_center[0] + ) + y = ( + a * math.sin(theta + rotation) + - self.options.penr * math.sin(ratio * theta + rotation) + + view_center[1] + ) + + dx = ( + ( + -a * math.sin(theta + rotation) + - ratio + * self.options.penr + * math.sin(ratio * theta + rotation) + * flip + ) + * scale + / 3 + ) + dy = ( + ( + a * math.cos(theta + rotation) + - ratio * self.options.penr * math.cos(ratio * theta + rotation) + ) + * scale + / 3 + ) + + if i <= 0: + path_string += "M {},{} C {},{} ".format( + str(x), str(y), str(x + dx), str(y + dy) + ) + else: + path_string += "{},{} {},{}".format( + str(x - dx), str(y - dy), str(x), str(y) + ) + + if ( + math.fmod(i / ratio, self.options.quality) == 0 + and i % self.options.quality == 0 + ): + path_string += "Z" + break + else: + if i == maxPointCount - 1: + pass # we reached the allowed maximum of points, stop here + else: + path_string += " C {},{} ".format(str(x + dx), str(y + dy)) + + new.path = path_string + self.svg.get_current_layer().append(new) + + +if __name__ == "__main__": + Spirograph().run() diff --git a/share/extensions/straightseg.inx b/share/extensions/straightseg.inx new file mode 100644 index 0000000..1f0cdb8 --- /dev/null +++ b/share/extensions/straightseg.inx @@ -0,0 +1,16 @@ + + + Straighten Segments + org.inkscape.filter.segment_straightener + 50.0 + 1 + + path + + + + + + diff --git a/share/extensions/straightseg.py b/share/extensions/straightseg.py new file mode 100755 index 0000000..55f4d45 --- /dev/null +++ b/share/extensions/straightseg.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +"""Straintens path segments (but doesn't turn them into lines)""" +import inkex + +from inkex.bezier import percent_point + + +class SegmentStraightener(inkex.EffectExtension): + """Make segments straiter""" + + def add_arguments(self, pars): + pars.add_argument( + "-p", + "--percent", + type=float, + default=50.0, + help="move curve handles PERCENT percent closer to a straight line", + ) + pars.add_argument( + "-b", + "--behavior", + type=int, + default=1, + help="straightening behavior for cubic segments", + ) + + def effect(self): + for node in self.svg.selection.get(inkex.PathElement): + path = node.path.to_arrays() + last = [] + sub_start = [] + for cmd, params in path: + if cmd == "C": + if self.options.behavior <= 1: + # shorten handles towards end points + params[:2] = percent_point( + params[:2], last[:], self.options.percent + ) + params[2:4] = percent_point( + params[2:4], params[-2:], self.options.percent + ) + else: + # shorten handles towards thirds of the segment + dest1 = percent_point(last[:], params[-2:], 33.3) + dest2 = percent_point(params[-2:], last[:], 33.3) + params[:2] = percent_point( + params[:2], dest1[:], self.options.percent + ) + params[2:4] = percent_point( + params[2:4], dest2[:], self.options.percent + ) + elif cmd == "Q": + dest = percent_point(last[:], params[-2:], 50) + params[:2] = percent_point(params[:2], dest, self.options.percent) + if cmd == "M": + sub_start = params[-2:] + if cmd == "Z": + last = sub_start[:] + else: + last = params[-2:] + node.path = path + + +if __name__ == "__main__": + SegmentStraightener().run() diff --git a/share/extensions/svg2fxg.inx b/share/extensions/svg2fxg.inx new file mode 100644 index 0000000..f9ed756 --- /dev/null +++ b/share/extensions/svg2fxg.inx @@ -0,0 +1,14 @@ + + + FXG Output + org.inkscape.output.fxg + + .fxg + text/xml+fxg + Flash XML Graphics (*.fxg) + Adobe's XML Graphics file format + + + svg2fxg.xsl + + diff --git a/share/extensions/svg2fxg.xsl b/share/extensions/svg2fxg.xsl new file mode 100644 index 0000000..1e25264 --- /dev/null +++ b/share/extensions/svg2fxg.xsl @@ -0,0 +1,3008 @@ + + + + + + + + + + + + + + + + + + + 2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Collapsed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pad + reflect + repeat + + + + + + + linearRGB + rgb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pad + reflect + repeat + + + + + + + linearRGB + rgb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 0 + 1 + + + + + + + + + + + + nonZero + + + evenOdd + + + + + + + + nonZero + + + evenOdd + + + + nonZero + + + evenOdd + + + + + + + + nonZero + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FXG does not support dasharrays + + + + + FXG does not support dashoffsets + + + + + + + bevel + round + miter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + miter + + + + + + + + round + square + round + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + preserve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + preserve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + bold + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + Arial + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + superscript + subscript + -1000 + 1000 + + + + + % + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rl + tb + + + + rotate270 + + + + + + + + + + + + + + + + + + + + + underline + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ltr + rtl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ascent + + + + + + + + + + + + + + + + preserve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ascent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Embed('') + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FXG does not support polygons + + + + + FXG does not support polylines + + +
diff --git a/share/extensions/svg2xaml.inx b/share/extensions/svg2xaml.inx new file mode 100644 index 0000000..dea7865 --- /dev/null +++ b/share/extensions/svg2xaml.inx @@ -0,0 +1,15 @@ + + + XAML Output + org.inkscape.output.xaml + false + + .xaml + text/xml+xaml + Microsoft XAML (*.xaml) + Microsoft's GUI definition format + + + svg2xaml.xsl + + diff --git a/share/extensions/svg2xaml.xsl b/share/extensions/svg2xaml.xsl new file mode 100644 index 0000000..7036f0f --- /dev/null +++ b/share/extensions/svg2xaml.xsl @@ -0,0 +1,2987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Collapsed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + Absolute + RelativeToBoundingBox + + + + + + Pad + Reflect + Repeat + + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Absolute + RelativeToBoundingBox + + + + + + Pad + Reflect + Repeat + + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 0 + 1 + + + + + + + + + + + NonZero + + + EvenOdd + + + + + + + NonZero + + + EvenOdd + + + + NonZero + + + EvenOdd + + + + + + + + NonZero + + + + + + + + + + + + + + + + + + + + + + + + #000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bevel + Round + Miter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Round + Square + Flat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fill + + + + + + + + + + preserve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + + + + + + + + + + + + + + + + + + + + + + + Thin + ExtraLight + Light + Normal + Medium + SemiBold + Bold + ExtraBold + Black + ExtraBlack + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + Arial + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Normal + Superscript + Subscript + + % + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rl + tb + + + + rotate270 + + + + + + + + + + + + + + + + + + + + + Underline + Strikethrough + Overline + None + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LeftToRight + RightToLeft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Left + Center + Right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/svg_fonts/EMSAllure.svg b/share/extensions/svg_fonts/EMSAllure.svg new file mode 100644 index 0000000..79115cf --- /dev/null +++ b/share/extensions/svg_fonts/EMSAllure.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Allure +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Allura +Designer: Rob Leuschke, TypeSETit +Link: http://www.typesetit.com +Google font page: https://fonts.google.com/specimen/Allura + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSElfin.svg b/share/extensions/svg_fonts/EMSElfin.svg new file mode 100644 index 0000000..989b235 --- /dev/null +++ b/share/extensions/svg_fonts/EMSElfin.svg @@ -0,0 +1,236 @@ + + + + + + +Font name: EMS Elfin +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Mountains of Christmas +Designer: Crystal Kluge, Tart Workshop +Link: http://www.tartworkshop.com +Google font page: https://fonts.google.com/specimen/Mountains+of+Christmas +Note: SIL OFL per metadata; Google cites Apache License, version 2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSFelix.svg b/share/extensions/svg_fonts/EMSFelix.svg new file mode 100644 index 0000000..7ab9b16 --- /dev/null +++ b/share/extensions/svg_fonts/EMSFelix.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Felix +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Felipa +Designer: Fontstage +Link: https://twitter.com/fontstage +Google font page: https://fonts.google.com/specimen/Felipa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSNixish.svg b/share/extensions/svg_fonts/EMSNixish.svg new file mode 100644 index 0000000..6710f2b --- /dev/null +++ b/share/extensions/svg_fonts/EMSNixish.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Nixish +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Nixie One +Designer: Jovanny Lemonad +Link: http://jovanny.ru +Google font page: https://fonts.google.com/specimen/Nixie+One + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSNixishItalic.svg b/share/extensions/svg_fonts/EMSNixishItalic.svg new file mode 100644 index 0000000..df9c3ae --- /dev/null +++ b/share/extensions/svg_fonts/EMSNixishItalic.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Nixish Italic +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Nixie One +Designer: Jovanny Lemonad +Link: http://jovanny.ru +Google font page: https://fonts.google.com/specimen/Nixie+One + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSOsmotron.svg b/share/extensions/svg_fonts/EMSOsmotron.svg new file mode 100644 index 0000000..03f053c --- /dev/null +++ b/share/extensions/svg_fonts/EMSOsmotron.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Osmotron +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Orbitron (Regular) +Designer: Matt McInerney, the League of Moveable Type +Link: https://www.theleagueofmoveabletype.com +Google font page: https://fonts.google.com/specimen/Orbitron + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSReadability.svg b/share/extensions/svg_fonts/EMSReadability.svg new file mode 100644 index 0000000..88a59fe --- /dev/null +++ b/share/extensions/svg_fonts/EMSReadability.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Readability +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Source Sans Pro-Light +Designer: Paul D. Hunt, Adobe +Link: http://www.adobe.com +Google font page: https://fonts.google.com/specimen/Source+Sans+Pro + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSReadabilityItalic.svg b/share/extensions/svg_fonts/EMSReadabilityItalic.svg new file mode 100644 index 0000000..b4d8efe --- /dev/null +++ b/share/extensions/svg_fonts/EMSReadabilityItalic.svg @@ -0,0 +1,235 @@ + + + + + + +Font name: EMS Readability Italic +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Source Sans Pro-Light +Designer: Paul D. Hunt, Adobe +Link: http://www.adobe.com +Google font page: https://fonts.google.com/specimen/Source+Sans+Pro + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/EMSTech.svg b/share/extensions/svg_fonts/EMSTech.svg new file mode 100644 index 0000000..0b2f108 --- /dev/null +++ b/share/extensions/svg_fonts/EMSTech.svg @@ -0,0 +1,236 @@ + + + + + + + +Font name: EMS Tech +License: SIL Open Font License http://scripts.sil.org/OFL +Created by: Sheldon B. Michaels +SVG font conversion by: Windell H. Oskay +A derivative of: Architects Daughter +Designer: Kimberly Geswein, Kimberly Geswein Fonts +Link: http://www.kimberlygeswein.com/ +Google font page: https://fonts.google.com/specimen/Architects+Daughter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheyGothEnglish.svg b/share/extensions/svg_fonts/HersheyGothEnglish.svg new file mode 100644 index 0000000..d7e95b5 --- /dev/null +++ b/share/extensions/svg_fonts/HersheyGothEnglish.svg @@ -0,0 +1,261 @@ + + + + + + +Font name: Hershey Gothic English + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySans1.svg b/share/extensions/svg_fonts/HersheySans1.svg new file mode 100644 index 0000000..9321d2e --- /dev/null +++ b/share/extensions/svg_fonts/HersheySans1.svg @@ -0,0 +1,260 @@ + + + + + + +Font name: Hershey Sans 1-stroke + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySansMed.svg b/share/extensions/svg_fonts/HersheySansMed.svg new file mode 100644 index 0000000..d586e09 --- /dev/null +++ b/share/extensions/svg_fonts/HersheySansMed.svg @@ -0,0 +1,260 @@ + + + + + + +Font name: Hershey Sans medium + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheyScript1.svg b/share/extensions/svg_fonts/HersheyScript1.svg new file mode 100644 index 0000000..202db1e --- /dev/null +++ b/share/extensions/svg_fonts/HersheyScript1.svg @@ -0,0 +1,261 @@ + + + + + + +Font name: Hershey Script 1-stroke + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheyScriptMed.svg b/share/extensions/svg_fonts/HersheyScriptMed.svg new file mode 100644 index 0000000..3c73469 --- /dev/null +++ b/share/extensions/svg_fonts/HersheyScriptMed.svg @@ -0,0 +1,261 @@ + + + + + + +Font name: Hershey Script medium + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySerifBold.svg b/share/extensions/svg_fonts/HersheySerifBold.svg new file mode 100644 index 0000000..193977b --- /dev/null +++ b/share/extensions/svg_fonts/HersheySerifBold.svg @@ -0,0 +1,261 @@ + + + + + + +Font name: Hershey Serif bold + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySerifBoldItalic.svg b/share/extensions/svg_fonts/HersheySerifBoldItalic.svg new file mode 100644 index 0000000..9dcf9e7 --- /dev/null +++ b/share/extensions/svg_fonts/HersheySerifBoldItalic.svg @@ -0,0 +1,262 @@ + + + + + + +Font name: Hershey Serif bold italic + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySerifMed.svg b/share/extensions/svg_fonts/HersheySerifMed.svg new file mode 100644 index 0000000..22ecabd --- /dev/null +++ b/share/extensions/svg_fonts/HersheySerifMed.svg @@ -0,0 +1,260 @@ + + + + + + +Font name: Hershey Serif medium + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/HersheySerifMedItalic.svg b/share/extensions/svg_fonts/HersheySerifMedItalic.svg new file mode 100644 index 0000000..5b7a37f --- /dev/null +++ b/share/extensions/svg_fonts/HersheySerifMedItalic.svg @@ -0,0 +1,260 @@ + + + + + + +Font name: Hershey Serif medium italic + +Originally prepared in 2011 and converted to SVG fonts +in 2019 by Windell H. Oskay, www.evilmadscientist.com + +Contents adapted from emergent.unpythonic.net/software/hershey + by way of "Hershey Fonts in SVG" by Marty McGuire + http://www.thingiverse.com/thing:6168 + +------------------------------------------------------------------- +The Hershey Fonts are a set of vector fonts with a liberal license. + +USE RESTRICTION: + This distribution of the Hershey Fonts may be used by anyone for + any purpose, commercial or otherwise, providing that: + 1. The following acknowledgements must be distributed with + the font data: + - The Hershey Fonts were originally created by Dr. + A. V. Hershey while working at the U. S. + National Bureau of Standards. + - The format of the Font data in this distribution + was originally created by + James Hurt + Cognition, Inc. + 900 Technology Park Drive + Billerica, MA 01821 + (mit-eddie!ci-dandelion!hurt) + 2. The font data in this distribution may be converted into + any other format *EXCEPT* the format distributed by + the U.S. NTIS where each point is described + in eight bytes as "xxx yyy:", where xxx and yyy are + the coordinate values as ASCII numbers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/svg_fonts/OFL.txt b/share/extensions/svg_fonts/OFL.txt new file mode 100644 index 0000000..f1a20ac --- /dev/null +++ b/share/extensions/svg_fonts/OFL.txt @@ -0,0 +1,97 @@ +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/share/extensions/svgcalendar.inx b/share/extensions/svgcalendar.inx new file mode 100644 index 0000000..747771f --- /dev/null +++ b/share/extensions/svgcalendar.inx @@ -0,0 +1,144 @@ + + + Calendar + org.inkscape.render.calendar + + + 2022 + 0 + true + false + + + + + + + + + + + + true + + 3 + 6cm + 1cm + + + 0x808080FF + 0x686868FF + 0x909090FF + 0x000000FF + 0x787878FF + 0xB0B0B0FF + 0x787878FF + + + arial + arial + arial + arial + + + + January February March April May June July August September October November December + Sun Mon Tue Wed Thu Fri Sat + + Wk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/svgcalendar.py b/share/extensions/svgcalendar.py new file mode 100755 index 0000000..a21fd49 --- /dev/null +++ b/share/extensions/svgcalendar.py @@ -0,0 +1,548 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2008 Aurelio A. Heckert +# Week number option added by Olav Vitters and Nicolas Dufour (2012) +# +# 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. +# +""" +A calendar generator plugin for Inkscape, but also can be used as a standalone +command line application. +# +More on ISO week number calculation on: +http://en.wikipedia.org/wiki/ISO_week_date +(The first week of a year is the week that contains the first Thursdayof the year.) +""" + +__version__ = "0.4" + +import datetime +import calendar +import re +import sys + +import inkex +from inkex import TextElement +from inkex.localization import inkex_gettext as _ + +if sys.version_info[0] > 2: + + def unicode(stringlike, encoding): + """Compatibility for python 2 strings""" + if isinstance(stringlike, bytes): + return stringlike.decode(encoding) + return stringlike + + +class Calendar(inkex.EffectExtension): + """Generate Calendar in SVG""" + + def add_arguments(self, pars): + pars.add_argument("--tab", type=str, dest="tab") + pars.add_argument( + "--month", + type=int, + default=0, + help="Month to be generated. If 0, then the entry year will be generated.", + ) + pars.add_argument( + "--year", + type=int, + default=0, + help="Year to be generated. If 0, then the current year will be generated.", + ) + pars.add_argument( + "--fill-empty-day-boxes", + type=inkex.Boolean, + dest="fill_edb", + default=True, + help="Fill empty day boxes with next month days.", + ) + pars.add_argument( + "--show-week-number", + type=inkex.Boolean, + dest="show_weeknr", + default=False, + help="Include a week number column.", + ) + pars.add_argument( + "--start-day", default="sun", help='Week start day. ("sun" or "mon")' + ) + pars.add_argument( + "--weekend", + default="sat+sun", + help='Define the weekend days. ("sat+sun" or "sat" or "sun")', + ) + pars.add_argument( + "--auto-organize", + type=inkex.Boolean, + dest="auto_organize", + default=True, + help="Automatically set the size and positions.", + ) + pars.add_argument( + "--months-per-line", + type=int, + dest="months_per_line", + default=3, + help="Number of months side by side.", + ) + pars.add_argument( + "--month-width", + type=str, + dest="month_width", + default="6cm", + help="The width of the month days box.", + ) + pars.add_argument( + "--month-margin", + type=str, + dest="month_margin", + default="1cm", + help="The space between the month boxes.", + ) + pars.add_argument( + "--color-year", + type=inkex.Color, + dest="color_year", + default=inkex.Color(0x808080FF), + help="Color for the year header.", + ) + pars.add_argument( + "--color-month", + type=inkex.Color, + dest="color_month", + default=inkex.Color(0x686868FF), + help="Color for the month name header.", + ) + pars.add_argument( + "--color-day-name", + type=inkex.Color, + dest="color_day_name", + default=inkex.Color(0x909090FF), + help="Color for the week day names header.", + ) + pars.add_argument( + "--color-day", + type=inkex.Color, + dest="color_day", + default=inkex.Color(0x000000FF), + help="Color for the common day box.", + ) + pars.add_argument( + "--color-weekend", + type=inkex.Color, + dest="color_weekend", + default=inkex.Color(0x787878FF), + help="Color for the weekend days.", + ) + pars.add_argument( + "--color-nmd", + type=inkex.Color, + dest="color_nmd", + default=inkex.Color(0xB0B0B0FF), + help="Color for the next month day, in empty day boxes.", + ) + pars.add_argument( + "--color-weeknr", + type=inkex.Color, + dest="color_weeknr", + default=inkex.Color(0x787878FF), + help="Color for the week numbers.", + ) + pars.add_argument( + "--font-year", + type=str, + dest="font_year", + default="arial", + help="Font for the year string.", + ) + pars.add_argument( + "--font-month", + type=str, + dest="font_month", + default="arial", + help="Font for the month strings.", + ) + pars.add_argument( + "--font-day-name", + type=str, + dest="font_day_name", + default="arial", + help="Font for the days of the week strings.", + ) + pars.add_argument( + "--font-day", + type=str, + dest="font_day", + default="arial", + help="Font for the day strings.", + ) + pars.add_argument( + "--month-names", + type=str, + dest="month_names", + default="January February March " + "April May June July " + "August September October " + "November December", + help="The month names for localization.", + ) + pars.add_argument( + "--day-names", + type=str, + dest="day_names", + default="Sun Mon Tue Wed Thu Fri Sat", + help="The week day names for localization.", + ) + pars.add_argument( + "--weeknr-name", + type=str, + dest="weeknr_name", + default="Wk", + help="The week number column name for localization.", + ) + pars.add_argument( + "--encoding", + type=str, + dest="input_encode", + default="arabic", + help="The input encoding of the names.", + ) + + def validate_options(self): + """Validity check for various text inputs""" + # inkex.errormsg( self.options.input_encode ) + # Convert string names lists in real lists + month_name = re.match(r"\s*(.*[^\s])\s*", self.options.month_names) + self.options.month_names = re.split(r"\s+", month_name.group(1)) + month_name = re.match(r"\s*(.*[^\s])\s*", self.options.day_names) + self.options.day_names = re.split(r"\s+", month_name.group(1)) + + # Validate names lists + if len(self.options.month_names) != 12: + inkex.errormsg( + 'The month name list "' + + str(self.options.month_names) + + '" is invalid. Using default.' + ) + self.options.month_names = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ] + if len(self.options.day_names) != 7: + inkex.errormsg( + 'The day name list "' + + str(self.options.day_names) + + '" is invalid. Using default.' + ) + self.options.day_names = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] + # Convert year 0 to current year + if self.options.year == 0: + self.options.year = datetime.datetime.today().year + # Year 1 starts it's week at monday, obligatorily + if self.options.year == 1: + self.options.start_day = "mon" + # Set the calendar start day + if self.options.start_day == "sun": + calendar.setfirstweekday(6) + else: + calendar.setfirstweekday(0) + # Convert string numbers with unit to user space float numbers + self.options.month_width = self.svg.unittouu(self.options.month_width) + self.options.month_margin = self.svg.unittouu(self.options.month_margin) + + # initial values + month_x_pos = 0 + month_y_pos = 0 + weeknr = 0 + + def calculate_size_and_positions(self): + """month_margin month_width months_per_line auto_organize""" + self.doc_w = self.svg.unittouu(self.document.getroot().get("width")) + self.doc_h = self.svg.unittouu(self.document.getroot().get("height")) + if self.options.show_weeknr: + self.cols_before = 1 + else: + self.cols_before = 0 + if self.options.auto_organize: + if self.doc_h > self.doc_w: + self.months_per_line = 3 + else: + self.months_per_line = 4 + else: + self.months_per_line = self.options.months_per_line + # self.month_w = self.doc_w / self.months_per_line + if self.options.auto_organize: + self.month_w = (self.doc_w * 0.8) / self.months_per_line + self.month_margin = self.month_w / 10 + else: + self.month_w = self.options.month_width + self.month_margin = self.options.month_margin + self.day_w = self.month_w / (7 + self.cols_before) + self.day_h = self.month_w / 9 + self.month_h = self.day_w * 7 + if self.options.month == 0: + self.year_margin = ( + self.doc_w + + self.day_w + - (self.month_w * self.months_per_line) + - (self.month_margin * (self.months_per_line - 1)) + ) / 2 # - self.month_margin + else: + self.year_margin = (self.doc_w - self.month_w) / 2 + self.style_day = { + "font-size": str(self.day_w / 2), + "font-family": self.options.font_day, + "text-anchor": "middle", + "text-align": "center", + "fill": self.options.color_day, + } + self.style_weekend = self.style_day.copy() + self.style_weekend["fill"] = self.options.color_weekend + self.style_nmd = self.style_day.copy() + self.style_nmd["fill"] = self.options.color_nmd + self.style_month = self.style_day.copy() + self.style_month["fill"] = self.options.color_month + self.style_month["font-family"] = self.options.font_month + self.style_month["font-size"] = str(self.day_w / 1.5) + self.style_month["font-weight"] = "bold" + self.style_day_name = self.style_day.copy() + self.style_day_name["fill"] = self.options.color_day_name + self.style_day_name["font-family"] = self.options.font_day_name + self.style_day_name["font-size"] = str(self.day_w / 3) + self.style_year = self.style_day.copy() + self.style_year["fill"] = self.options.color_year + self.style_year["font-family"] = self.options.font_year + self.style_year["font-size"] = str(self.day_w * 2) + self.style_year["font-weight"] = "bold" + self.style_weeknr = self.style_day.copy() + self.style_weeknr["fill"] = self.options.color_weeknr + self.style_weeknr["font-size"] = str(self.day_w / 3) + + def is_weekend(self, pos): + """Detect weekend days; weekend values: "sat+sun" or "sat" or "sun" """ + if self.options.start_day == "sun": + if self.options.weekend == "sat+sun" and pos == 0: + return True + if self.options.weekend == "sat+sun" and pos == 6: + return True + if self.options.weekend == "sat" and pos == 6: + return True + if self.options.weekend == "sun" and pos == 0: + return True + else: + if self.options.weekend == "sat+sun" and pos == 5: + return True + if self.options.weekend == "sat+sun" and pos == 6: + return True + if self.options.weekend == "sat" and pos == 5: + return True + if self.options.weekend == "sun" and pos == 6: + return True + return False + + def in_line_month(self, cal): + """Lay out days of week in each week""" + cal2 = [] + for week in cal: + for day in week: + if day != 0: + cal2.append(day) + return cal2 + + def write_month_header(self, g, m): + """Write month header""" + txt_atts = { + "style": str(inkex.Style(self.style_month)), + "x": str((self.month_w - self.day_w) / 2), + "y": str(self.day_h / 5), + } + try: + g.add(TextElement(**txt_atts)).text = unicode( + self.options.month_names[m - 1], self.options.input_encode + ) + except: + raise ValueError(_("You must select a correct system encoding.")) + + week_group = g.add(inkex.Group()) + week_x = 0 + if self.options.start_day == "sun": + day_names = self.options.day_names[:] + else: + day_names = self.options.day_names[1:] + day_names.append(self.options.day_names[0]) + + if self.options.show_weeknr: + day_names.insert(0, self.options.weeknr_name) + + for wday in day_names: + txt_atts = { + "style": str(inkex.Style(self.style_day_name)), + "x": str(self.day_w * week_x), + "y": str(self.day_h), + } + try: + week_group.add(TextElement(**txt_atts)).text = unicode( + wday, self.options.input_encode + ) + except: + raise ValueError(_("You must select a correct system encoding.")) + + week_x += 1 + + def create_month(self, m): + """Lay out one month in place on the calendar""" + txt_atts = { + "transform": "translate(" + + str( + self.year_margin + (self.month_w + self.month_margin) * self.month_x_pos + ) + + "," + + str((self.day_h * 4) + (self.month_h * self.month_y_pos)) + + ")", + "id": "month_" + str(m) + "_" + str(self.options.year), + } + g = self.year_g.add(inkex.Group(**txt_atts)) + self.write_month_header(g, m) + gdays = g.add(inkex.Group()) + cal = calendar.monthcalendar(self.options.year, m) + if m == 1: + if self.options.year > 1: + before_month = self.in_line_month( + calendar.monthcalendar(self.options.year - 1, 12) + ) + else: + before_month = self.in_line_month( + calendar.monthcalendar(self.options.year, m - 1) + ) + if m == 12: + next_month = self.in_line_month( + calendar.monthcalendar(self.options.year + 1, 1) + ) + else: + next_month = self.in_line_month( + calendar.monthcalendar(self.options.year, m + 1) + ) + if len(cal) < 6: + # add a line after the last week + cal.append([0, 0, 0, 0, 0, 0, 0]) + if len(cal) < 6: + # add a line before the first week (Feb 2009) + cal.reverse() + cal.append([0, 0, 0, 0, 0, 0, 0]) + cal.reverse() + # How mutch before month days will be showed: + bmd = cal[0].count(0) + cal[1].count(0) + before = True + week_y = 0 + for week in cal: + if ( + self.weeknr != 0 + and ( + (self.options.start_day == "mon" and week[0] != 0) + or (self.options.start_day == "sun" and week[1] != 0) + ) + ) or ( + self.weeknr == 0 + and ( + (self.options.start_day == "mon" and week[3] > 0) + or (self.options.start_day == "sun" and week[4] > 0) + ) + ): + self.weeknr += 1 + week_x = 0 + if self.options.show_weeknr: + # Remove leap week (starting previous year) and empty weeks + if self.weeknr != 0 and not (week[0] == 0 and week[6] == 0): + style = self.style_weeknr + txt_atts = { + "style": str(inkex.Style(style)), + "x": str(self.day_w * week_x), + "y": str(self.day_h * (week_y + 2)), + } + gdays.add(TextElement(**txt_atts)).text = str(self.weeknr) + week_x += 1 + else: + week_x += 1 + for day in week: + style = self.style_day + if self.is_weekend(week_x - self.cols_before): + style = self.style_weekend + if day == 0: + style = self.style_nmd + txt_atts = { + "style": str(inkex.Style(style)), + "x": str(self.day_w * week_x), + "y": str(self.day_h * (week_y + 2)), + } + text = None + if day == 0 and not self.options.fill_edb: + pass # draw nothing + elif day == 0: + if before: + text = str(before_month[-bmd]) + bmd -= 1 + else: + text = str(next_month[bmd]) + bmd += 1 + else: + text = str(day) + before = False + if text: + gdays.add(TextElement(**txt_atts)).text = text + week_x += 1 + week_y += 1 + self.month_x_pos += 1 + if self.month_x_pos >= self.months_per_line: + self.month_x_pos = 0 + self.month_y_pos += 1 + + def effect(self): + self.validate_options() + self.calculate_size_and_positions() + parent = self.document.getroot() + txt_atts = {"id": "year_" + str(self.options.year)} + self.year_g = parent.add(inkex.Group(**txt_atts)) + txt_atts = { + "style": str(inkex.Style(self.style_year)), + "x": str(self.doc_w / 2), + "y": str(self.day_w * 1.5), + } + self.year_g.add(TextElement(**txt_atts)).text = str(self.options.year) + try: + if self.options.month == 0: + for m in range(1, 13): + self.create_month(m) + else: + self.create_month(self.options.month) + except ValueError as err: + return inkex.errormsg(str(err)) + return None + + +if __name__ == "__main__": + Calendar().run() diff --git a/share/extensions/svgfont2layers.inx b/share/extensions/svgfont2layers.inx new file mode 100644 index 0000000..13538b7 --- /dev/null +++ b/share/extensions/svgfont2layers.inx @@ -0,0 +1,15 @@ + + + Convert SVG Font to Glyph Layers + org.inkscape.typography.svg_font_to_layers + 30 + + all + + + + + + diff --git a/share/extensions/svgfont2layers.py b/share/extensions/svgfont2layers.py new file mode 100755 index 0000000..e9d1710 --- /dev/null +++ b/share/extensions/svgfont2layers.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Felipe Correa da Silva Sanches +# +# 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. +# +"""Extension for converting svg fonts to layers""" + +import inkex + + +class SvgFontToLayers(inkex.EffectExtension): + """Convert an svg font to layers""" + + def add_arguments(self, pars): + pars.add_argument( + "--count", + type=int, + default=30, + help="Stop making layers after this number of glyphs.", + ) + + def flip_cordinate_system(self, elem, emsize, baseline): + """Scale and translate the element's path, returns the path object""" + path = elem.path + path.scale(1, -1, inplace=True) + path.translate(0, int(emsize) - int(baseline), inplace=True) + return path + + def effect(self): + # TODO: detect files with multiple svg fonts declared. + # Current code only reads the first svgfont instance + font = self.svg.defs.findone("svg:font") + if font is None: + return inkex.errormsg("There are no svg fonts") + # setwidth = font.get("horiz-adv-x") + baseline = font.get("horiz-origin-y") + if baseline is None: + baseline = 0 + + fontface = font.findone("svg:font-face") + + # TODO: where should we save the font family name? + # fontfamily = fontface.get("font-family") + emsize = fontface.get("units-per-em") + + # TODO: should we guarantee that equals ? + caps = int(fontface.get("cap-height", 0)) + xheight = int(fontface.get("x-height", 0)) + ascender = int(fontface.get("ascent", 0)) + descender = int(fontface.get("descent", 0)) + + self.svg.set("width", emsize) + self.svg.namedview.new_guide(baseline, True, "baseline") + self.svg.namedview.new_guide(baseline + ascender, True, "ascender") + self.svg.namedview.new_guide(baseline + caps, True, "caps") + self.svg.namedview.new_guide(baseline + xheight, True, "xheight") + self.svg.namedview.new_guide(baseline - descender, True, "decender") + + # TODO: missing-glyph + count = 0 + for glyph in font.findall("svg:glyph"): + unicode_char = glyph.get("unicode") + if unicode_char is None: + continue + + layer = self.svg.add(inkex.Layer.new("GlyphLayer-" + unicode_char)) + # glyph layers (except the first one) are innitially hidden + if count != 0: + layer.style["display"] = "none" + + ############################ + # Option 1: + # Using clone (svg:use) as childnode of svg:glyph + + # use = self.get_or_create(glyph, inkex.Use()) + # use.href = group + # TODO: This code creates nodes but they do not render on svg fonts dialog. why? + + ############################ + # Option 2: + # Using svg:paths as childnodes of svg:glyph + for elem in glyph.findall("svg:path"): + new_path = layer.add(inkex.PathElement()) + new_path.path = self.flip_cordinate_system(elem, emsize, baseline) + + ############################ + # Option 3: + # Using curve description in d attribute of svg:glyph + path = layer.add(inkex.PathElement()) + path.path = self.flip_cordinate_system(glyph, emsize, baseline) + + count += 1 + if count >= self.options.count: + break + + +if __name__ == "__main__": + SvgFontToLayers().run() diff --git a/share/extensions/synfig_fileformat.py b/share/extensions/synfig_fileformat.py new file mode 100755 index 0000000..b8a4532 --- /dev/null +++ b/share/extensions/synfig_fileformat.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +synfig_fileformat.py +Synfig file format utilities + +Copyright (C) 2011 Nikita Kitaev + +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 +""" + +# ##### Constants ########################################## +kux = 60.0 # Number of SVG units (pixels) per Synfig "unit" +gamma = 1.0 +tangent_scale = 3.0 # Synfig tangents are scaled by a factor of 3 + +# ##### Layer parameters, types, and default values ######## +layers = {} + +# Layer_Composite is the parent of most layers +default_composite = { + "z_depth": ["real", 0.0], + "amount": ["real", 1.0], + "blend_method": ["integer", 0], +} + +layers["PasteCanvas"] = default_composite.copy() +layers["PasteCanvas"].update( + { + "origin": ["vector", [0.0, 0.0]], + "canvas": ["canvas", None], + "zoom": ["real", 0.0], + "time_offset": ["time", "0s"], + "children_lock": ["bool", False], + "focus": ["vector", [0.0, 0.0]], + } +) + +# Layers in mod_geometry + +layers["circle"] = default_composite.copy() +layers["circle"].update( + { + "color": ["color", [0, 0, 0, 1]], + "radius": ["real", 1.0], + "feather": ["real", 0.0], + "origin": ["vector", [0.0, 0.0]], + "invert": ["bool", False], + } +) + +layers["rectangle"] = default_composite.copy() +layers["rectangle"].update( + { + "color": ["color", [0, 0, 0, 1]], + "point1": ["vector", [0, 0]], + "point2": ["vector", [1, 1]], + "expand": ["real", 0.0], + "invert": ["bool", False], + } +) + +default_shape = default_composite.copy() +default_shape.update( + { + "color": ["color", [0, 0, 0, 1]], + "origin": ["vector", [0.0, 0.0]], + "invert": ["bool", False], + "antialias": ["bool", True], + "feather": ["real", 0.0], + "blurtype": ["integer", 1], + "winding_style": ["integer", 0], + } +) + +layers["region"] = default_shape.copy() +layers["region"].update({"bline": ["bline", None]}) + +layers["outline"] = default_shape.copy() +layers["outline"].update( + { + "bline": ["bline", None], + "round_tip[0]": ["bool", True], + "round_tip[1]": ["bool", True], + "sharp_cusps": ["bool", True], + "width": ["real", 1.0], + "loopyness": ["real", 1.0], + "expand": ["real", 0.0], + "homogeneous_width": ["bool", True], + } +) + +# Layers in mod_gradient + +layers["linear_gradient"] = default_composite.copy() +layers["linear_gradient"].update( + { + "p1": ["vector", [0, 0]], + "p2": ["vector", [1, 1]], + "gradient": ["gradient", {0.0: [0, 0, 0, 1], 1.0: [1, 1, 1, 1]}], + "loop": ["bool", False], + "zigzag": ["bool", False], + } +) + +layers["radial_gradient"] = default_composite.copy() +layers["radial_gradient"].update( + { + "gradient": ["gradient", {0.0: [0, 0, 0, 1], 1.0: [1, 1, 1, 1]}], + "center": ["vector", [0, 0]], + "radius": ["real", 1.0], + "loop": ["bool", False], + "zigzag": ["bool", False], + } +) + +# Layers in lyr_std + +layers["import"] = default_composite.copy() +layers["import"].update( + { + "tl": ["vector", [-1, 1]], + "br": ["vector", [1, -1]], + "c": ["integer", 1], + "gamma_adjust": ["real", 1.0], + "filename": ["string", ""], # foo + "time_offset": ["time", "0s"], + } +) + +# transforms are not blending +layers["warp"] = { + "src_tl": ["vector", [-1, 1]], + "src_br": ["vector", [1, -1]], + "dest_tl": ["vector", [-1, 1]], + "dest_tr": ["vector", [1, 1]], + "dest_br": ["vector", [1, -1]], + "dest_bl": ["vector", [-1, -1]], + "clip": ["bool", False], + "horizon": ["real", 4.0], +} + +layers["rotate"] = { + "origin": ["vector", [0.0, 0.0]], + "amount": ["angle", 0], # +} + +layers["translate"] = {"origin": ["vector", [0.0, 0.0]]} + +# Layers in mod_filter +layers["blur"] = default_composite.copy() +layers["blur"].update( + { + "size": ["vector", [1, 1]], + "type": ["integer", 3], # 1 is fast gaussian, 3 is regular + } +) + +# ##### Layer versions ##################################### +layer_versions = { + "outline": "0.2", + "rectangle": "0.2", + "linear_gradient": "0.0", + "blur": "0.2", + None: "0.1", # default +} + +# ##### Blend Methods ###################################### +blend_method_names = { + 0: "composite", + 1: "straight", + 13: "onto", + 21: "straight onto", + 12: "behind", + 16: "screen", + 20: "overlay", + 17: "hand light", + 6: "multiply", + 7: "divide", + 4: "add", + 5: "subtract", + 18: "difference", + 2: "brighten", + 3: "darken", + 8: "color", + 9: "hue", + 10: "saturation", + 11: "luminance", + 14: "alpha brighten", # deprecated + 15: "alpha darken", # deprecated + 19: "alpha over", # deprecated +} + +blend_methods = dict((v, k) for (k, v) in blend_method_names.items()) + + +# ##### Functions ########################################## +def paramType(layer, param, value=None): + if layer in layers.keys(): + layer_params = layers[layer] + if param in layer_params.keys(): + return layer_params[param][0] + else: + raise Exception("Invalid parameter type for layer") + else: + # Unknown layer, try to determine parameter type based on value + if value is None: + raise Exception("No information for given layer") + if type(value) == int: + return "integer" + elif type(value) == float: + return "real" + elif type(value) == bool: + return "bool" + elif type(value) == dict: + if "points" in value.keys(): + return "bline" + elif 0.0 in value.keys(): + return "gradient" + else: + raise Exception("Could not automatically determine parameter type") + elif type(value) == list: + if len(value) == 2: + return "vector" + elif len(value) == 3 or len(value) == 4: + return "color" + else: + # The first two could also be canvases + return "canvas" + elif type(value) == str: + return "string" + + +def defaultLayerVersion(layer): + if layer in layer_versions.keys(): + return layer_versions[layer] + else: + return layer_versions[None] + + +def defaultLayerParams(layer): + if layer in layers.keys(): + return layers[layer].copy() + else: + return {} diff --git a/share/extensions/synfig_output.inx b/share/extensions/synfig_output.inx new file mode 100644 index 0000000..72fd384 --- /dev/null +++ b/share/extensions/synfig_output.inx @@ -0,0 +1,18 @@ + + + Synfig Output + org.inkscape.output.synfig_export + synfig_fileformat.py + synfig_prepare.py + + .sif + image/sif + Synfig Animation (*.sif) + Synfig Animation written using the sif-file exporter extension + true + + + diff --git a/share/extensions/synfig_output.py b/share/extensions/synfig_output.py new file mode 100755 index 0000000..327c013 --- /dev/null +++ b/share/extensions/synfig_output.py @@ -0,0 +1,1485 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Nikita Kitaev +# +# 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 +# +""" +An Inkscape extension for exporting Synfig files (.sif) +""" +import math +import uuid +from copy import deepcopy + +from lxml import etree + +import inkex +from inkex import ( + Group, + Layer, + Anchor, + Switch, + PathElement, + Metadata, + NamedView, + Gradient, + SvgDocumentElement, + Path, + Transform, +) + +import synfig_fileformat as sif +from synfig_prepare import MalformedSVGError, SynfigPrep, get_dimension + + +# ##### Utility Classes #################################### +class UnsupportedException(Exception): + """When part of an element is not supported, this exception is raised to invalidate the whole element""" + + pass + + +class SynfigDocument(object): + """A synfig document, with commands for adding layers and layer parameters""" + + def __init__(self, width=1024, height=768, name="Synfig Animation 1"): + self.root_canvas = etree.fromstring( + """ + + {} + + """.format( + width, height, name + ) + ) + + self._update_viewbox() + + self.gradients = {} + self.filters = {} + + # ## Properties + + def get_root_canvas(self): + return self.root_canvas + + def get_root_tree(self): + return self.root_canvas.getroottree() + + def _update_viewbox(self): + """Update the viewbox to match document width and height""" + attr_viewbox = "{:f} {:f} {:f} {:f}".format( + -self.width / 2.0 / sif.kux, + self.height / 2.0 / sif.kux, + self.width / 2.0 / sif.kux, + -self.height / 2.0 / sif.kux, + ) + self.root_canvas.set("view-box", attr_viewbox) + + def get_width(self): + return float(self.root_canvas.get("width", "0")) + + def set_width(self, value): + self.root_canvas.set("width", str(value)) + self._update_viewbox() + + def get_height(self): + return float(self.root_canvas.get("height", "0")) + + def set_height(self, value): + self.root_canvas.set("height", str(value)) + self._update_viewbox() + + def get_name(self): + return self.root_canvas.get("name", "") + + def set_name(self, value): + self.root_canvas.set("name", value) + self._update_viewbox() + + width = property(get_width, set_width) + height = property(get_height, set_height) + name = property(get_name, set_name) + + # ## Public utility functions + + def new_guid(self): + """Generate a new GUID""" + return uuid.uuid4().hex + + # ## Coordinate system conversions + + def distance_svg2sif(self, distance): + """Convert distance from SVG to Synfig units""" + return distance / sif.kux + + def distance_sif2svg(self, distance): + """Convert distance from Synfig to SVG units""" + return distance * sif.kux + + def coor_svg2sif(self, vector): + """Convert SVG coordinate [x, y] to Synfig units""" + x = vector[0] + y = self.height - vector[1] + + x -= self.width / 2.0 + y -= self.height / 2.0 + x /= sif.kux + y /= sif.kux + + return [x, y] + + def coor_sif2svg(self, vector): + """Convert Synfig coordinate [x, y] to SVG units""" + x = vector[0] * sif.kux + self.width / 2.0 + y = vector[1] * sif.kux + self.height / 2.0 + + y = self.height - y + + assert ( + self.coor_svg2sif([x, y]) == vector + ), "sif to svg coordinate conversion error" + + return [x, y] + + def list_coor_svg2sif(self, l): + """Scan a list for coordinate pairs and convert them to Synfig units""" + # If list has two numerical elements, + # treat it as a coordinate pair + if type(l) == list and len(l) == 2: + if type(l[0]) == int or type(l[0]) == float: + if type(l[1]) == int or type(l[1]) == float: + l_sif = self.coor_svg2sif(l) + l[0] = l_sif[0] + l[1] = l_sif[1] + return + + # Otherwise recursively iterate over the list + for x in l: + if type(x) == list: + self.list_coor_svg2sif(x) + + def list_coor_sif2svg(self, l): + """Scan a list for coordinate pairs and convert them to SVG units""" + # If list has two numerical elements, + # treat it as a coordinate pair + if type(l) == list and len(l) == 2: + if type(l[0]) == int or type(l[0]) == float: + if type(l[1]) == int or type(l[1]) == float: + l_sif = self.coor_sif2svg(l) + l[0] = l_sif[0] + l[1] = l_sif[1] + return + + # Otherwise recursively iterate over the list + for x in l: + if type(x) == list: + self.list_coor_sif2svg(x) + + def bline_coor_svg2sif(self, b): + """Convert a BLine from SVG to Synfig coordinate units""" + self.list_coor_svg2sif(b["points"]) + + def bline_coor_sif2svg(self, b): + """Convert a BLine from Synfig to SVG coordinate units""" + self.list_coor_sif2svg(b["points"]) + + # ## XML Builders -- private + # ## used to create XML elements in the Synfig document + + def build_layer(self, layer_type, desc, canvas=None, active=True, version="auto"): + """Build an empty layer""" + if canvas is None: + layer = self.root_canvas.makeelement("layer") + else: + layer = etree.SubElement(canvas, "layer") + + layer.set("type", layer_type) + layer.set("desc", desc) + if active: + layer.set("active", "true") + else: + layer.set("active", "false") + + if version == "auto": + version = sif.defaultLayerVersion(layer_type) + + if type(version) == float: + version = str(version) + + layer.set("version", version) + + return layer + + def _calc_radius(self, p1x, p1y, p2x, p2y): + """Calculate radius of a tangent given two points""" + # Synfig tangents are scaled by a factor of 3 + return sif.tangent_scale * math.sqrt((p2x - p1x) ** 2 + (p2y - p1y) ** 2) + + def _calc_angle(self, p1x, p1y, p2x, p2y): + """Calculate angle (in radians) of a tangent given two points""" + dx = p2x - p1x + dy = p2y - p1y + if dx > 0 and dy > 0: + ag = math.pi + math.atan(dy / dx) + elif dx > 0 > dy: + ag = math.pi + math.atan(dy / dx) + elif dx < 0 and dy < 0: + ag = math.atan(dy / dx) + elif dx < 0 < dy: + ag = 2 * math.pi + math.atan(dy / dx) + elif dx == 0 and dy > 0: + ag = -1 * math.pi / 2 + elif dx == 0 and dy < 0: + ag = math.pi / 2 + elif dx == 0 and dy == 0: + ag = 0 + elif dx < 0 and dy == 0: + ag = 0 + elif dx > 0 and dy == 0: + ag = math.pi + + return (ag * 180) / math.pi + + def build_param(self, layer, name, value, param_type="auto", guid=None): + """Add a parameter node to a layer""" + if layer is None: + param = self.root_canvas.makeelement("param") + else: + param = etree.SubElement(layer, "param") + param.set("name", name) + + # Automatically detect param_type + if param_type == "auto": + if layer is not None: + layer_type = layer.get("type") + param_type = sif.paramType(layer_type, name) + else: + param_type = sif.paramType(None, name, value) + + if param_type == "real": + el = etree.SubElement(param, "real") + el.set("value", str(float(value))) + elif param_type == "integer": + el = etree.SubElement(param, "integer") + el.set("value", str(int(value))) + elif param_type == "vector": + el = etree.SubElement(param, "vector") + x = etree.SubElement(el, "x") + x.text = str(float(value[0])) + y = etree.SubElement(el, "y") + y.text = str(float(value[1])) + elif param_type == "color": + el = etree.SubElement(param, "color") + r = etree.SubElement(el, "r") + r.text = str(float(value[0])) + g = etree.SubElement(el, "g") + g.text = str(float(value[1])) + b = etree.SubElement(el, "b") + b.text = str(float(value[2])) + a = etree.SubElement(el, "a") + a.text = str(float(value[3])) if len(value) > 3 else "1.0" + elif param_type == "gradient": + el = etree.SubElement(param, "gradient") + # Value is a dictionary of color stops + # see get_gradient() + for pos in value.keys(): + color = etree.SubElement(el, "color") + color.set("pos", str(float(pos))) + + c = value[pos] + + r = etree.SubElement(color, "r") + r.text = str(float(c[0])) + g = etree.SubElement(color, "g") + g.text = str(float(c[1])) + b = etree.SubElement(color, "b") + b.text = str(float(c[2])) + a = etree.SubElement(color, "a") + a.text = str(float(c[3])) if len(c) > 3 else "1.0" + elif param_type == "bool": + el = etree.SubElement(param, "bool") + if value: + el.set("value", "true") + else: + el.set("value", "false") + elif param_type == "time": + el = etree.SubElement(param, "time") + if type(value) == int: + el.set("value", "{:d}s".format(value)) + elif type(value) == float: + el.set("value", "{:f}s".format(value)) + elif type(value) == str: + el.set("value", value) + elif param_type == "bline": + el = etree.SubElement(param, "bline") + el.set("type", "bline_point") + + # value is a bline (dictionary type), see path_to_bline_list + if value["loop"]: + el.set("loop", "true") + else: + el.set("loop", "false") + + for vertex in value["points"]: + x = float(vertex[1][0]) + y = float(vertex[1][1]) + + tg1x = float(vertex[0][0]) + tg1y = float(vertex[0][1]) + + tg2x = float(vertex[2][0]) + tg2y = float(vertex[2][1]) + + tg1_radius = self._calc_radius(x, y, tg1x, tg1y) + tg1_angle = self._calc_angle(x, y, tg1x, tg1y) + + tg2_radius = self._calc_radius(x, y, tg2x, tg2y) + tg2_angle = self._calc_angle(x, y, tg2x, tg2y) - 180.0 + + if vertex[3]: + split = "true" + else: + split = "false" + + entry = etree.SubElement(el, "entry") + composite = etree.SubElement(entry, "composite") + composite.set("type", "bline_point") + + point = etree.SubElement(composite, "point") + vector = etree.SubElement(point, "vector") + etree.SubElement(vector, "x").text = str(x) + etree.SubElement(vector, "y").text = str(y) + + width = etree.SubElement(composite, "width") + etree.SubElement(width, "real").set("value", "1.0") + + origin = etree.SubElement(composite, "origin") + etree.SubElement(origin, "real").set("value", "0.5") + + split_el = etree.SubElement(composite, "split") + etree.SubElement(split_el, "bool").set("value", split) + + t1 = etree.SubElement(composite, "t1") + t2 = etree.SubElement(composite, "t2") + + t1_rc = etree.SubElement(t1, "radial_composite") + t1_rc.set("type", "vector") + + t2_rc = etree.SubElement(t2, "radial_composite") + t2_rc.set("type", "vector") + + t1_r = etree.SubElement(t1_rc, "radius") + t2_r = etree.SubElement(t2_rc, "radius") + t1_radius = etree.SubElement(t1_r, "real") + t2_radius = etree.SubElement(t2_r, "real") + t1_radius.set("value", str(tg1_radius)) + t2_radius.set("value", str(tg2_radius)) + + t1_t = etree.SubElement(t1_rc, "theta") + t2_t = etree.SubElement(t2_rc, "theta") + t1_angle = etree.SubElement(t1_t, "angle") + t2_angle = etree.SubElement(t2_t, "angle") + t1_angle.set("value", str(tg1_angle)) + t2_angle.set("value", str(tg2_angle)) + elif param_type == "canvas": + el = etree.SubElement(param, "canvas") + el.set("xres", "10.0") + el.set("yres", "10.0") + + # "value" is a list of layers + if value is not None: + for layer in value: + el.append(layer) + else: + raise AssertionError("Unsupported param type {}".format(param_type)) + + if guid: + el.set("guid", guid) + else: + el.set("guid", self.new_guid()) + + return param + + # ## Public layer API + # ## Should be used by outside functions to create layers and set layer parameters + + def create_layer( + self, + layer_type, + desc, + params={}, + guids={}, + canvas=None, + active=True, + version="auto", + ): + """Create a new layer + + Keyword arguments: + layer_type -- layer type string used internally by Synfig + desc -- layer description + params -- a dictionary of parameter names and their values + guids -- a dictionary of parameter types and their guids (optional) + active -- set to False to create a hidden layer + """ + layer = self.build_layer(layer_type, desc, canvas, active, version) + default_layer_params = sif.defaultLayerParams(layer_type) + + for param_name in default_layer_params.keys(): + param_type = default_layer_params[param_name][0] + if param_name in params.keys(): + param_value = params[param_name] + else: + param_value = default_layer_params[param_name][1] + + if param_name in guids.keys(): + param_guid = guids[param_name] + else: + param_guid = None + + if param_value is not None: + self.build_param( + layer, param_name, param_value, param_type, guid=param_guid + ) + + return layer + + def set_param( + self, layer, name, value, param_type="auto", guid=None, modify_linked=False + ): + """Set a layer parameter + + Keyword arguments: + layer -- the layer to set the parameter for + name -- parameter name + value -- parameter value + param_type -- parameter type (default "auto") + guid -- guid of the parameter value + """ + if modify_linked: + raise AssertionError("Modifying linked parameters is not supported") + + layer_type = layer.get("type") + assert layer_type, "Layer does not have a type" + + if param_type == "auto": + param_type = sif.paramType(layer_type, name) + + # Remove existing parameters with this name + existing = [] + for param in layer.iterchildren(): + if param.get("name") == name: + existing.append(param) + + if len(existing) == 0: + self.build_param(layer, name, value, param_type, guid) + elif len(existing) > 1: + raise AssertionError("Found multiple parameters with the same name") + else: + new_param = self.build_param(None, name, value, param_type, guid) + layer.replace(existing[0], new_param) + + def set_params(self, layer, params={}, guids={}, modify_linked=False): + """Set layer parameters + + Keyword arguments: + layer -- the layer to set the parameter for + params -- a dictionary of parameter names and their values + guids -- a dictionary of parameter types and their guids (optional) + """ + for param_name in params.keys(): + if param_name in guids.keys(): + self.set_param( + layer, + param_name, + params[param_name], + guid=guids[param_name], + modify_linked=modify_linked, + ) + else: + self.set_param( + layer, param_name, params[param_name], modify_linked=modify_linked + ) + + def get_param(self, layer, name, param_type="auto"): + """Get the value of a layer parameter + + Keyword arguments: + layer -- the layer to get the parameter from + name -- param name + param_type -- parameter type (default "auto") + + NOT FULLY IMPLEMENTED + """ + layer_type = layer.get("type") + assert layer_type, "Layer does not have a type" + + if param_type == "auto": + param_type = sif.paramType(layer_type, name) + + for param in layer.iterchildren(): + if param.get("name") == name: + if param_type == "real": + return float(param[0].get("value", "0")) + elif param_type == "integer": + return int(param[0].get("integer", "0")) + else: + raise Exception( + "Getting this type of parameter not yet implemented" + ) + + # ## Global defs, and related + + # SVG Filters + def add_filter(self, filter_id, f): + """Register a filter""" + self.filters[filter_id] = f + + # SVG Gradients + def add_linear_gradient( + self, + gradient_id, + p1, + p2, + mtx=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], + stops=[], + link="", + spread_method="pad", + ): + """Register a linear gradient definition""" + gradient = { + "type": "linear", + "p1": p1, + "p2": p2, + "mtx": mtx, + "spreadMethod": spread_method, + } + if stops: + gradient["stops"] = stops + gradient["stops_guid"] = self.new_guid() + elif link != "": + gradient["link"] = link + else: + raise MalformedSVGError("Gradient has neither stops nor link") + self.gradients[gradient_id] = gradient + + def add_radial_gradient( + self, + gradient_id, + center, + radius, + focus, + mtx=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], + stops=[], + link="", + spread_method="pad", + ): + """Register a radial gradient definition""" + gradient = { + "type": "radial", + "center": center, + "radius": radius, + "focus": focus, + "mtx": mtx, + "spreadMethod": spread_method, + } + if stops: + gradient["stops"] = stops + gradient["stops_guid"] = self.new_guid() + elif link != "": + gradient["link"] = link + else: + raise MalformedSVGError("Gradient has neither stops nor link") + self.gradients[gradient_id] = gradient + + def get_gradient(self, gradient_id): + """ + Return a gradient with a given id + + Linear gradient format: + { + "type" : "linear", + "p1" : [x, y], + "p2" : [x, y], + "mtx" : mtx, + "stops" : color stops, + "stops_guid": color stops guid, + "spreadMethod": "pad", "reflect", or "repeat" + } + + Radial gradient format: + { + "type" : "radial", + "center" : [x, y], + "radius" : r, + "focus" : [x, y], + "mtx" : mtx, + "stops" : color stops, + "stops_guid": color stops guid, + "spreadMethod": "pad", "reflect", or "repeat" + } + + Color stops format + { + 0.0 : color ([r,g,b,a] or [r,g,b]) at start, + [a number] : color at that position, + 1.0 : color at end + } + """ + + if gradient_id not in self.gradients.keys(): + return None + + gradient = self.gradients[gradient_id] + + # If the gradient has no link, we are done + if "link" not in gradient.keys() or gradient["link"] == "": + return gradient + + # If the gradient does have a link, find the color stops recursively + if gradient["link"] not in self.gradients.keys(): + raise MalformedSVGError("Linked gradient ID not found") + + linked_gradient = self.get_gradient(gradient["link"]) + gradient["stops"] = linked_gradient["stops"] + gradient["stops_guid"] = linked_gradient["stops_guid"] + del gradient["link"] + + # Update the gradient in our listing + # (so recursive lookup only happens once) + self.gradients[gradient_id] = gradient + + return gradient + + def gradient_to_params(self, gradient): + """Transform gradient to a list of parameters to pass to a Synfig layer""" + # Create a copy of the gradient + g = gradient.copy() + + # Set synfig-only attribs + if g["spreadMethod"] == "repeat": + g["loop"] = True + elif g["spreadMethod"] == "reflect": + g["loop"] = True + # Reflect the gradient + # Original: 0.0 [A . B . C] 1.0 + # New: 0.0 [A . B . C . B . A] 1.0 + # (with gradient size doubled) + new_stops = {} + + # reflect the stops + for pos in g["stops"]: + val = g["stops"][pos] + if pos == 1.0: + new_stops[pos / 2.0] = val + else: + new_stops[pos / 2.0] = val + new_stops[1 - pos / 2.0] = val + g["stops"] = new_stops + + # double the gradient size + if g["type"] == "linear": + g["p2"] = [ + g["p1"][0] + 2.0 * (g["p2"][0] - g["p1"][0]), + g["p1"][1] + 2.0 * (g["p2"][1] - g["p1"][1]), + ] + if g["type"] == "radial": + g["radius"] *= 2.0 + + # Rename "stops" to "gradient" + g["gradient"] = g["stops"] + + # Convert coordinates + if g["type"] == "linear": + g["p1"] = self.coor_svg2sif(g["p1"]) + g["p2"] = self.coor_svg2sif(g["p2"]) + + if g["type"] == "radial": + g["center"] = self.coor_svg2sif(g["center"]) + g["radius"] = self.distance_svg2sif(g["radius"]) + + # Delete extra attribs + removed_attribs = [ + "type", + "stops", + "stops_guid", + "mtx", + "focus", + "spreadMethod", + ] + for x in removed_attribs: + if x in g.keys(): + del g[x] + return g + + # ## Public operations API + # Operations act on a series of layers, and (optionally) on a series of named parameters + # The "is_end" attribute should be set to true when the layers are at the end of a canvas + # (i.e. when adding transform layers on top of them does not require encapsulation) + + def op_blur(self, layers, x, y, name="Blur", is_end=False): + """Gaussian blur the given layers by the given x and y amounts + + Keyword arguments: + layers -- list of layers + x -- x-amount of blur + y -- x-amount of blur + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + blur = self.create_layer( + "blur", + name, + params={"blend_method": sif.blend_methods["straight"], "size": [x, y]}, + ) + + if is_end: + return layers + [blur] + else: + return self.op_encapsulate(layers + [blur]) + + def op_color(self, layers, overlay, is_end=False): + """Apply a color overlay to the given layers + + Should be used to apply a gradient or pattern to a shape + + Keyword arguments: + layers -- list of layers + overlay -- color layer to apply + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + if not layers: + return layers + if overlay is None: + return layers + + overlay_enc = self.op_encapsulate([overlay]) + self.set_param( + overlay_enc[0], "blend_method", sif.blend_methods["straight onto"] + ) + ret = layers + overlay_enc + + if is_end: + return ret + else: + return self.op_encapsulate(ret) + + def op_encapsulate(self, layers, name="Inline Canvas", is_end=False): + """Encapsulate the given layers + + Keyword arguments: + layers -- list of layers + name -- Name of the PasteCanvas layer that is created + is_end -- set to True if layers are at the end of a canvas + + Returns: list of one layer + """ + + if not layers: + return layers + + layer = self.create_layer("PasteCanvas", name, params={"canvas": layers}) + return [layer] + + def op_fade(self, layers, opacity, is_end=False): + """Increase the opacity of the given layers by a certain amount + + Keyword arguments: + layers -- list of layers + opacity -- the opacity to apply (float between 0.0 to 1.0) + name -- name of the Transform layer that is added + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + # If there is blending involved, first encapsulate the layers + for layer in layers: + if self.get_param(layer, "blend_method") != sif.blend_methods["composite"]: + return self.op_fade(self.op_encapsulate(layers), opacity, is_end) + + # Otherwise, set their amount + for layer in layers: + amount = self.get_param(layer, "amount") + self.set_param(layer, "amount", amount * opacity) + + return layers + + def op_filter(self, layers, filter_id, is_end=False): + """Apply a filter to the given layers + + Keyword arguments: + layers -- list of layers + filter_id -- id of the filter + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + if filter_id not in self.filters.keys(): + raise MalformedSVGError("Filter {} not found".format(filter_id)) + + try: + ret = self.filters[filter_id](self, layers, is_end) + assert type(ret) == list + return ret + except UnsupportedException: + # If the filter is not supported, ignore it. + return layers + + def op_set_blend(self, layers, blend_method, is_end=False): + """Set the blend method of the given group of layers + + If more than one layer is supplied, they will be encapsulated. + + Keyword arguments: + layers -- list of layers + blend_method -- blend method to give the layers + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + if not layers: + return layers + if blend_method == "composite": + return layers + + layer = layers[0] + if len(layers) > 1 or self.get_param(layers[0], "amount") != 1.0: + layer = self.op_encapsulate(layers)[0] + + layer = deepcopy(layer) + + self.set_param(layer, "blend_method", sif.blend_methods[blend_method]) + + return [layer] + + def op_transform(self, layers, mtx, name="Transform", is_end=False): + """Apply a matrix transformation to the given layers + + Keyword arguments: + layers -- list of layers + mtx -- transformation matrix + name -- name of the Transform layer that is added + is_end -- set to True if layers are at the end of a canvas + + Returns: list of layers + """ + if not layers: + return layers + if mtx is None or mtx == [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]: + return layers + + src_tl = [100, 100] + src_br = [200, 200] + + dest_tl = [100, 100] + dest_tr = [200, 100] + dest_br = [200, 200] + dest_bl = [100, 200] + + dest_tl = Transform(mtx).apply_to_point(dest_tl) + dest_tr = Transform(mtx).apply_to_point(dest_tr) + dest_br = Transform(mtx).apply_to_point(dest_br) + dest_bl = Transform(mtx).apply_to_point(dest_bl) + + warp = self.create_layer( + "warp", + name, + params={ + "src_tl": self.coor_svg2sif(src_tl), + "src_br": self.coor_svg2sif(src_br), + "dest_tl": self.coor_svg2sif(dest_tl), + "dest_tr": self.coor_svg2sif(dest_tr), + "dest_br": self.coor_svg2sif(dest_br), + "dest_bl": self.coor_svg2sif(dest_bl), + }, + ) + + if is_end: + return layers + [warp] + else: + return self.op_encapsulate(layers + [warp]) + + +# ##### Utility Functions ################################## + +# ## Path related + + +def path_to_bline_list(path_d, nodetypes=None, mtx=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]): + """ + Convert a path to a BLine List + + bline_list format: + + Vertex: + [[tg1x, tg1y], [x,y], [tg2x, tg2y], split = T/F] + Vertex list: + [ vertex, vertex, vertex, ...] + Bline: + { + "points" : vertex_list, + "loop" : True / False + } + """ + + # Exit on empty paths + if not path_d: + return [] + + # Parse the path + path = Path(path_d).to_arrays() + + # Append (more than) enough c's to the nodetypes + if nodetypes is None: + nt = "" + else: + nt = nodetypes + + for _ in range(len(path)): + nt += "c" + + # Create bline list + # borrows code from cubicsuperpath.py + + # bline_list := [bline, bline, ...] + # bline := { + # "points":[vertex, vertex, ...], + # "loop":True/False, + # } + + bline_list = [] + + subpathstart = [] + last = [] + lastctrl = [] + lastsplit = True + + for s in path: + cmd, params = s + if cmd != "M" and bline_list == []: + raise MalformedSVGError( + "Bad path data: path doesn't start with moveto, {}, {}".format(s, path) + ) + elif cmd == "M": + # Add previous point to subpath + if last: + bline_list[-1]["points"].append( + [lastctrl[:], last[:], last[:], lastsplit] + ) + # Start a new subpath + bline_list.append({"nodetypes": "", "loop": False, "points": []}) + # Save coordinates of this point + subpathstart = params[:] + last = params[:] + lastctrl = params[:] + lastsplit = False if nt[0] == "z" else True + nt = nt[1:] + elif cmd in "LHV": + bline_list[-1]["points"].append([lastctrl[:], last[:], last[:], lastsplit]) + if cmd == "H": + last = [params[0], last[1]] + lastctrl = [params[0], last[1]] + elif cmd == "V": + last = [last[0], params[0]] + lastctrl = [last[0], params[0]] + else: + last = params[:] + lastctrl = params[:] + lastsplit = False if nt[0] == "z" else True + nt = nt[1:] + elif cmd == "C": + bline_list[-1]["points"].append( + [lastctrl[:], last[:], params[:2], lastsplit] + ) + last = params[-2:] + lastctrl = params[2:4] + lastsplit = False if nt[0] == "z" else True + nt = nt[1:] + elif cmd == "Q": + q0 = last[:] + q1 = params[0:2] + q2 = params[2:4] + x0 = q0[0] + x1 = 1.0 / 3 * q0[0] + 2.0 / 3 * q1[0] + x2 = 2.0 / 3 * q1[0] + 1.0 / 3 * q2[0] + x3 = q2[0] + y0 = q0[1] + y1 = 1.0 / 3 * q0[1] + 2.0 / 3 * q1[1] + y2 = 2.0 / 3 * q1[1] + 1.0 / 3 * q2[1] + y3 = q2[1] + bline_list[-1]["points"].append( + [lastctrl[:], [x0, y0], [x1, y1], lastsplit] + ) + last = [x3, y3] + lastctrl = [x2, y2] + lastsplit = False if nt[0] == "z" else True + nt = nt[1:] + elif cmd == "A": + from inkex.paths import arc_to_path + + arcp = arc_to_path(last[:], params[:]) + arcp[0][0] = lastctrl[:] + last = arcp[-1][1] + lastctrl = arcp[-1][0] + lastsplit = False if nt[0] == "z" else True + nt = nt[1:] + for el in arcp[:-1]: + el.append(True) + bline_list[-1]["points"].append(el) + elif cmd == "Z": + if len(bline_list[-1]["points"]) == 0: + # If the path "loops" after only one point + # e.g. "M 0 0 Z" + bline_list[-1]["points"].append([lastctrl[:], last[:], last[:], False]) + elif last == subpathstart: + # If we are back to the original position + # merge our tangent into the first point + bline_list[-1]["points"][0][0] = lastctrl[:] + else: + # Otherwise draw a line to the starting point + bline_list[-1]["points"].append( + [lastctrl[:], last[:], last[:], lastsplit] + ) + + # Clear the variables (no more points need to be added) + last = [] + lastctrl = [] + lastsplit = True + + # Loop the subpath + bline_list[-1]["loop"] = True + # Append final superpoint, if needed + if last: + bline_list[-1]["points"].append([lastctrl[:], last[:], last[:], lastsplit]) + + # Apply the transformation + if mtx != [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]: + for bline in bline_list: + for vertex in bline["points"]: + for point in vertex: + if not isinstance(point, bool): + pnt = Transform(mtx).apply_to_point(point) + point[0], point[1] = pnt[0], pnt[1] + + return bline_list + + +# ## Style related + + +def extract_color(style, color_attrib, *opacity_attribs): + if color_attrib in style.keys(): + if style[color_attrib] == "none": + return [1, 1, 1, 0] + c = inkex.Color(style[color_attrib]).to_rgb() + else: + c = (0, 0, 0) + + # Convert color scales and adjust gamma + color = [ + pow(c[0] / 255.0, sif.gamma), + pow(c[1] / 255.0, sif.gamma), + pow(c[2] / 255.0, sif.gamma), + 1.0, + ] + + for opacity in opacity_attribs: + if opacity in style.keys(): + color[3] *= float(style[opacity]) + return color + + +def extract_opacity(style, *opacity_attribs): + ret = 1.0 + for opacity in opacity_attribs: + if opacity in style.keys(): + ret *= float(style[opacity]) + return ret + + +def extract_width(style, width_attrib, mtx): + if width_attrib in style.keys(): + width = get_dimension(style[width_attrib]) + else: + width = 1 + + area_scale_factor = mtx[0][0] * mtx[1][1] - mtx[0][1] * mtx[1][0] + linear_scale_factor = math.sqrt(abs(area_scale_factor)) + + return width * linear_scale_factor / sif.kux + + +# ##### Main Class ######################################### +class SynfigExport(SynfigPrep): + def __init__(self): + SynfigPrep.__init__(self) + + def effect(self): + # Prepare the document for exporting + SynfigPrep.effect(self) + svg = self.document.getroot() + width = get_dimension(svg.get("width", 1024)) + height = get_dimension(svg.get("height", 768)) + + title = svg.getElement("svg:title") + if title is not None: + name = title.text + else: + name = svg.get("sodipodi:docname", "Synfig Animation 1") + + doc = SynfigDocument(width, height, name) + + layers = [] + for node in svg.iterchildren(): + layers += self.convert_node(node, doc) + + root_canvas = doc.get_root_canvas() + for layer in layers: + root_canvas.append(layer) + + self.synfig_document = doc.get_root_tree() + + def save(self, stream): + self.synfig_document.write(stream) + + def convert_node(self, node, d): + """Convert an SVG node to a list of Synfig layers""" + # Parse tags that don't draw any layers + if isinstance(node, SvgDocumentElement): + self.parse_defs(node, d) + return [] + elif not isinstance( + node, (Group, Anchor, Switch, PathElement, Metadata, NamedView) + ): + # An unsupported element + return [] + + layers = [] + if isinstance(node, Group): + for subnode in node: + layers += self.convert_node(subnode, d) + if isinstance(node, Layer): + name = node.label or "Inline Canvas" + layers = d.op_encapsulate(layers, name=name) + + elif isinstance(node, (Anchor, Switch)): + # Treat anchor and switch as a group + for subnode in node: + layers += self.convert_node(subnode, d) + elif isinstance(node, PathElement): + layers = self.convert_path(node, d) + + style = node.style + if "filter" in style.keys() and style["filter"].startswith("url"): + filter_id = style["filter"][5:].split(")")[0] + layers = d.op_filter(layers, filter_id) + + opacity = extract_opacity(style, "opacity") + if opacity != 1.0: + layers = d.op_fade(layers, opacity) + + return layers + + def parse_defs(self, node, d): + for child in node.iterchildren(): + if isinstance(child, Gradient): + self.parse_gradient(child, d) + elif child.TAG == "filter": + self.parse_filter(child, d) + + def parse_gradient(self, node, d): + if node.TAG == "linearGradient": + gradient_id = node.get("id", str(id(node))) + x1 = float(node.get("x1", "0.0")) + x2 = float(node.get("x2", "0.0")) + y1 = float(node.get("y1", "0.0")) + y2 = float(node.get("y2", "0.0")) + + mtx = node.gradientTransform.matrix + + link = node.get("xlink:href", "#")[1:] + spread_method = node.get("spreadMethod", "pad") + if link == "": + stops = self.parse_stops(node, d) + d.add_linear_gradient( + gradient_id, + [x1, y1], + [x2, y2], + mtx, + stops=stops, + spread_method=spread_method, + ) + else: + d.add_linear_gradient( + gradient_id, + [x1, y1], + [x2, y2], + mtx, + link=link, + spread_method=spread_method, + ) + elif node.TAG == "radialGradient": + gradient_id = node.get("id", str(id(node))) + cx = float(node.get("cx", "0.0")) + cy = float(node.get("cy", "0.0")) + r = float(node.get("r", "0.0")) + fx = float(node.get("fx", "0.0")) + fy = float(node.get("fy", "0.0")) + + mtx = node.gradientTransform.matrix + + link = node.get("xlink:href", "#")[1:] + spread_method = node.get("spreadMethod", "pad") + if link == "": + stops = self.parse_stops(node, d) + d.add_radial_gradient( + gradient_id, + [cx, cy], + r, + [fx, fy], + mtx, + stops=stops, + spread_method=spread_method, + ) + else: + d.add_radial_gradient( + gradient_id, + [cx, cy], + r, + [fx, fy], + mtx, + link=link, + spread_method=spread_method, + ) + + def parse_stops(self, node, d): + stops = {} + for stop in node.iterchildren(): + if stop.TAG == "stop": + offset = float(stop.get("offset")) + style = stop.style + stops[offset] = extract_color(style, "stop-color", "stop-opacity") + else: + raise MalformedSVGError("Child of gradient is not a stop") + + return stops + + def parse_filter(self, node, d): + filter_id = node.get("id", str(id(node))) + + # A filter is just like an operator (the op_* functions), + # except that it's created here + def the_filter(d, layers, is_end=False): + refs = {None: layers, "SourceGraphic": layers} # default + encapsulate_result = not is_end + + for child in node.iterchildren(): + if child.get("in") not in refs: + # "SourceAlpha", "BackgroundImage", + # "BackgroundAlpha", "FillPaint", "StrokePaint" + # are not supported + raise UnsupportedException + l_in = refs[child.get("in")] + l_out = [] + if child.TAG == "feGaussianBlur": + std_dev = child.get("stdDeviation", "0") + std_dev = std_dev.replace(",", " ").split() + x = float(std_dev[0]) + if len(std_dev) > 1: + y = float(std_dev[1]) + else: + y = x + + if x == 0 and y == 0: + l_out = l_in + else: + x = d.distance_svg2sif(x) + y = d.distance_svg2sif(y) + l_out = d.op_blur(l_in, x, y, is_end=True) + elif child.TAG == "feBlend": + # Note: Blend methods are not an exact match + # because SVG uses alpha channel in places where + # Synfig does not + mode = child.get("mode", "normal") + if mode == "normal": + blend_method = "composite" + elif mode == "multiply": + blend_method = "multiply" + elif mode == "screen": + blend_method = "screen" + elif mode == "darken": + blend_method = "darken" + elif mode == "lighten": + blend_method = "brighten" + else: + raise MalformedSVGError("Invalid blend method") + + if child.get("in2") == "BackgroundImage": + encapsulate_result = False + l_out = d.op_set_blend(l_in, blend_method) + d.op_set_blend( + l_in, "behind" + ) + elif child.get("in2") not in refs: + raise UnsupportedException + else: + l_in2 = refs[child.get("in2")] + l_out = l_in2 + d.op_set_blend(l_in, blend_method) + + else: + # This filter element is currently unsupported + raise UnsupportedException + + # Output the layers + if child.get("result"): + refs[child.get("result")] = l_out + + # Set the default for the next filter element + refs[None] = l_out + + # Return the output from the last element + if len(refs[None]) > 1 and encapsulate_result: + return d.op_encapsulate(refs[None]) + else: + return refs[None] + + d.add_filter(filter_id, the_filter) + + def convert_path(self, node, d): + """Convert an SVG path node to a list of Synfig layers""" + layers = [] + + node_id = node.get("id", str(id(node))) + style = node.style + + mtx = node.transform.matrix + blines = path_to_bline_list(node.get("d"), node.get("sodipodi:nodetypes"), mtx) + for bline in blines: + d.bline_coor_svg2sif(bline) + bline_guid = d.new_guid() + + if style.setdefault("fill", "#000000") != "none": + if style["fill"].startswith("url"): + # Set the color to black, so we can later overlay + # the shape with a gradient or pattern + color = [0, 0, 0, 1] + else: + color = extract_color(style, "fill", "fill-opacity") + + layer = d.create_layer( + "region", + node_id, + { + "bline": bline, + "color": color, + "winding_style": 1 + if style.setdefault("fill-rule", "nonzero") == "evenodd" + else 0, + }, + guids={"bline": bline_guid}, + ) + + if style["fill"].startswith("url"): + color_layer = self.convert_url( + style["fill"][5:].split(")")[0], mtx, d + )[0] + layer = d.op_color([layer], overlay=color_layer)[0] + layer = d.op_fade([layer], extract_opacity(style, "fill-opacity"))[ + 0 + ] + + layers.append(layer) + + if style.setdefault("stroke", "none") != "none": + if style["stroke"].startswith("url"): + # Set the color to black, so we can later overlay + # the shape with a gradient or pattern + color = [0, 0, 0, 1] + else: + color = extract_color(style, "stroke", "stroke-opacity") + + layer = d.create_layer( + "outline", + node_id, + { + "bline": bline, + "color": color, + "width": extract_width(style, "stroke-width", mtx), + "sharp_cusps": True + if style.setdefault("stroke-linejoin", "miter") == "miter" + else False, + "round_tip[0]": False + if style.setdefault("stroke-linecap", "butt") == "butt" + else True, + "round_tip[1]": False + if style.setdefault("stroke-linecap", "butt") == "butt" + else True, + }, + guids={"bline": bline_guid}, + ) + + if style["stroke"].startswith("url"): + color_layer = self.convert_url( + style["stroke"][5:].split(")")[0], mtx, d + )[0] + layer = d.op_color([layer], overlay=color_layer)[0] + layer = d.op_fade( + [layer], extract_opacity(style, "stroke-opacity") + )[0] + + layers.append(layer) + + return layers + + def convert_url(self, url_id, mtx, d): + """Return a list Synfig layers that represent the gradient with the given id""" + gradient = d.get_gradient(url_id) + if gradient is None: + # Patterns and other URLs not supported + return [None] + + if gradient["type"] == "linear": + layer = d.create_layer( + "linear_gradient", + url_id, + d.gradient_to_params(gradient), + guids={"gradient": gradient["stops_guid"]}, + ) + + if gradient["type"] == "radial": + layer = d.create_layer( + "radial_gradient", + url_id, + d.gradient_to_params(gradient), + guids={"gradient": gradient["stops_guid"]}, + ) + + trm = Transform(mtx) * Transform(gradient["mtx"]) + return d.op_transform([layer], trm.matrix) + + +if __name__ == "__main__": + SynfigExport().run() diff --git a/share/extensions/synfig_prepare.py b/share/extensions/synfig_prepare.py new file mode 100755 index 0000000..9899eec --- /dev/null +++ b/share/extensions/synfig_prepare.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Nikita Kitaev +# +# 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 +# +""" +Simplifies SVG files in preparation for sif export. +""" + +import os +import tempfile +from subprocess import PIPE, Popen +from inkex.command import inkscape, write_svg, ProgramRunError +from inkex.localization import inkex_gettext as _ +from inkex.base import TempDirMixin + +import inkex +from inkex import ( + load_svg, + Group, + PathElement, + ShapeElement, + Anchor, + Switch, + SvgDocumentElement, + Transform, +) + +###### Utility Classes #################################### + + +class MalformedSVGError(Exception): + """Raised when the SVG document is invalid or contains unsupported features""" + + def __init__(self, value): + self.value = value + + def __str__(self): + return ( + _( + """SVG document is invalid or contains unsupported features + +Error message: %s + +The SVG to Synfig converter is designed to handle SVG files that were created using Inkscape. Unsupported features are most likely to occur in SVG files written by other programs. +""" + ) + % repr(self.value) + ) + + +###### Utility Functions ################################## + +### Path related + + +def fuse_subpaths(path: inkex.Path): + """Fuse subpaths of a path. Should only be used on unstroked paths. + The idea is to replace every moveto by a lineto, and then walk all the extra lines + backwards to get the same fill. For unfilled paths, this gives visually good results + in cases with not-too-complex paths, i.e. no intersections. + There may be extra zero-length Lineto commands.""" + + result = inkex.Path() + return_stack = [] + for i, seg in enumerate(path.proxy_iterator()): + if seg.letter not in "zZmM": + result.append(seg.command) + elif i == 0: + result.append(seg.command) + first = seg.end_point + else: + # Add a line instead of the ZoneClose / Move command, and store + # the initial position. + return_to = seg.previous_end_point + if seg.letter in "mM": + if seg.previous_end_point != first: # only close if needed + # all paths must be closed for this algorithm to work. Since + # the path doesn't have a stroke, it's visually irrellevant. + result.append(inkex.paths.Line(*first)) + return_to = first + + return_stack += [return_to] + result.append(inkex.paths.Line(*seg.end_point)) + + first = seg.end_point + + # also close the last subpath + return_stack += [first] + + # now apply the return stack backwards + for point in return_stack[::-1]: + result.append(inkex.paths.Line(*point)) + + return result + + +def split_fill_and_stroke(path_node): + """Split a path into two paths, one filled and one stroked + + Returns a the list [fill, stroke], where each is the XML element of the + fill or stroke, or None. + """ + style = dict(inkex.Style.parse_str(path_node.get("style", ""))) + + # If there is only stroke or only fill, don't split anything + if "fill" in style and style["fill"] == "none": + if "stroke" not in style or style["stroke"] == "none": + return [None, None] # Path has neither stroke nor fill + else: + return [None, path_node] + if "stroke" not in style.keys() or style["stroke"] == "none": + return [path_node, None] + + group = Group() + fill = group.add(PathElement()) + stroke = group.add(PathElement()) + + d = path_node.pop("d") + if d is None: + raise AssertionError("Cannot split stroke and fill of non-path element") + + nodetypes = path_node.pop("sodipodi:nodetypes", None) + path_id = path_node.pop("id", str(id(path_node))) + transform = path_node.pop("transform", None) + path_node.pop("style") + + # Pass along all remaining attributes to the group + for attrib_name, attrib_value in path_node.attrib.items(): + group.set(attrib_name, attrib_value) + + group.set("id", path_id) + + # Next split apart the style attribute + style_group = {} + style_fill = {"stroke": "none", "fill": "#000000"} + style_stroke = {"fill": "none", "stroke": "none"} + + for key in style.keys(): + if key.startswith("fill"): + style_fill[key] = style[key] + elif key.startswith("stroke"): + style_stroke[key] = style[key] + elif key.startswith("marker"): + style_stroke[key] = style[key] + elif key.startswith("filter"): + style_group[key] = style[key] + else: + style_fill[key] = style[key] + style_stroke[key] = style[key] + + if len(style_group) != 0: + group.set("style", str(inkex.Style(style_group))) + + fill.set("style", str(inkex.Style(style_fill))) + stroke.set("style", str(inkex.Style(style_stroke))) + + # Finalize the two paths + fill.set("d", d) + stroke.set("d", d) + if nodetypes is not None: + fill.set("sodipodi:nodetypes", nodetypes) + stroke.set("sodipodi:nodetypes", nodetypes) + fill.set("id", path_id + "-fill") + stroke.set("id", path_id + "-stroke") + if transform is not None: + fill.set("transform", transform) + stroke.set("transform", transform) + + # Replace the original node with the group + path_node.getparent().replace(path_node, group) + + return [fill, stroke] + + +### Object related + + +def propagate_attribs( + node, parent_style={}, parent_transform=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] +): + """Propagate style and transform to remove inheritance""" + + # Don't enter non-graphical portions of the document + if not isinstance(node, (ShapeElement, SvgDocumentElement)): + return + + # Compose the transformations + if isinstance(node, SvgDocumentElement) and node.get("viewBox"): + vx, vy, vw, vh = [get_dimension(x) for x in node.get_viewbox()] + dw = get_dimension(node.get("width", vw)) + dh = get_dimension(node.get("height", vh)) + this_transform = Transform(translate=(-vx, -vy), scale=(dw / vw, dh / vh)) + del node.attrib["viewBox"] + else: + this_transform = Transform(parent_transform) + + this_transform @= node.transform + + # Compose the style attribs + this_style = dict(inkex.Style.parse_str(node.get("style", ""))) + remaining_style = {} # Style attributes that are not propagated + + non_propagated = ["filter"] # Filters should remain on the topmost ancestor + for key in non_propagated: + if key in this_style.keys(): + remaining_style[key] = this_style[key] + del this_style[key] + + # Create a copy of the parent style, and merge this style into it + parent_style_copy = parent_style.copy() + parent_style_copy.update(this_style) + this_style = parent_style_copy + + # Merge in any attributes outside of the style + style_attribs = ["fill", "stroke"] + for attrib in style_attribs: + if node.get(attrib): + this_style[attrib] = node.get(attrib) + del node.attrib[attrib] + + if isinstance(node, (SvgDocumentElement, Group, Anchor, Switch)): + # Leave only non-propagating style attributes + if remaining_style: + node.style = remaining_style + else: + if "style" in node.keys(): + del node.attrib["style"] + + # Remove the transform attribute + if "transform" in node.keys(): + del node.attrib["transform"] + + # Continue propagating on subelements + for child in node.iterchildren(): + propagate_attribs(child, this_style, this_transform) + else: + # This element is not a container + + # Merge remaining_style into this_style + this_style.update(remaining_style) + + # Set the element's style and transform attribs + node.style = this_style + node.transform = this_transform + + +### Style related + + +def get_dimension(s="1024"): + """Convert an SVG length string from arbitrary units to pixels""" + return inkex.units.convert_unit(s, "px") + + +###### Main Class ######################################### +class SynfigPrep(TempDirMixin, inkex.EffectExtension): + def effect(self): + """Transform document in preparation for exporting it into the Synfig format""" + + self.preprocess() + + # Remove inheritance of attributes + propagate_attribs(self.document.getroot()) + + # Fuse multiple subpaths in fills + for node in self.document.getroot().xpath("//svg:path"): + if node.get("d", "").lower().count("m") > 1: + # There are multiple subpaths + fill = split_fill_and_stroke(node)[0] + if fill is not None: + fill.path = fuse_subpaths(fill.path) + + def preprocess(self): + + actions = [ + "unlock-all", + # Flow roots contain rectangles inside them, so they need to be + # converted to paths separately from other shapes + "select-by-element:flowRoot", + "object-to-path", + "select-clear", + ] + + # Now convert all non-paths to paths + elements = ["rect", "circle", "ellipse", "line", "polyline", "polygon", "text"] + actions += ["select-by-element:" + i for i in elements] + actions += ["object-to-path", "select-clear"] + # unlink clones + actions += ["select-by-element:use", "object-unlink-clones"] + # save and overwrite + actions += ["export-overwrite", "export-do"] + + infile = os.path.join(self.tempdir, "input.svg") + write_svg(self.document, infile) + try: + inkscape(infile, actions=";".join(actions)) + except ProgramRunError as err: + inkex.errormsg(_("An error occurred during document preparation")) + inkex.errormsg(err.stderr.decode("utf-8")) + + with open(infile, "r") as stream: + self.document = load_svg(stream) + + return self.document + + +if __name__ == "__main__": + SynfigPrep().run() diff --git a/share/extensions/tar_layers.inx b/share/extensions/tar_layers.inx new file mode 100644 index 0000000..2e726bf --- /dev/null +++ b/share/extensions/tar_layers.inx @@ -0,0 +1,17 @@ + + + Collection of SVG files One per root layer + org.inkscape.output.tar_layers + org.inkscape.output.svg.inkscape + + .tar + application/tar + Layers as Separate SVG (*.tar) + Each layer split into it's own svg file and collected as a tape archive (tar file) + false + + + diff --git a/share/extensions/tar_layers.py b/share/extensions/tar_layers.py new file mode 100755 index 0000000..3a4732c --- /dev/null +++ b/share/extensions/tar_layers.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2014 Martin Owens, email@doctormo.org +# +# 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. +# +""" +An extension to export multiple svg files from a single svg file containing layers. + +Each defs is duplicated for each svg outputted. +""" + +from __future__ import unicode_literals +import os +import sys +import copy +import tarfile +import io +import calendar +import time +import inkex + + +class TarLayers(inkex.OutputExtension): + """Entry point to our layers export""" + + def make_template(self): + """Returns the current document as a new empty document with the same defs""" + newdoc = copy.deepcopy(self.document) + for (name, layer) in self.layers(newdoc): + layer.getparent().remove(layer) + return newdoc + + def layers(self, document): + for node in document.getroot().iterchildren(): + if isinstance(node, inkex.Layer) and node.label: + yield (node.label, node) + + def io_document(self, name, doc): + string = io.BytesIO() + doc.write(string) + info = tarfile.TarInfo(name=name + ".svg") + info.mtime = calendar.timegm(time.gmtime()) + info.size = string.tell() + string.seek(0) + return dict(tarinfo=info, fileobj=string) + + def save(self, stream): + """Save the tar file output""" + tar = tarfile.open(fileobj=stream, mode="w|") + + # Switch stdout to binary on Windows. + if sys.platform == "win32": + import msvcrt + + try: + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + except io.UnsupportedOperation: + pass # The .fileno() function is not available during pytest runs + + template = self.make_template() + + previous = None + for (name, _layer) in self.layers(self.document): + layer = copy.deepcopy(_layer) + if previous != None: + template.getroot().replace(previous, layer) + else: + template.getroot().append(layer) + previous = layer + + tar.addfile(**self.io_document(name, template)) + + +if __name__ == "__main__": # pragma: no cover + TarLayers().run() diff --git a/share/extensions/template.py b/share/extensions/template.py new file mode 100755 index 0000000..8206697 --- /dev/null +++ b/share/extensions/template.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 Martin Owens +# +# 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. +# +""" +Generic template functionality controlled by the INX file. +""" + +import inkex + + +class InxDefinedTemplate(inkex.TemplateExtension): + """Most functionality is in TemplateExtension""" + + multi_inx = True + themes = { + "white": ("#ffffff", "#666666"), + "gray": ("#808080", "#444444"), + "black": ("#000000", "#999999"), + } + + def add_arguments(self, pars): + pars.add_argument("--background", type=self.arg_theme, default="normal") + pars.add_argument("--noborder", type=inkex.Boolean) + + def arg_theme(self, value): + """Set the page theme based on the value given""" + if value in self.themes: + return self.themes[value] + return None + + def set_namedview(self, width, height, unit): + super(InxDefinedTemplate, self).set_namedview(width, height, unit) + namedview = self.svg.namedview + if self.options.background: + namedview.set("pagecolor", self.options.background[0]) + namedview.set("bordercolor", self.options.background[1]) + namedview.set("inkscape:pageopacity", "1.0") + namedview.set("inkscape:pageshadow", "0") + + if self.options.noborder: + namedview.set("bordercolor", namedview.get("pagecolor")) + namedview.set("borderopacity", "0") + + +if __name__ == "__main__": + InxDefinedTemplate().run() diff --git a/share/extensions/template_business_card.inx b/share/extensions/template_business_card.inx new file mode 100644 index 0000000..2f9f044 --- /dev/null +++ b/share/extensions/template_business_card.inx @@ -0,0 +1,30 @@ + + + Business Card + org.inkscape.template.business_card + + + + + + + + + + + + + all + + + Business Card... + Tavmjong Bah + Business card of chosen size. + 2014-10-09 + business card + + + diff --git a/share/extensions/template_desktop.inx b/share/extensions/template_desktop.inx new file mode 100644 index 0000000..5d2e71a --- /dev/null +++ b/share/extensions/template_desktop.inx @@ -0,0 +1,42 @@ + + + Desktop + org.inkscape.template.desktop + + + + + + + + + + + + + + + + + + + + + 1920 + 1080 + + + all + + + Desktop... + Tavmjong Bah + Empty desktop of chosen size. + 2014-10-09 + empty desktop + + + diff --git a/share/extensions/template_dvd_cover.inx b/share/extensions/template_dvd_cover.inx new file mode 100644 index 0000000..ff12eaf --- /dev/null +++ b/share/extensions/template_dvd_cover.inx @@ -0,0 +1,29 @@ + + + DVD Cover + org.inkscape.template.dvd_cover + + + + + + + + + 3 + + + all + + + DVD Cover... + Tavmjong Bah + DVD cover of chosen size. + 2014-10-10 + dvd cover + + + diff --git a/share/extensions/template_dvd_cover.py b/share/extensions/template_dvd_cover.py new file mode 100755 index 0000000..90215cc --- /dev/null +++ b/share/extensions/template_dvd_cover.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2010 Tavmjong Bah +# 2019 Martin Owens +# +# 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. +# +""" +Generic template functionality controlled by the INX file. +""" + +import inkex + + +class DvdCover(inkex.TemplateExtension): + """Create an empty DVD Cover (in mm)""" + + multi_inx = True + + def add_arguments(self, pars): + pars.add_argument( + "-s", "--spine", type=float, default=14.0, help="Dvd spine width (mm)" + ) + pars.add_argument( + "-b", + "--bleed", + type=float, + default=3.0, + help="Bleed (extra area around image", + ) + + def get_size(self): + # Dimensions in mm + width = 259.0 # Before adding spine width or bleed + height = 183.0 # Before adding bleed + bleed = self.options.bleed + spine = self.options.spine + + return (width + spine + bleed * 2.0, "mm", height + bleed * 2.0, "mm") + + def set_namedview(self, width, height, unit): + super(DvdCover, self).set_namedview(width, height, unit) + (width, _, height, unit) = self.get_size() + bleed, spine = self.options.bleed, self.options.spine + self.svg.namedview.new_guide(bleed, True, "bottom") + self.svg.namedview.new_guide(height - bleed, True, "top") + self.svg.namedview.new_guide(bleed, False, "left edge") + self.svg.namedview.new_guide((width - spine) / 2.0, False, "left spline") + self.svg.namedview.new_guide((width + spine) / 2.0, False, "right spline") + self.svg.namedview.new_guide(width - bleed, False, "top") + + +if __name__ == "__main__": + DvdCover().run() diff --git a/share/extensions/template_envelope.inx b/share/extensions/template_envelope.inx new file mode 100644 index 0000000..f10a408 --- /dev/null +++ b/share/extensions/template_envelope.inx @@ -0,0 +1,25 @@ + + + Envelope + org.inkscape.template.envelope + + + + + + + + all + + + Envelope... + Windell Oskay + Blank envelope of chosen size. + 2019-07-11 + empty envelope dl no10 + + + diff --git a/share/extensions/template_generic.inx b/share/extensions/template_generic.inx new file mode 100644 index 0000000..3ce33ce --- /dev/null +++ b/share/extensions/template_generic.inx @@ -0,0 +1,41 @@ + + + Generic Canvas + org.inkscape.template.generic_canvas + + 800 + 600 + + + + + + + + + + + + + + + + + + false + + + all + + + Generic canvas... + Tavmjong Bah + Generic canvas of chosen size. + 2014-10-09 + empty generic canvas + + + diff --git a/share/extensions/template_icon.inx b/share/extensions/template_icon.inx new file mode 100644 index 0000000..1ce6db5 --- /dev/null +++ b/share/extensions/template_icon.inx @@ -0,0 +1,23 @@ + + + Icon + org.inkscape.template.icon + + 16 + true + + + all + + + Icon... + Tavmjong Bah + Empty icon of chosen size. + 2014-10-09 + empty icon + + + diff --git a/share/extensions/template_page.inx b/share/extensions/template_page.inx new file mode 100644 index 0000000..413a282 --- /dev/null +++ b/share/extensions/template_page.inx @@ -0,0 +1,43 @@ + + + Blank Page + org.inkscape.template.page + + + + + + + + + + + + + + + + + + + + + + + false + + + all + + + Blank Page... + Jan Darowski, updated by Tavmjong Bah + Empty page of chosen size. + 2019-07-11 + empty page sheet tabloid ledger letter legal print paper a4 a3 a5 letter black white opaque + + + diff --git a/share/extensions/template_seamless_pattern.inx b/share/extensions/template_seamless_pattern.inx new file mode 100644 index 0000000..7495df5 --- /dev/null +++ b/share/extensions/template_seamless_pattern.inx @@ -0,0 +1,24 @@ + + + Seamless Pattern + org.inkscape.template.seamless_pattern + + 100 + 100 + + + all + + + Seamless Pattern... + Jabiertxof + Create seamless patterns. + 2014-10-16 + live seamless patterns + + + + diff --git a/share/extensions/template_seamless_pattern.py b/share/extensions/template_seamless_pattern.py new file mode 100755 index 0000000..b80610e --- /dev/null +++ b/share/extensions/template_seamless_pattern.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Written by Jabiertxof +# V.06 + +import os + +from inkex import load_svg, TemplateExtension, Transform + + +class SeamlessPattern(TemplateExtension): + """Generate a seamless pattern template""" + + multi_inx = True + + @classmethod + def get_template(cls, **kwargs): + name = "seamless_pattern.svg" + path = os.path.dirname(os.path.realpath(__file__)) + return load_svg(os.path.join(path, name)) + + def set_namedview(self, width, height, unit): + width = self.options.width + height = self.options.height + factor = width / height + clip_rect = self.svg.getElementById("clipPathRect") + clip_rect.set("width", str(width)) + clip_rect.set("height", str(height)) + + scale = Transform(scale=(width / 100, height / 100)) + self.svg.getElementById("designTop").transform = scale + self.svg.getElementById("designBottom").transform = scale + + scale = (1, factor) if factor <= 1 else (1 / factor, 1) + for child in self.svg.getElementById("designTop"): + child.transform = Transform(scale=scale) + + text_preview = self.svg.getElementById("textPreview") + if text_preview is not None: + x = width / 100.0 / factor + y = height / 100.0 + if factor <= 1: + x *= factor + y *= factor + text_preview.transform = Transform( + translate=(int(width) * 2, 0), scale=(x, y) + ) + + info_group = self.svg.getElementById("infoGroup") + if info_group is not None: + scale = 100 if factor <= 1 else 1000 + info_group.transform = Transform( + scale=(width / scale, height / scale * factor) + ) + + sides = [(x, y) for y in (-height, 0, height) for x in (-width, 0, width)] + for i, (x, y) in enumerate(sides): + top = self.svg.getElementById("top{i}".format(i=i + 1)) + bottom = self.svg.getElementById("bottom{i}".format(i=i + 1)) + if top is not None and bottom is not None: + bottom.transform = top.transform = Transform(translate=(x, y)) + + clones = [ + (x, y) for x in (0, width, width * 2) for y in (0, height, height * 2) + ] + for i, (x, y) in enumerate(clones): + preview = self.svg.getElementById("clonePreview{i}".format(i=i)) + if preview is not None: + preview.transform = Transform(translate=(x, y)) + + pattern_generator = self.svg.getElementById("fullPatternClone") + if pattern_generator is not None: + pattern_generator.transform = Transform(translate=(width * 2, -height)) + pattern_generator.set("inkscape:tile-cx", width / 2) + pattern_generator.set("inkscape:tile-cy", height / 2) + pattern_generator.set("inkscape:tile-w", width) + pattern_generator.set("inkscape:tile-h", height) + pattern_generator.set("inkscape:tile-x0", width) + pattern_generator.set("inkscape:tile-y0", height) + pattern_generator.set("width", width) + pattern_generator.set("height", height) + + namedview = self.svg.namedview + namedview.set("inkscape:document-units", "px") + namedview.set("inkscape:cx", (width * 5.5) / 2) + namedview.set("inkscape:cy", "0") + namedview.set("inkscape:zoom", 1 / (width / 100)) + + +if __name__ == "__main__": + SeamlessPattern().run() diff --git a/share/extensions/template_video.inx b/share/extensions/template_video.inx new file mode 100644 index 0000000..7d8c63d --- /dev/null +++ b/share/extensions/template_video.inx @@ -0,0 +1,35 @@ + + + Video Screen + org.inkscape.template.video + + + + + + + + + + + + + + 1920 + 1080 + + + all + + + Video... + Tavmjong Bah + Video screen of chosen size. + 2014-10-09 + empty video + + + diff --git a/share/extensions/tests/README.md b/share/extensions/tests/README.md new file mode 100644 index 0000000..d5a9a85 --- /dev/null +++ b/share/extensions/tests/README.md @@ -0,0 +1 @@ +See ../TESTING.md diff --git a/share/extensions/tests/__init__.py b/share/extensions/tests/__init__.py new file mode 100644 index 0000000..9bad579 --- /dev/null +++ b/share/extensions/tests/__init__.py @@ -0,0 +1 @@ +# coding=utf-8 diff --git a/share/extensions/tests/add_pylint.py b/share/extensions/tests/add_pylint.py new file mode 100755 index 0000000..a0cf840 --- /dev/null +++ b/share/extensions/tests/add_pylint.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (C) 2019 Martin Owens +# +# 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, USA. +# +""" +Add pylint scores to html coverage report html. + +This would be done deeper in coverage (as a plugin) but that functionality isn't available. +""" + +import os +import re +import sys +from pylint import lint +from pylint.reporters.text import TextReporter + +DIR = os.path.dirname(__file__) +REX = re.compile(r".+?\">([^<]+\.py).+?\<\/tr\>") + +ARGS = ["--rcfile=" + os.path.join(DIR, "..", ".pylintrc")] +stdout = sys.stdout + + +class WritableObject(object): + """dummy output stream for pylint""" + + def __init__(self): + self.content = [] + + def write(self, line): + "dummy write" + self.content.append(line) + + def read(self): + "dummy read" + return self.content + + +def run_pylint(fname): + "run pylint on the given file" + pylint_output = WritableObject() + # Pipe lint errors to devnull + temp, sys.stderr = sys.stderr, open(os.devnull, "w", encoding="utf-8") + try: + lint.Run([fname] + ARGS, reporter=TextReporter(pylint_output), exit=False) + except Exception: # pylint: disable=broad-except + return None + sys.stderr = temp + for output in pylint_output.read(): + rates = re.findall(r"rated at (\-?[\d\.]+)", output) + for rate in rates: + return float(rate) + if " rated " in output: + print(f"FAIL: {output}") + return None + + +def add_lint(fname): + """ + Parse index.html and append in the needed pylint score for this file. + """ + # Read in index file and strip out html whitespace (for easier rex'ing) + with open(fname, "r", encoding="utf-8") as fhl: + html = re.sub(r"\>\s+\<", "><", fhl.read()) + + # Keep a tab on how much we've inserted into the html + adjust = 0 + scores = [] + for match in REX.finditer(html): + score = add_lint_one(match.groups()[0]) + scores.append(score) + (start, end) = match.span() + start += adjust + end += adjust + old_content = html[start:end] + new_content = old_content[:-5] + f"{score}" + html = html[:start] + new_content + html[end:] + adjust += len(new_content) - len(old_content) + + total = sum(scores) / len(scores) + html = html.replace("coverage", "coveragepylint") + html = html.replace("", f"{total:.2f}") + + with open(fname, "w") as fhl: + fhl.write(html) + + +def add_lint_one(py_file): + score = run_pylint(py_file) + if score is None: + score = -11.0 + return score + + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[-1].endswith(".html"): + for filename in sys.argv[1:]: + if os.path.isfile(filename): + add_lint(filename) + else: + for my_py_file in sys.argv[1:]: + score = add_lint_one(my_py_file) + print(f"{score},{my_py_file}") diff --git a/share/extensions/tests/data/README.md b/share/extensions/tests/data/README.md new file mode 100644 index 0000000..21dd50d --- /dev/null +++ b/share/extensions/tests/data/README.md @@ -0,0 +1,10 @@ +Files here should only be used in tests and won't be installed with Inkscape extensions. + +Folders: + + io - Non SVG files which extensions can read or save to for comparisons. + svg - SVG files which tests read in and test extensions and modules with. + cmd - Caches of calls to external programs, used when those programs are not available. + refs - Comparison files, all the expected outputs of calls. + batches - Data files where each row contains test data for the module. + diff --git a/share/extensions/tests/data/batches/barcodes.dat b/share/extensions/tests/data/batches/barcodes.dat new file mode 100644 index 0000000..38c1eaa --- /dev/null +++ b/share/extensions/tests/data/batches/barcodes.dat @@ -0,0 +1,513 @@ +ean8:9493712:2020001011010001100010110111101020201000100110011011011001100110202 +ean8:2811738:2020010011011011100110010011001020201000100100001010010001011100202 +ean8:2248057:2020010011001001101000110110111020201110010100111010001001010000202 +ean8:0995042:2020001101000101100010110110001020201110010101110011011001110100202 +ean8:0262682:2020001101001001101011110010011020201010000100100011011001010000202 +ean8:2006346:2020010011000110100011010101111020201000010101110010100001000100202 +ean8:9892307:2020001011011011100010110010011020201000010111001010001001010000202 +ean8:7033691:2020111011000110101111010111101020201010000111010011001101000100202 +ean8:6587381:2020101111011000101101110111011020201000010100100011001101010000202 +ean8:4491441:2020100011010001100010110011001020201011100101110011001101000100202 +ean8:0099044:2020001101000110100010110001011020201110010101110010111001001000202 +ean8:7565347:2020111011011000101011110110001020201000010101110010001001000100202 +ean8:0764195:2020001101011101101011110100011020201100110111010010011101011100202 +ean8:4882328:2020100011011011101101110010011020201000010110110010010001110100202 +ean8:4635078:2020100011010111101111010110001020201110010100010010010001000100202 +ean8:8992114:2020110111000101100010110010011020201100110110011010111001101100202 +ean8:6658162:2020101111010111101100010110111020201100110101000011011001001000202 +ean8:7880049:2020111011011011101101110001101020201110010101110011101001010000202 +ean8:7782648:2020111011011101101101110010011020201010000101110010010001110010202 +ean8:8249002:2020110111001001101000110001011020201110010111001011011001000100202 +ean8:8735885:2020110111011101101111010110001020201001000100100010011101001000202 +ean8:9818050:2020001011011011100110010110111020201110010100111011100101110100202 +ean8:3410390:2020111101010001100110010001101020201000010111010011100101010000202 +ean8:9699144:2020001011010111100010110001011020201100110101110010111001101100202 +ean8:7628790:2020111011010111100100110110111020201000100111010011100101110100202 +ean8:2020310:2020010011000110100100110001101020201000010110011011100101001000202 +ean8:0429248:2020001101010001100100110001011020201101100101110010010001000100202 +ean8:3135528:2020111101001100101111010110001020201001110110110010010001001110202 +ean8:3182301:2020111101001100101101110010011020201000010111001011001101101100202 +ean8:0320063:2020001101011110100100110001101020201110010101000010000101010000202 +ean8:0865925:2020001101011011101011110110001020201110100110110010011101001110202 +ean8:3413434:2020111101010001100110010111101020201011100100001010111001011100202 +ean8:6730313:2020101111011101101111010001101020201000010110011010000101000100202 +ean8:4091215:2020100011000110100010110011001020201101100110011010011101001000202 +ean8:6504268:2020101111011000100011010100011020201101100101000010010001000100202 +ean8:0127593:2020001101001100100100110111011020201001110111010010000101000010202 +ean8:9214184:2020001011001001100110010100011020201100110100100010111001100110202 +ean8:4457000:2020100011010001101100010111011020201110010111001011100101101100202 +ean8:2575579:2020010011011000101110110110001020201001110100010011101001011100202 +ean8:3501739:2020111101011000100011010011001020201000100100001011101001011100202 +ean8:0733658:2020001101011101101111010111101020201010000100111010010001011100202 +ean8:6162818:2020101111001100101011110010011020201001000110011010010001101100202 +ean8:2397509:2020010011011110100010110111011020201001110111001011101001001110202 +ean8:3813610:2020111101011011100110010111101020201010000110011011100101001000202 +ean8:9488712:2020001011010001101101110110111020201000100110011011011001110100202 +ean8:1754326:2020011001011101101100010100011020201000010110110010100001101100202 +ean8:5221351:2020110001001001100100110011001020201000010100111011001101110100202 +ean8:6047658:2020101111000110101000110111011020201010000100111010010001010000202 +ean8:0475473:2020001101010001101110110110001020201011100100010010000101101100202 +ean8:0775368:2020001101011101101110110110001020201000010101000010010001001000202 +ean8:5825189:2020110001011011100100110110001020201100110100100011101001001000202 +ean8:9934666:2020001011000101101111010100011020201010000101000010100001110100202 +ean8:4849196:2020100011011011101000110001011020201100110111010010100001110100202 +ean8:6672405:2020101111010111101110110010011020201011100111001010011101010000202 +ean8:6368942:2020101111011110101011110110111020201110100101110011011001010000202 +ean8:0356360:2020001101011110101100010101111020201000010101000011100101100110202 +ean8:1506024:2020011001011000100011010101111020201110010110110010111001101100202 +ean8:0218852:2020001101001001100110010110111020201001000100111011011001101100202 +ean8:4357801:2020100011011110101100010111011020201001000111001011001101010000202 +ean8:8268643:2020110111001001101011110110111020201010000101110010000101000100202 +ean8:0117677:2020001101001100100110010111011020201010000100010010001001000010202 +ean8:8066330:2020110111000110101011110101111020201000010100001011100101110010202 +ean8:3074324:2020111101000110101110110100011020201000010110110010111001000010202 +ean8:7241642:2020111011001001101000110011001020201010000101110011011001010000202 +ean8:3375910:2020111101011110101110110110001020201110100110011011100101011100202 +ean8:5797167:2020110001011101100010110111011020201100110101000010001001011100202 +ean8:4413827:2020100011010001100110010111101020201001000110110010001001100110202 +ean8:0008083:2020001101000110100011010110111020201110010100100010000101001110202 +ean8:3240693:2020111101001001101000110001101020201010000111010010000101100110202 +ean8:3358989:2020111101011110101100010110111020201110100100100011101001000010202 +ean8:2525297:2020010011011000100100110110001020201101100111010010001001101100202 +ean8:9429514:2020001011010001100100110001011020201001110110011010111001010000202 +ean8:7496160:2020111011010001100010110101111020201100110101000011100101000010202 +ean8:2549811:2020010011011000101000110001011020201001000110011011001101110010202 +ean8:0366059:2020001101011110101011110101111020201110010100111011101001100110202 +ean8:7565529:2020111011011000101011110110001020201001110110110011101001000100202 +ean8:0544331:2020001101011000101000110100011020201000010100001011001101011100202 +ean8:5278325:2020110001001001101110110110111020201000010110110010011101001000202 +ean8:9659719:2020001011010111101100010001011020201000100110011011101001011100202 +ean8:6060276:2020101111000110101011110001101020201101100100010010100001000010202 +ean8:9983234:2020001011000101101101110111101020201101100100001010111001010000202 +ean8:9912723:2020001011000101100110010010011020201000100110110010000101000100202 +ean8:3934993:2020111101000101101111010100011020201110100111010010000101011100202 +ean8:9878705:2020001011011011101110110110111020201000100111001010011101110010202 +ean8:6099896:2020101111000110100010110001011020201001000111010010100001001110202 +ean8:9344302:2020001011011110101000110100011020201000010111001011011001110100202 +ean8:5779196:2020110001011101101110110001011020201100110111010010100001001000202 +ean8:2670364:2020010011010111101110110001101020201000010101000010111001110010202 +ean8:4049157:2020100011000110101000110001011020201100110100111010001001001000202 +ean8:6303180:2020101111011110100011010111101020201100110100100011100101001110202 +ean8:4252404:2020100011001001101100010010011020201011100111001010111001001110202 +ean8:6442834:2020101111010001101000110010011020201001000100001010111001001110202 +ean8:7330702:2020111011011110101111010001101020201000100111001011011001110010202 +ean8:6650523:2020101111010111101100010001101020201001110110110010000101001110202 +ean8:3261954:2020111101001001101011110011001020201110100100111010111001010000202 +ean8:1149083:2020011001001100101000110001011020201110010100100010000101001000202 +ean8:1227062:2020011001001001100100110111011020201110010101000011011001110010202 +ean8:7770854:2020111011011101101110110001101020201001000100111010111001110010202 +ean8:4841093:2020100011011011101000110011001020201110010111010010000101110100202 +ean8:9642244:2020001011010111101000110010011020201101100101110010111001100110202 +ean13:082432472648:20201101110010011010001101111010010011010001102020100010011011001010000101110010010001110010202 +ean13:867963203104:20201011110010001000101100001010100001001001102020111001010000101100110111001010111001001110202 +ean13:509274672682:20200011010010111001101101110110100011000010102020100010011011001010000100100011011001110010202 +ean13:137969745319:20201111010111011001011101011110010111001000102020101110010011101000010110011011101001101100202 +ean13:167788639568:20201011110111011001000101101110001001000010102020100001011101001001110101000010010001101100202 +ean13:763909437639:20201011110100001000101101001110001011001110102020100001010001001010000100001011101001110010202 +ean13:552090940230:20201100010011011010011100010110001101001011102020101110011100101101100100001011100101110100202 +ean13:064430020090:20201011110100011010001101111010001101000110102020110110011100101110010111010011100101001000202 +ean13:932131660272:20201111010011011011001101111010110011010111102020101000011100101101100100010011011001001000202 +ean13:697948544222:20200010110010001001011100111010110111011000102020101110010111001101100110110011011001110010202 +ean13:156973387097:20201100010101111001011101110110100001010000102020100100010001001110010111010010001001100110202 +ean13:742353933447:20201000110011011011110101110010111101001011102020100001010000101011100101110010001001001000202 +ean13:165804313397:20201011110110001000100100011010011101010000102020110011010000101000010111010010001001101100202 +ean13:142542648187:20201000110010011011100101000110011011000010102020101110010010001100110100100010001001101100202 +ean13:293746185362:20200010110111101001000100111010101111011001102020100100010011101000010101000011011001011100202 +ean13:079018947306:20201110110001011000110100110010110111000101102020101110010001001000010111001010100001110010202 +ean13:114714603442:20200110010100011001000100110010011101000010102020111001010000101011100101110011011001000100202 +ean13:886864480655:20201101110000101011011100001010011101010001102020100100011100101010000100111010011101011100202 +ean13:087399049352:20201101110111011011110100010110001011000110102020101110011101001000010100111011011001000010202 +ean13:680731212600:20201101110100111001000101000010011001001001102020110011011011001010000111001011100101001000202 +ean13:839853108496:20201111010010111011011101110010100001001100102020111001010010001011100111010010100001001000202 +ean13:759662798861:20201100010010111010111100001010010011001000102020111010010010001001000101000011001101011100202 +ean13:522030126885:20200100110011011010011101111010001101011001102020110110010100001001000100100010011101011100202 +ean13:872252192093:20201110110011011001001101110010011011001100102020111010011011001110010111010010000101011100202 +ean13:978323527315:20201110110001001010000100100110100001011000102020110110010001001000010110011010011101110100202 +ean13:594820728295:20200010110011101000100100100110001101001000102020110110010010001101100111010010011101000100202 +ean13:817309047999:20200110010010001011110101001110010111000110102020101110010001001110100111010011101001011100202 +ean13:529552650589:20200100110010111011100101100010010011000010102020100111011100101001110100100011101001000010202 +ean13:301953031072:20200011010011001001011101110010100001000110102020100001011001101110010100010011011001101100202 +ean13:279759074172:20201110110001011001000101110010001011010011102020100010010111001100110100010011011001011100202 +ean13:966269952443:20201011110000101001101101011110010111000101102020100111011011001011100101110010000101000100202 +ean13:393886491651:20200010110111101000100100010010000101010001102020111010011001101010000100111011001101110100202 +ean13:592818880852:20200010110011011000100100110010110111000100102020100100011100101001000100111011011001110010202 +ean13:629415132010:20200100110010111001110101100110110001001100102020100001011011001110010110011011100101001000202 +ean13:649798154930:20201000110010111001000100101110110111001100102020100111010111001110100100001011100101110100202 +ean13:106475417609:20200011010101111001110101110110111001001110102020110011010001001010000111001011101001110010202 +ean13:853904645292:20201100010100001000101101001110011101010111102020101110010011101101100111010011011001100110202 +ean13:431977667645:20201111010110011000101101110110010001000010102020101000010001001010000101110010011101000010202 +ean13:814819509497:20200110010011101011011101100110010111011000102020111001011101001011100111010010001001000100202 +ean13:308817835364:20200011010110111000100101100110010001011011102020100001010011101000010101000010111001011100202 +ean13:618801393027:20200110010001001000100101001110011001011110102020111010010000101110010110110010001001110010202 +ean13:164480667538:20201011110100011001110101101110100111000010102020101000010001001001110100001010010001011100202 +ean13:081023710137:20201101110011001000110100100110111101011101102020110011011100101100110100001010001001000100202 +ean13:493359422890:20200010110100001011110101100010010111001110102020110110011011001001000111010011100101110010202 +ean13:275532814865:20201110110110001011100101000010010011000100102020110011010111001001000101000010011101001000202 +ean13:111345042302:20200110010011001010000101000110111001010011102020101110011011001000010111001011011001001000202 +ean13:513537464719:20200110010100001011100101111010111011001110102020101000010111001000100110011011101001001110202 +ean13:766449694282:20201011110000101010001100111010001011000010102020111010010111001101100100100011011001110100202 +ean13:961792988802:20201011110110011001000100010110011011000101102020100100010010001001000111001011011001001110202 +ean13:866540005468:20201011110000101011000100111010100111000110102020111001010011101011100101000010010001101100202 +ean13:888983089059:20201101110001001000101100010010100001000110102020100100011101001110010100111011101001100110202 +ean13:722513175727:20200100110011011011000101100110111101011001102020100010010011101000100110110010001001110100202 +ean13:843297735811:20201000110100001001001100101110010001011101102020100001010011101001000110011011001101101100202 +ean13:627233353075:20200100110010001001101101000010111101011110102020100111010000101110010100010010011101110010202 +ean13:203591705672:20200011010111101011100100101110011001001000102020111001010011101010000100010011011001001110202 +ean13:686779501514:20201101110000101001000100100010001011011000102020111001011001101001110110011010111001001110202 +ean13:379483955591:20201110110001011001110100010010100001000101102020100111010011101001110111010011001101101100202 +ean13:576363706332:20201110110000101010000101011110111101001000102020111001010100001000010100001011011001000010202 +ean13:295226681860:20200010110110001001101100110110101111000010102020100100011001101001000101000011100101110100202 +ean13:901443422086:20200011010110011001110101000110100001010001102020110110011011001110010100100010100001000100202 +ean13:093300442985:20200010110111101011110100011010001101010001102020101110011011001110100100100010011101000010202 +ean13:517520551545:20200110010010001011100100100110001101011100102020100111011001101001110101110010011101000010202 +ean13:370982564882:20201110110001101001011100010010011011011000102020101000010111001001000100100011011001110010202 +ean13:640884610730:20201000110100111000100100010010100011010111102020110011011100101000100100001011100101001110202 +ean13:601211133573:20200011010110011001101101100110011001001100102020100001010000101001110100010010000101110100202 +ean13:772390839786:20201110110011011011110100101110001101000100102020100001011101001000100100100010100001110100202 +ean13:037823325554:20201111010111011011011100100110111101011110102020110110010011101001110100111010111001000010202 +ean13:636746415900:20201111010000101001000100111010101111010001102020110011010011101110100111001011100101000100202 +ean13:378365729312:20201110110110111010000100001010111001011101102020110110011101001000010110011011011001110010202 +ean13:588008084415:20201101110001001010011100011010110111010011102020100100010111001011100110011010011101000010202 +ean13:493847586062:20200010110100001011011101000110010001011100102020100100010100001110010101000011011001110010202 +ean13:661725378018:20201011110110011001000100110110110001011110102020100010010010001110010110011010010001110010202 +ean13:785941917380:20201101110111001000101100111010011001001011102020110011010001001000010100100011100101011100202 +ean13:476858945743:20201110110000101011011101100010001001001011102020101110010011101000100101110010000101010000202 +ean13:621022451023:20200100110110011010011100110110010011010001102020100111011001101110010110110010000101001000202 +ean13:738611126276:20201111010001001010111101100110011001011001102020110110010100001101100100010010100001110010202 +ean13:610023637901:20200110010100111010011100110110111101010111102020100001010001001110100111001011001101001000202 +ean13:310432899227:20200110010001101001110101000010011011011011102020111010011101001101100110110010001001110010202 +ean13:079481718507:20201110110001011010001101101110011001011101102020110011010010001001110111001010001001000010202 +ean13:794525704564:20200010110011101011000100110110110001001000102020111001010111001001110101000010111001010000202 +ean13:367079205365:20201011110111011010011100100010010111001001102020111001010011101000010101000010011101100110202 +ean13:791478205064:20200010110110011010001100100010110111001101102020111001010011101110010101000010111001000100202 +ean13:622805103976:20200100110011011000100101001110110001001100102020111001010000101110100100010010100001100110202 +ean13:659692878482:20201100010010111000010100101110010011011011102020100010010010001011100100100011011001011100202 +ean13:312673979722:20200110010010011000010100100010100001000101102020100010011101001000100110110011011001110010202 +ean13:634789369262:20201111010011101001000100010010001011011110102020101000011101001101100101000011011001000100202 +ean13:508031061191:20200011010001001010011101111010011001010011102020101000011001101100110111010011001101000100202 +ean13:617546677352:20200110010010001011100100111010101111010111102020100010010001001000010100111011011001000010202 +ean13:386750842077:20201101110101111001000101110010100111011011102020101110011011001110010100010010001001100110202 +ean13:217930060540:20200110010111011001011101000010001101010011102020101000011100101001110101110011100101100110202 +ean13:529453929533:20200100110010111001110101100010111101001011102020110110011101001001110100001010000101000010202 +ean13:403667633768:20200011010100001010111101011110010001000010102020100001010000101000100101000010010001110100202 +ean13:788401327704:20201101110001001010001101001110011001010000102020110110010001001000100111001010111001000100202 +ean13:316882500762:20200110010101111000100100010010011011011000102020111001011100101000100101000011011001101100202 +ean13:413254666172:20200110010100001001001101100010011101000010102020101000010100001100110100010011011001100110202 +ean13:666719764771:20201011110000101001000101100110001011011101102020101000010111001000100100010011001101100110202 +ean13:502326102133:20200011010011011010000100100110101111011001102020111001011011001100110100001010000101010000202 +ean13:690549661049:20200010110100111011100100111010001011010111102020101000011001101110010101110011101001001110202 +ean13:055572466568:20201100010110001011000101110110010011010001102020101000010100001001110101000010010001110100202 +ean13:636596356068:20201111010000101011100100101110101111011110102020100111010100001110010101000010010001000010202 +ean2:02:010110100111010010011 +ean2:19:010110110011010010111 +ean2:34:010110100001010100011 +upce:844677:202000100100111010011101010111101110110111011020202 +upce:610879:202000010101100110001101011011101110110010111020202 +upce:982526:202001011100010010011011011000100100110101111020202 +upce:846420:202000100100111010101111010001100110110001101020202 +upce:322140:202010000100110110010011001100100111010001101020202 +upce:625042:202000010100100110110001010011101000110011011020202 +upce:996072:202001011100101110101111000110101110110011011020202 +upce:539996:202011100101000010001011000101100010110000101020202 +upce:340168:202010000100111010001101001100100001010110111020202 +upce:841913:202000100101000110100111000101101100110011001020202 +upce:124122:202011001100110110100011001100100110110010011020202 +upce:401968:202001110100011010110011000101101011110001001020202 +upce:225085:202001101100100110111001010011101101110110001020202 +upce:368038:202010000101011110001001010011101111010110111020202 +upce:817155:202000100100110010111011011001101100010111001020202 +upce:554120:202011100101110010100011011001100100110001101020202 +upce:113080:202011001101100110111101000110101101110100111020202 +upce:755380:202001000101100010110001011110100010010100111020202 +upce:201858:202001101100011010110011000100101100010110111020202 +upce:226567:202001101100100110000101011100101011110111011020202 +upce:507089:202011100101001110111011000110101101110010111020202 +upce:442680:202001110101000110011011010111101101110100111020202 +upce:557738:202011100101100010111011001000101000010110111020202 +upce:928720:202001011100100110001001011101100100110100111020202 +upce:395240:202010000100101110110001001101101000110001101020202 +upce:931548:202001011101111010110011011000101000110001001020202 +upce:729228:202001000100100110001011001001100110110001001020202 +upce:116746:202011001100110010000101011101100111010101111020202 +upce:293469:202001101100101110111101010001101011110010111020202 +upce:555569:202011100101100010111001011000100001010001011020202 +upce:786474:202001000100010010000101010001101110110100011020202 +upce:761950:202001000101011110110011000101101100010100111020202 +upce:585584:202011100101101110111001011000100010010100011020202 +upce:929816:202001011100110110001011011011100110010000101020202 +upce:311259:202010000100110010011001001101101110010001011020202 +upce:694531:202000010100101110011101011000101111010011001020202 +upce:375808:202010000100100010110001011011101101110011101020202 +upce:240462:202001101100111010001101010001100001010010011020202 +upce:309270:202010000100011010010111001001100100010001101020202 +upce:531272:202011100101111010110011001001101110110011011020202 +upce:910577:202001011100110010001101011100100100010111011020202 +upce:816561:202000100100110010000101011000100001010011001020202 +upce:805838:202000100100011010110001011011101000010001001020202 +upce:533215:202011100101000010111101001101100110010110001020202 +upce:346122:202010000101000110000101001100100100110011011020202 +upce:625930:202000010100100110110001001011101000010001101020202 +upce:952717:202001011101110010010011001000100110010111011020202 +upce:402896:202001110101001110010011011011100010110000101020202 +upce:295983:202001101100101110110001000101101101110100001020202 +upce:024592:202010011100100110011101011000100010110011011020202 +upce:289724:202001101101101110010111011101100100110011101020202 +upce:252704:202001101101110010011011011101100011010100011020202 +upce:273290:202001101101110110111101001101100010110100111020202 +upce:385633:202010000100010010110001010111101111010100001020202 +upce:549951:202011100100111010001011001011101100010011001020202 +upce:568347:202011100101011110110111010000100111010111011020202 +upce:214740:202001101100110010011101001000101000110001101020202 +upce:969934:202001011101011110010111000101101111010011101020202 +upce:832367:202000100101111010010011010000100001010111011020202 +upce:359222:202010000101100010001011001101100110110010011020202 +upce:508230:202011100101001110001001001001101111010001101020202 +upce:308002:202010000101001110110111010011100011010010011020202 +upce:318751:202010000100110010001001011101101110010011001020202 +upce:174459:202011001100100010011101010001101100010001011020202 +upce:403448:202001110101001110111101010001101000110001001020202 +upce:429459:202001110100100110010111010001101110010001011020202 +upce:271338:202001101100100010110011011110101111010110111020202 +upce:515949:202011100100110010110001001011101000110010111020202 +upce:066186:202010011101011110000101001100100010010101111020202 +upce:609466:202000010100011010001011001110101011110000101020202 +upce:857406:202000100101110010010001010001101011110100011020202 +upce:237382:202001101101111010111011010000101101110011011020202 +upce:260304:202001101100001010001101010000100011010100011020202 +upce:899152:202000100100101110010111001100101100010010011020202 +upce:773424:202001000100100010111101001110100100110100011020202 +upce:367789:202010000101011110111011011101100010010010111020202 +upce:344078:202010000100111010011101000110101110110110111020202 +upce:627031:202000010100100110010001000110101000010011001020202 +upce:146732:202011001100111010101111001000101111010010011020202 +upce:608666:202000010100011010001001000010101011110101111020202 +upce:855228:202000100101110010111001001001100100110110111020202 +upce:439192:202001110101000010010111001100100010110010011020202 +upce:917451:202001011100110010010001010001101110010011001020202 +upce:072613:202010011101110110100111010111100110010011011020202 +upce:813590:202000100100110010100001011000100010110100111020202 +upce:176138:202011001100100010101111001100101000010110111020202 +upce:690945:202000010100101110001101001011101000110110001020202 +upce:849613:202000100100111010001011010111101100110111101020202 +upce:269053:202001101101011110001011000110101110010100001020202 +upce:701050:202001000100011010011001010011101110010001101020202 +upce:074527:202010011101110110011101011000100110110111011020202 +upce:218296:202001101100110010001001001101100010110101111020202 +upce:874938:202000100100100010100011000101101111010001001020202 +upce:023936:202010011100110110111101000101101111010000101020202 +upce:896764:202000100100101110000101011101101011110100011020202 +upce:979612:202001011100100010001011010111101100110010011020202 +upce:137449:202011001101000010010001010001101000110001011020202 +upce:687160:202000010100010010010001001100101011110001101020202 +upce:839620:202000100101111010010111000010100100110001101020202 +upce:921800:202001011100100110110011000100100011010001101020202 +ean5:72823:010110010001010011011010110111010010011010111101 +ean5:19075:010110110011010001011010001101010010001010110001 +ean5:16659:010110011001010000101010101111010111001010001011 +ean5:54239:010110111001010100011010011011010111101010001011 +ean5:70848:010110111011010001101010001001010011101010110111 +ean5:75795:010110010001010110001010111011010001011010111001 +ean5:15726:010110011001010110001010010001010011011010101111 +ean5:58560:010110110001010110111010110001010000101010100111 +ean5:24670:010110011011010100011010101111010111011010100111 +ean5:24946:010110011011010100011010001011010100011010000101 +ean5:69776:010110000101010001011010010001010111011010101111 +ean5:74692:010110010001010100011010101111010010111010010011 +ean5:10925:010110110011010001101010001011010010011010111001 +ean5:63372:010110000101010111101010111101010111011010011011 +ean5:62942:010110101111010010011010010111010011101010010011 +ean5:35265:010110111101010110001010011011010101111010111001 +ean5:38088:010110111101010001001010001101010001001010110111 +ean5:50203:010110111001010100111010010011010001101010111101 +ean5:57111:010110111001010111011010011001010011001010110011 +ean5:64593:010110101111010100011010111001010001011010100001 +ean5:52424:010110110001010010011010011101010011011010100011 +ean5:77259:010110010001010111011010010011010111001010001011 +ean5:07028:010110001101010111011010100111010011011010110111 +ean5:50627:010110111001010001101010101111010011011010111011 +ean5:60414:010110000101010001101010011101010011001010100011 +ean5:86940:010110001001010101111010010111010100011010001101 +ean5:36095:010110111101010101111010100111010001011010111001 +ean5:01124:010110100111010011001010011001010011011010100011 +ean5:57346:010110111001010111011010100001010100011010101111 +ean5:79607:010110010001010001011010000101010001101010111011 +ean5:31184:010110111101010011001010110011010001001010100011 +ean5:29583:010110011011010001011010110001010110111010100001 +ean5:75568:010110111011010110001010111001010101111010001001 +ean5:53258:010110110001010100001010010011010111001010110111 +ean5:78345:010110010001010110111010111101010100011010111001 +ean5:56838:010110110001010000101010001001010111101010110111 +ean5:61031:010110101111010110011010001101010100001010011001 +ean5:98054:010110001011010110111010001101010111001010011101 +ean5:28204:010110010011010110111010010011010100111010011101 +ean5:18738:010110011001010001001010111011010100001010110111 +ean5:17221:010110110011010111011010010011010010011010110011 +ean5:02270:010110001101010011011010010011010010001010001101 +ean5:02378:010110001101010011011010100001010111011010110111 +ean5:15957:010110110011010110001010010111010110001010111011 +ean5:13621:010110011001010111101010000101010010011010110011 +ean5:98891:010110001011010001001010110111010010111010011001 +ean5:50554:010110110001010100111010110001010111001010100011 +ean5:22677:010110010011010010011010101111010010001010010001 +ean5:49420:010110011101010001011010100011010010011010100111 +ean5:57712:010110110001010010001010010001010011001010010011 +ean5:13839:010110011001010100001010110111010111101010010111 +ean5:36422:010110111101010101111010011101010010011010011011 +ean5:10137:010110011001010100111010110011010111101010111011 +ean5:22734:010110010011010011011010010001010111101010100011 +ean5:25562:010110010011010110001010110001010000101010011011 +ean5:49015:010110100011010010111010001101010110011010110001 +ean5:34620:010110100001010100011010000101010010011010001101 +ean5:74909:010110010001010100011010010111010001101010001011 +ean5:57115:010110110001010111011010110011010110011010110001 +ean5:84963:010110001001010011101010001011010101111010111101 +ean5:95948:010110001011010110001010010111010100011010001001 +ean5:36006:010110100001010101111010100111010001101010101111 +ean5:05457:010110100111010110001010100011010110001010010001 +ean5:54806:010110111001010100011010110111010001101010000101 +ean5:32152:010110100001010010011010110011010110001010010011 +ean5:64913:010110101111010100011010010111010011001010100001 +ean5:53560:010110111001010111101010111001010101111010001101 +ean5:57373:010110110001010111011010100001010111011010100001 +ean5:54685:010110110001010100011010101111010001001010111001 +ean5:75408:010110010001010110001010100011010100111010110111 +ean5:56632:010110111001010000101010101111010111101010010011 +ean5:22639:010110010011010010011010101111010100001010010111 +ean5:92955:010110010111010010011010001011010111001010110001 +ean5:75465:010110111011010111001010100011010000101010110001 +ean5:56506:010110111001010101111010110001010100111010101111 +ean5:22627:010110011011010010011010000101010010011010111011 +ean5:98251:010110010111010110111010010011010110001010110011 +ean5:90220:010110010111010001101010011011010010011010001101 +ean5:93426:010110010111010111101010100011010011011010101111 +ean5:74169:010110010001010100011010110011010101111010001011 +ean5:36259:010110100001010101111010011011010110001010001011 +ean5:71855:010110111011010110011010001001010110001010110001 +ean5:04584:010110001101010100011010111001010001001010100011 +ean5:01152:010110100111010011001010011001010110001010011011 +ean5:72757:010110111011010010011010111011010111001010010001 +ean5:28673:010110010011010001001010101111010111011010100001 +ean5:75084:010110010001010111001010001101010110111010100011 +ean5:10562:010110011001010100111010110001010101111010011011 +ean5:63726:010110000101010111101010111011010011011010101111 +ean5:04292:010110001101010100011010011011010001011010011011 +ean5:77513:010110111011010010001010110001010110011010111101 +ean5:17826:010110011001010111011010110111010011011010000101 +ean5:44790:010110011101010011101010111011010001011010001101 +ean5:39572:010110111101010010111010111001010111011010010011 +ean5:55321:010110111001010111001010111101010010011010011001 +ean5:89717:010110110111010001011010111011010110011010010001 +ean5:02126:010110001101010011011010011001010011011010101111 +ean5:30106:010110100001010100111010011001010001101010101111 +ean5:57489:010110110001010111011010011101010110111010010111 +ean5:26505:010110011011010000101010110001010001101010110001 +upca:40710631975:20201000110001101011101100110010001101010111102020100001011001101110100100010010011101100110202 +upca:80176224795:20201101110001101001100101110110101111001001102020110110010111001000100111010010011101100110202 +upca:92748137722:20200010110010011011101101000110110111001100102020100001010001001000100110110011011001010000202 +upca:32450677259:20201111010010011010001101100010001101010111102020100010010001001101100100111011101001110010202 +upca:40851674702:20201000110001101011011101100010011001010111102020100010010111001000100111001011011001001000202 +upca:59115174167:20201100010001011001100100110010110001001100102020100010010111001100110101000010001001100110202 +upca:84003578078:20201101110100011000110100011010111101011000102020100010010010001110010100010010010001001000202 +upca:95062540829:20200010110110001000110101011110010011011000102020101110011100101001000110110011101001010000202 +upca:64901078016:20201011110100011000101100011010011001000110102020100010010010001110010110011010100001110010202 +upca:48432140125:20201000110110111010001101111010010011001100102020101110011100101100110110110010011101010000202 +upca:17430588576:20200110010111011010001101111010001101011000102020100100010010001001110100010010100001001000202 +upca:63153964133:20201011110111101001100101100010111101000101102020101000010111001100110100001010000101010000202 +upca:74093932950:20201110110100011000110100010110111101000101102020100001011011001110100100111011100101001110202 +upca:57541363089:20201100010111011011000101000110011001011110102020101000010000101110010100100011101001000100202 +upca:07377087198:20200011010111011011110101110110111011000110102020100100010001001100110111010010010001110100202 +upca:05635524594:20200011010110001010111101111010110001011000102020110110010111001001110111010010111001001000202 +upca:70318362910:20201110110001101011110100110010110111011110102020101000011011001110100110011011100101011100202 +upca:36925218506:20201111010101111000101100100110110001001001102020110011010010001001110111001010100001001110202 +upca:45343236277:20201000110110001011110101000110111101001001102020100001010100001101100100010010001001110010202 +upca:03926388241:20200011010111101000101100100110101111011110102020100100010010001101100101110011001101101100202 +upca:64192083538:20201011110100011001100100010110010011000110102020100100010000101001110100001010010001100110202 +upca:25525653142:20200100110110001011000100100110110001010111102020100111010000101100110101110011011001110010202 +upca:38104462945:20201111010110111001100100011010100011010001102020101000011011001110100101110010011101001000202 +upca:09225889378:20200011010001011001001100100110110001011011102020100100011101001000010100010010010001000100202 +upca:93748811785:20200010110111101011101101000110110111011011102020110011011001101000100100100010011101001110202 +upca:30467816622:20201111010001101010001101011110111011011011102020110011010100001010000110110011011001110100202 +upca:74931591622:20201110110100011000101101111010011001011000102020111010011001101010000110110011011001000010202 +upca:92475784788:20200010110010011010001101110110110001011101102020100100010111001000100100100010010001110100202 +upca:40454544331:20201000110001101010001101100010100011011000102020101110010111001000010100001011001101000010202 +upca:35237883084:20201111010110001001001101111010111011011011102020100100010000101110010100100010111001100110202 +upca:75646706855:20201110110110001010111101000110101111011101102020111001010100001001000100111010011101000100202 +upca:82889483314:20201101110010011011011101101110001011010001102020100100010000101000010110011010111001101100202 +upca:73893633416:20201110110111101011011100010110111101010111102020100001010000101011100110011010100001001110202 +upca:10454576813:20200110010001101010001101100010100011011000102020100010010100001001000110011010000101101100202 +upca:33334522835:20201111010111101011110101111010100011011000102020110110011011001001000100001010011101110100202 +upca:45793591164:20201000110110001011101100010110111101011000102020111010011001101100110101000010111001110010202 +upca:18057726450:20200110010110111000110101100010111011011101102020110110010100001011100100111011100101000100202 +upca:96083152912:20200010110101111000110101101110111101001100102020100111011011001110100110011011011001001000202 +upca:16563181689:20200110010101111011000101011110111101001100102020100100011001101010000100100011101001101100202 +upca:51276473461:20201100010011001001001101110110101111010001102020100010010000101011100101000011001101011100202 +upca:08128913293:20200011010110111001100100100110110111000101102020110011010000101101100111010010000101011100202 +upca:34146752391:20201111010100011001100101000110101111011101102020100111011011001000010111010011001101000100202 +upca:97515692692:20200010110111011011000100110010110001010111102020111010011011001010000111010011011001000100202 +upca:97669919853:20200010110111011010111101011110001011000101102020110011011101001001000100111010000101010000202 +upca:18678734797:20200110010110111010111101110110110111011101102020100001010111001000100111010010001001110100202 +upca:74076303825:20201110110100011000110101110110101111011110102020111001010000101001000110110010011101000010202 +upca:08662387020:20200011010110111010111101011110010011011110102020100100010001001110010110110011100101010000202 +upca:26133671442:20200100110101111001100101111010111101010111102020100010011001101011100101110011011001000010202 +upca:87138605931:20201101110111011001100101111010110111010111102020111001010011101110100100001011001101001110202 +upca:67189289819:20201011110111011001100101101110001011001001102020100100011101001001000110011011101001110010202 +upca:09759720707:20200011010001011011101101100010001011011101102020110110011100101000100111001010001001000010202 +upca:56485529906:20201100010101111010001101101110110001011000102020110110011101001110100111001010100001110100202 +upca:58154525395:20201100010110111001100101100010100011011000102020110110010011101000010111010010011101001000202 +upca:67888609275:20201011110111011011011101101110110111010111102020111001011101001101100100010010011101010000202 +upca:15168153237:20200110010110001001100101011110110111001100102020100111010000101101100100001010001001110010202 +upca:74424730673:20201110110100011010001100100110100011011101102020100001011100101010000100010010000101110100202 +upca:45168971187:20201000110110001001100101011110110111000101102020100010011001101100110100100010001001000100202 +upca:12149723784:20200110010010011001100101000110001011011101102020110110010000101000100100100010111001011100202 +upca:33804286457:20201111010111101011011100011010100011001001102020100100010100001011100100111010001001101100202 +upca:27558248562:20200100110111011011000101100010110111001001102020101110010010001001110101000011011001011100202 +upca:92390267160:20200010110010011011110100010110001101001001102020101000010001001100110101000011100101000100202 +upca:63742039163:20201011110111101011101101000110010011000110102020100001011101001100110101000010000101101100202 +upca:67117098326:20201011110111011001100100110010111011000110102020111010010010001000010110110010100001010000202 +upca:32901624258:20201111010010011000101100011010011001010111102020110110010111001101100100111010010001001000202 +upca:88848685777:20201101110110111011011101000110110111010111102020100100010011101000100100010010001001101100202 +upca:57070085601:20201100010111011000110101110110001101000110102020100100010011101010000111001011001101100110202 +upca:83043128438:20201101110111101000110101000110111101001100102020110110010010001011100100001010010001010000202 +upca:52432147628:20201100010010011010001101111010010011001100102020101110010001001010000110110010010001001000202 +upca:15067795584:20200110010110001000110101011110111011011101102020111010010011101001110100100010111001100110202 +upca:27777156430:20200100110111011011101101110110111011001100102020100111010100001011100100001011100101100110202 +upca:82471218344:20201101110010011010001101110110011001001001102020110011010010001000010101110010111001011100202 +upca:94175044091:20200010110100011001100101110110110001000110102020101110010111001110010111010011001101010000202 +upca:34936749963:20201111010100011000101101111010101111011101102020101110011101001110100101000010000101110100202 +upca:46502492658:20201000110101111011000100011010010011010001102020111010011011001010000100111010010001100110202 +upca:47153985860:20201000110111011001100101100010111101000101102020100100010011101001000101000011100101010000202 +upca:79601763982:20201110110001011010111100011010011001011101102020101000010000101110100100100011011001110010202 +upca:91685238225:20200010110011001010111101101110110001001001102020100001010010001101100110110010011101110100202 +upca:46916417994:20201000110101111000101100110010101111010001102020110011010001001110100111010010111001011100202 +upca:30878845484:20201111010001101011011101110110110111011011102020101110010011101011100100100010111001110100202 +upca:39321907655:20201111010001011011110100100110011001000101102020111001010001001010000100111010011101011100202 +upca:48232524842:20201000110110111001001101111010010011011000102020110110010111001001000101110011011001010000202 +upca:94750199914:20200010110100011011101101100010001101001100102020111010011101001110100110011010111001010000202 +upca:28310653784:20200100110110111011110100110010001101010111102020100111010000101000100100100010111001100110202 +upca:00814405096:20200011010001101011011100110010100011010001102020111001010011101110010111010010100001000100202 +upca:60974743279:20201011110001101000101101110110100011011101102020101110010000101101100100010011101001011100202 +upca:45141255670:20201000110110001001100101000110011001001001102020100111010011101010000100010011100101010000202 +upca:62241294735:20201011110010011001001101000110011001001001102020111010010111001000100100001010011101001110202 +upca:67241197048:20201011110111011001001101000110011001001100102020111010010001001110010101110010010001110100202 +upca:57709892169:20201100010111011011101100011010001011011011102020111010011011001100110101000011101001000100202 +upca:49234133045:20201000110001011001001101111010100011001100102020100001010000101110010101110010011101010000202 +upca:44106865868:20201000110100011001100100011010101111011011102020101000010011101001000101000010010001001000202 +upca:07033900539:20200011010111011000110101111010111101000101102020111001011100101001110100001011101001000100202 +upca:63922260360:20201011110111101000101100100110010011001001102020101000011100101000010101000011100101110100202 +upca:63544942112:20201011110111101011000101000110100011000101102020101110011011001100110110011011011001001110202 +upca:52602007800:20201100010010011010111100011010010011000110102020111001010001001001000111001011100101001000202 +upca:94048257810:20200010110100011000110101000110110111001001102020100111010001001001000110011011100101101100202 +upca:82699181094:20201101110010011010111100010110001011001100102020100100011001101110010111010010111001000010202 +upca:94628599972:20200010110100011010111100100110110111011000102020111010011101001110100100010011011001011100202 +upca:09938844603:20200011010001011000101101111010110111011011102020101110010111001010000111001010000101010000202 +upca:37128560103:20201111010111011001100100100110110111011000102020101000011100101100110111001010000101110010202 +code128:Something:11010010000110111010001000111101011110111010101100100001001111010010011000010100001101001100001010010011010000100011101101100011101011 +code128:OrOther:1101001000010001110110100100111101000111011010011110100100110000101011001000010010011110101001111001100011101011 +code128:Inkscape:110100100001100010001011000010100110000100101011110010010000101100100101100001010011110010110010000100111001101100011101011 +code128:Simple:11010010000110111010001000011010011110111010101001111001100101000010110010000111010111101100011101011 +code128:U~GE~7&R:110100100001101110111010001011110110100010001000110100010001011110111011011101001100100011000101110101100111001100011101011 +code25i:123456:10101101001010110011011010010100110100110010101101 +code39:123456:10010110110101101001010110101100101011011011001010101010011010110110100110101010110011010101001011011010 +code39ext:123456:10010110110101001001010010101010110011010010010100101101010110010100100101001010110101100101001001010010101011011001010010010100101100101010110100100101001010011010101101001011011010 +rm4scc:123456:25051525350515352515052535150535251515252505251535050535353 +rm4scc:a1b2c3e4:251525152505152535153505250515352505253515150525350535350515053525053505353 diff --git a/share/extensions/tests/data/cmd/fig2dev/5d879c5bf2edd4bc478d8bef487538b9.msg b/share/extensions/tests/data/cmd/fig2dev/5d879c5bf2edd4bc478d8bef487538b9.msg new file mode 100644 index 0000000..bebbc39 --- /dev/null +++ b/share/extensions/tests/data/cmd/fig2dev/5d879c5bf2edd4bc478d8bef487538b9.msg @@ -0,0 +1,29 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: fig2dev +Arguments: -L io/test.fig output.svg svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IS0tIENyZWF0b3I6IGZpZzJk +ZXYgVmVyc2lvbiAzLjIuNmEgLS0+CjwhLS0gQ3JlYXRpb25EYXRlOiAyMDE5LTA0LTI1IDEwOjUx +OjIyIC0tPgo8IS0tIE1hZ25pZmljYXRpb246IDEuMDUgLS0+CjxzdmcJeG1sbnM9Imh0dHA6Ly93 +d3cudzMub3JnLzIwMDAvc3ZnIgoJeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkv +eGxpbmsiCgl3aWR0aD0iMzA1cHQiIGhlaWdodD0iMjE3cHQiCgl2aWV3Qm94PSIxODc4IDE3NDMg +NDgzOSAzNDQ0Ij4KPGcgZmlsbD0ibm9uZSI+CjwhLS0gQ2lyY2xlIC0tPgo8Y2lyY2xlIGN4PSIy +NzAwIiBjeT0iMzI4NSIgcj0iNTg3IgoJc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9Ijhw +eCIvPgo8IS0tIExpbmUgLS0+CjxyZWN0IHg9IjE4OTAiIHk9IjI1NjUiIHdpZHRoPSIzMDYwIiBo +ZWlnaHQ9IjI2MTAiCglzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iOHB4Ii8+CjwhLS0g +TGluZSAtLT4KPHJlY3QgeD0iNTIyMCIgeT0iMjYxMCIgd2lkdGg9IjE0ODUiIGhlaWdodD0iMTcx +MCIgcng9IjEwNSIKCXN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI4cHgiLz4KPCEtLSBU +ZXh0IC0tPgo8dGV4dCB4bWw6c3BhY2U9InByZXNlcnZlIiB4PSIyNTIwIiB5PSIxODkwIiBmaWxs +PSIjMDAwMDAwIiBmb250LWZhbWlseT0iVGltZXMiIGZvbnQtc3R5bGU9Im5vcm1hbCIgZm9udC13 +ZWlnaHQ9Im5vcm1hbCIgZm9udC1zaXplPSIxNDQiIHRleHQtYW5jaG9yPSJzdGFydCI+SGVsbG8g +SW5rc2NhcGU8L3RleHQ+CjwvZz4KPC9zdmc+Cg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/gimp/a8418e80d6e849cc2e91b1baecbfada4.msg b/share/extensions/tests/data/cmd/gimp/a8418e80d6e849cc2e91b1baecbfada4.msg new file mode 100644 index 0000000..93fb936 --- /dev/null +++ b/share/extensions/tests/data/cmd/gimp/a8418e80d6e849cc2e91b1baecbfada4.msg @@ -0,0 +1,2204 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: gimp +Arguments: - --batch-interpreter=plug-in-script-fu-eval -b -i + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +V2VsY29tZSB0byBUaW55U2NoZW1lLCBWZXJzaW9uIDEuNDAKQ29weXJpZ2h0IChjKSBEaW1pdHJp +b3MgU291ZmxpcwoKdHM+IApHaXZlczogMAp0cz4gCkV2YWw6IChkZWZpbmUgKHBuZy10by1sYXll +ciBpbWcgcG5nX2ZpbGVuYW1lIGxheWVyX25hbWUpIChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5n +LWxvYWQgUlVOLU5PTklOVEVSQUNUSVZFIHBuZ19maWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBu +Z19sYXllciAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5 +ZXIgKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAo +Z2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0 +LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpKSkKRXZhbDogKGxhbWJkYSAoaW1nIHBuZ19maWxl +bmFtZSBsYXllcl9uYW1lKSAobGV0KiAoKHBuZyAoY2FyIChmaWxlLXBuZy1sb2FkIFJVTi1OT05J +TlRFUkFDVElWRSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKSkpIChwbmdfbGF5ZXIgKGNhciAo +Z2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIHBuZykpKSAoeGNmX2xheWVyIChjYXIgKGdpbXAt +bGF5ZXItbmV3LWZyb20tZHJhd2FibGUgcG5nX2xheWVyIGltZykpKSkgKGdpbXAtaW1hZ2UtYWRk +LWxheWVyIGltZyB4Y2ZfbGF5ZXIgLTEpIChnaW1wLWRyYXdhYmxlLXNldC1uYW1lIHhjZl9sYXll +ciBsYXllcl9uYW1lKSkpCkFwcGx5IHRvOiAoKChpbWcgcG5nX2ZpbGVuYW1lIGxheWVyX25hbWUp +IChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5nLWxvYWQgUlVOLU5PTklOVEVSQUNUSVZFIHBuZ19m +aWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBuZ19sYXllciAoY2FyIChnaW1wLWltYWdlLWdldC1h +Y3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5ZXIgKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1k +cmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAoZ2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9s +YXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpKSkp +CkV2YWw6IChpZiAobWFjcm8/IGZvcm0pIChtYWNyby1leHBhbmQtYWxsIChtYWNyby1leHBhbmQg +Zm9ybSkpIGZvcm0pCkV2YWw6IChtYWNybz8gZm9ybSkKRXZhbDogbWFjcm8/CkV2YWw6IGZvcm0K +QXBwbHkgdG86ICgoKGltZyBwbmdfZmlsZW5hbWUgbGF5ZXJfbmFtZSkgKGxldCogKChwbmcgKGNh +ciAoZmlsZS1wbmctbG9hZCBSVU4tTk9OSU5URVJBQ1RJVkUgcG5nX2ZpbGVuYW1lIHBuZ19maWxl +bmFtZSkpKSAocG5nX2xheWVyIChjYXIgKGdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciBwbmcp +KSkgKHhjZl9sYXllciAoY2FyIChnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIHBuZ19sYXll +ciBpbWcpKSkpIChnaW1wLWltYWdlLWFkZC1sYXllciBpbWcgeGNmX2xheWVyIC0xKSAoZ2ltcC1k +cmF3YWJsZS1zZXQtbmFtZSB4Y2ZfbGF5ZXIgbGF5ZXJfbmFtZSkpKSkKRXZhbDogZm9ybQpHaXZl +czogcG5nLXRvLWxheWVyCnRzPiAKRXZhbDogKGxldCogKChpbWcgKGNhciAoZ2ltcC1pbWFnZS1u +ZXcgMjAwIDIwMCBSR0IpKSkpIChnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uIGltZyA5Ni4wIDk2 +LjApIChnaW1wLWltYWdlLXVuZG8tZGlzYWJsZSBpbWcpIChmb3ItZWFjaCAobGFtYmRhIChuYW1l +cykgKHBuZy10by1sYXllciBpbWcgKGNhciBuYW1lcykgKGNkciBuYW1lcykpKSAobWFwIGNvbnMg +JygiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAiL3RtcC9naW1wLW91dC1xaW50 +Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgJygi +U2xpZGUzIiAiU2xpZGUyIiAiU2xpZGUxIikpKSAoZ2ltcC1pbWFnZS1yZXNpemUtdG8tbGF5ZXJz +IGltZykgKGdpbXAtaW1hZ2UtdW5kby1lbmFibGUgaW1nKSAoZ2ltcC1maWxlLXNhdmUgUlVOLU5P +TklOVEVSQUNUSVZFIGltZyAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgaW1nKSkg +Ii90bXAvZ2ltcC1vdXQtcWludGZnOHkvdGVzdC5zdmcueGNmIiAiL3RtcC9naW1wLW91dC1xaW50 +Zmc4eS90ZXN0LnN2Zy54Y2YiKSkKRXZhbDogKGNhciAoZ2ltcC1pbWFnZS1uZXcgMjAwIDIwMCBS +R0IpKQpFdmFsOiBjYXIKRXZhbDogKGdpbXAtaW1hZ2UtbmV3IDIwMCAyMDAgUkdCKQpFdmFsOiBn +aW1wLWltYWdlLW5ldwpFdmFsOiAyMDAKRXZhbDogMjAwCkV2YWw6IFJHQgpBcHBseSB0bzogKDIw +MCAyMDAgMCkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWltYWdl +LW5ldyIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChjb25z +ICJnaW1wLWltYWdlLW5ldyIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1uZXciCkV2 +YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1uZXciICgyMDAgMjAwIDApKQpBcHBseSB0bzog +KCM8Rk9SRUlHTiBQUk9DRURVUkUgOTQ4OTYzODc0NjA4NDg+ICgiZ2ltcC1pbWFnZS1uZXciIDIw +MCAyMDAgMCkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtbmV3IiAyMDAgMjAwIDApCkFwcGx5IHRv +OiAoKDEpKQpFdmFsOiAoZ2ltcC1pbWFnZS1zZXQtcmVzb2x1dGlvbiBpbWcgOTYuMCA5Ni4wKQpF +dmFsOiBnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uCkV2YWw6IGltZwpFdmFsOiA5Ni4wCkV2YWw6 +IDk2LjAKQXBwbHkgdG86ICgxIDk2LjAgOTYuMCkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1j +YWxsIChjb25zICJnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uIiB4KSkKRXZhbDogYXBwbHkKRXZh +bDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2Utc2V0LXJlc29sdXRp +b24iIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtaW1hZ2Utc2V0LXJlc29sdXRpb24iCkV2YWw6 +IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1zZXQtcmVzb2x1dGlvbiIgKDEgOTYuMCA5Ni4wKSkK +QXBwbHkgdG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDk0ODk2Mzg3NDYwODQ4PiAoImdpbXAtaW1h +Z2Utc2V0LXJlc29sdXRpb24iIDEgOTYuMCA5Ni4wKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1z +ZXQtcmVzb2x1dGlvbiIgMSA5Ni4wIDk2LjApCkV2YWw6IChnaW1wLWltYWdlLXVuZG8tZGlzYWJs +ZSBpbWcpCkV2YWw6IGdpbXAtaW1hZ2UtdW5kby1kaXNhYmxlCkV2YWw6IGltZwpBcHBseSB0bzog +KDEpCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS11bmRv +LWRpc2FibGUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFsOiAo +Y29ucyAiZ2ltcC1pbWFnZS11bmRvLWRpc2FibGUiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAt +aW1hZ2UtdW5kby1kaXNhYmxlIgpFdmFsOiB4CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtdW5kby1k +aXNhYmxlIiAoMSkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0 +OD4gKCJnaW1wLWltYWdlLXVuZG8tZGlzYWJsZSIgMSkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2Ut +dW5kby1kaXNhYmxlIiAxKQpFdmFsOiAoZm9yLWVhY2ggKGxhbWJkYSAobmFtZXMpIChwbmctdG8t +bGF5ZXIgaW1nIChjYXIgbmFtZXMpIChjZHIgbmFtZXMpKSkgKG1hcCBjb25zICcoIi90bXAvZ2lt +cC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUy +LnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICcoIlNsaWRlMyIgIlNs +aWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogZm9yLWVhY2gKRXZhbDogKGxhbWJkYSAobmFtZXMpIChw +bmctdG8tbGF5ZXIgaW1nIChjYXIgbmFtZXMpIChjZHIgbmFtZXMpKSkKQXBwbHkgdG86ICgoKG5h +bWVzKSAocG5nLXRvLWxheWVyIGltZyAoY2FyIG5hbWVzKSAoY2RyIG5hbWVzKSkpKQpFdmFsOiAo +aWYgKG1hY3JvPyBmb3JtKSAobWFjcm8tZXhwYW5kLWFsbCAobWFjcm8tZXhwYW5kIGZvcm0pKSBm +b3JtKQpFdmFsOiAobWFjcm8/IGZvcm0pCkV2YWw6IG1hY3JvPwpFdmFsOiBmb3JtCkFwcGx5IHRv +OiAoKChuYW1lcykgKHBuZy10by1sYXllciBpbWcgKGNhciBuYW1lcykgKGNkciBuYW1lcykpKSkK +RXZhbDogZm9ybQpFdmFsOiAobWFwIGNvbnMgJygiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTMucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgJygiU2xpZGUzIiAiU2xpZGUyIiAiU2xpZGUxIikpCkV2 +YWw6IG1hcApFdmFsOiBjb25zCkV2YWw6ICcoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUz +LnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUxLnBuZyIpCkV2YWw6ICcoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIp +CkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMy5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dp +bXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIp +KQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoYXBwbHkgcHJvYykgKGlmIChudWxsPyAoY2FyIGxp +c3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2Fy +cyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChh +cHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDog +bnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMy5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkK +RXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnpp +cDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChj +b25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkKRXZh +bDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBudWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFs +OiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMy5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkK +QXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgIi90bXAvZ2lt +cC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUx +LnBuZyIpKQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkg +KGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJz +KSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkKRXZhbDogKGFwcGx5IHVuemlwMS13aXRo +LWNkciBsaXN0cykKRXZhbDogYXBwbHkKRXZhbDogdW56aXAxLXdpdGgtY2RyCkV2YWw6IGxpc3Rz +CkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5w +bmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFp +bnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKQXBwbHkg +dG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIp +ICgiU2xpZGUzIiAiU2xpZGUyIiAiU2xpZGUxIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRl +cmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZh +bDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUzLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIg +Ii90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUzIiAiU2xpZGUyIiAi +U2xpZGUxIikpICgpICgpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNkcnMp +IChsZXQgKChjYXIxIChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13 +aXRoLWNkci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAo +YXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVs +bD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRl +My5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZh +bDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAx +LXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkp +IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2Fh +cgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUz +LnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUzIiAiU2xpZGUyIiAiU2xpZGUxIikpKQpFdmFs +OiAoY2FyIChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4 +CkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIikgKCJTbGlkZTMiICJTbGlkZTIiICJTbGlkZTEiKSkpCkFwcGx5IHRvOiAoKCIvdG1w +L2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSkKRXZhbDogKGNk +YXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5w +bmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRl +MiIgIlNsaWRlMSIpKSkKRXZhbDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4 +KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUzLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2lt +cC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUzIiAiU2xpZGUyIiAiU2xpZGUxIikp +KQpBcHBseSB0bzogKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChh +cHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkKRXZhbDog +dW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFsOiBjZHIKRXZh +bDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmci +ICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGFw +cGVuZCBjYXJzIChsaXN0IGNhcjEpKQpFdmFsOiBhcHBlbmQKRXZhbDogY2FycwpFdmFsOiAobGlz +dCBjYXIxKQpFdmFsOiBsaXN0CkV2YWw6IGNhcjEKQXBwbHkgdG86ICgiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTMucG5nIikKRXZhbDogeApBcHBseSB0bzogKCgpICgiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS9TbGlkZTMucG5nIikpCkV2YWw6IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkK +RXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxpc3QgY2RyMSkKRXZhbDogbGlzdApFdmFs +OiBjZHIxCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSkKRXZhbDogeApBcHBseSB0bzogKCgp +ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWlu +dGZnOHkvU2xpZGUxLnBuZyIpKSkKQXBwbHkgdG86ICgoKCJTbGlkZTMiICJTbGlkZTIiICJTbGlk +ZTEiKSkgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciKSAoKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5w +bmciKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2RycykgKGxldCAoKGNh +cjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0 +ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2Ry +cyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBs +aXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGxl +dCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgt +Y2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBl +bmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpFdmFs +OiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDog +KGNhciAoY2FyIHgpKQpFdmFsOiBjYXIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApB +cHBseSB0bzogKCgoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgoIlNs +aWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKQpFdmFsOiAoY2RhciBsaXN0cykKRXZhbDogY2RhcgpF +dmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZh +bDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDog +eApBcHBseSB0bzogKCgoIlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgo +IlNsaWRlMyIgIlNsaWRlMiIgIlNsaWRlMSIpKQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0ZXJh +dGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAo +bGlzdCBjZHIxKSkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogKGNkciBs +aXN0cykKRXZhbDogY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgiU2xpZGUzIiAiU2xpZGUy +IiAiU2xpZGUxIikpKQpFdmFsOiAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpCkV2YWw6IGFwcGVu +ZApFdmFsOiBjYXJzCkV2YWw6IChsaXN0IGNhcjEpCkV2YWw6IGxpc3QKRXZhbDogY2FyMQpBcHBs +eSB0bzogKCJTbGlkZTMiKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMy5wbmciKSAoIlNsaWRlMyIpKQpFdmFsOiAoYXBwZW5kIGNkcnMgKGxpc3QgY2Ry +MSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjZHJzCkV2YWw6IChsaXN0IGNkcjEpCkV2YWw6IGxpc3QK +RXZhbDogY2RyMQpBcHBseSB0bzogKCgiU2xpZGUyIiAiU2xpZGUxIikpCkV2YWw6IHgKQXBwbHkg +dG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMS5wbmciKSkgKCgiU2xpZGUyIiAiU2xpZGUxIikpKQpBcHBseSB0bzog +KCgpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAiU2xpZGUzIikgKCgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTEucG5nIikgKCJTbGlkZTIiICJTbGlkZTEiKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMp +IChjb25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBs +aXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNh +cnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/ +IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29u +cyBjYXJzIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICJTbGlkZTMiKSAoKCIvdG1wL2dp +bXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRl +MS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGNhciB1bnopCkV2YWw6IGNhcgpF +dmFsOiB1bnoKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmci +ICJTbGlkZTMiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2lt +cC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUyIiAiU2xpZGUxIikpKQpFdmFsOiAo +Y2RyIHVueikKRXZhbDogY2RyCkV2YWw6IHVuegpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUzLnBuZyIgIlNsaWRlMyIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgKCJTbGlkZTIi +ICJTbGlkZTEiKSkpCkV2YWw6IChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNv +bnMgcHJvYyBjZHJzKSkpCkV2YWw6IGNvbnMKRXZhbDogKGFwcGx5IHByb2MgY2FycykKRXZhbDog +YXBwbHkKRXZhbDogcHJvYwpFdmFsOiBjYXJzCkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3 +Nj4gKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICJTbGlkZTMiKSkKQXBwbHkg +dG86ICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAiU2xpZGUzIikKRXZhbDog +KGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKQpFdmFsOiBhcHBseQpFdmFsOiBtYXAKRXZhbDog +KGNvbnMgcHJvYyBjZHJzKQpFdmFsOiBjb25zCkV2YWw6IHByb2MKRXZhbDogY2RycwpBcHBseSB0 +bzogKCM8Y29ucyBQUk9DRURVUkUgNzY+ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUy +LnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUyIiAiU2xp +ZGUxIikpKQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCM8Y29ucyBQUk9DRURVUkUgNzY+ICgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTEucG5nIikgKCJTbGlkZTIiICJTbGlkZTEiKSkpCkFwcGx5IHRvOiAoIzxjb25zIFBST0NF +RFVSRSA3Nj4gKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIpKQpFdmFsOiAoaWYg +KG51bGw/IGxpc3RzKSAoYXBwbHkgcHJvYykgKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChs +ZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikp +IChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNv +bnMgcHJvYyBjZHJzKSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDog +bGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIpKSkK +RXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnpp +cDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChj +b25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkKRXZh +bDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBudWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFs +OiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIg +IlNsaWRlMSIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBu +ZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpKQpFdmFsOiAobGV0KiAoKHVu +eiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAo +Y2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2Mg +Y2RycykpKSkKRXZhbDogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykKRXZhbDogYXBwbHkK +RXZhbDogdW56aXAxLXdpdGgtY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgoIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUxLnBuZyIpICgiU2xpZGUyIiAiU2xpZGUxIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRl +cmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZh +bDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIp +ICgiU2xpZGUyIiAiU2xpZGUxIikpICgpICgpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoY29u +cyBjYXJzIGNkcnMpIChsZXQgKChjYXIxIChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMp +KSkgKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChs +aXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpKSkpCkV2YWw6IChudWxsPyBsaXN0 +cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFp +bnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAo +IlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2Ry +MSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAo +YXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFs +OiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUxLnBuZyIpICgiU2xpZGUyIiAiU2xpZGUxIikpKQpFdmFsOiAoY2FyIChjYXIgeCkpCkV2YWw6 +IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIikgKCJTbGlkZTIiICJTbGlkZTEiKSkpCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +KSkKRXZhbDogKGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGNkciAoY2FyIHgp +KQpFdmFsOiBjZHIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgo +Ii90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZn +OHkvU2xpZGUxLnBuZyIpICgiU2xpZGUyIiAiU2xpZGUxIikpKQpBcHBseSB0bzogKCgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChh +cHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkKRXZhbDog +dW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFsOiBjZHIKRXZh +bDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmci +ICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMiIgIlNsaWRlMSIp +KSkKRXZhbDogKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKQpFdmFsOiBhcHBlbmQKRXZhbDogY2Fy +cwpFdmFsOiAobGlzdCBjYXIxKQpFdmFsOiBsaXN0CkV2YWw6IGNhcjEKQXBwbHkgdG86ICgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIikKRXZhbDogeApBcHBseSB0bzogKCgpICgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIikpCkV2YWw6IChhcHBlbmQgY2RycyAo +bGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxpc3QgY2RyMSkKRXZh +bDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMS5wbmciKSkKRXZhbDogeApBcHBseSB0bzogKCgpICgoIi90bXAvZ2ltcC1vdXQtcWludGZn +OHkvU2xpZGUxLnBuZyIpKSkKQXBwbHkgdG86ICgoKCJTbGlkZTIiICJTbGlkZTEiKSkgKCIvdG1w +L2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciKSAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMS5wbmciKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2Rycykg +KGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdp +dGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChh +cHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxs +PwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGxl +dCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgt +Y2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBl +bmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpFdmFs +OiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGNhciAoY2Fy +IHgpKQpFdmFsOiBjYXIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzog +KCgoIlNsaWRlMiIgIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgoIlNsaWRlMiIgIlNsaWRlMSIpKQpF +dmFsOiAoY2RhciBsaXN0cykKRXZhbDogY2RhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNs +aWRlMiIgIlNsaWRlMSIpKSkKRXZhbDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNh +ciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoIlNsaWRlMiIgIlNsaWRlMSIpKSkK +QXBwbHkgdG86ICgoIlNsaWRlMiIgIlNsaWRlMSIpKQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0 +ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2Ry +cyAobGlzdCBjZHIxKSkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogKGNk +ciBsaXN0cykKRXZhbDogY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgiU2xpZGUyIiAiU2xp +ZGUxIikpKQpFdmFsOiAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpCkV2YWw6IGFwcGVuZApFdmFs +OiBjYXJzCkV2YWw6IChsaXN0IGNhcjEpCkV2YWw6IGxpc3QKRXZhbDogY2FyMQpBcHBseSB0bzog +KCJTbGlkZTIiKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMi5wbmciKSAoIlNsaWRlMiIpKQpFdmFsOiAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpCkV2 +YWw6IGFwcGVuZApFdmFsOiBjZHJzCkV2YWw6IChsaXN0IGNkcjEpCkV2YWw6IGxpc3QKRXZhbDog +Y2RyMQpBcHBseSB0bzogKCgiU2xpZGUxIikpCkV2YWw6IHgKQXBwbHkgdG86ICgoKCIvdG1wL2dp +bXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSkgKCgiU2xpZGUxIikpKQpBcHBseSB0bzogKCgp +ICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiU2xpZGUyIikgKCgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgKCJTbGlkZTEiKSkpCkV2YWw6IChpZiAobnVs +bD8gbGlzdHMpIChjb25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2Ry +MSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAo +YXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZh +bDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpF +dmFsOiAoY29ucyBjYXJzIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFw +cGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICJTbGlkZTIiKSAo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIpKSkKRXZhbDog +KGNhciB1bnopCkV2YWw6IGNhcgpFdmFsOiB1bnoKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMi5wbmciICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUxLnBuZyIpICgiU2xpZGUxIikpKQpFdmFsOiAoY2RyIHVueikKRXZhbDogY2RyCkV2YWw6 +IHVuegpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIlNs +aWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgKCJTbGlkZTEiKSkp +CkV2YWw6IChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJz +KSkpCkV2YWw6IGNvbnMKRXZhbDogKGFwcGx5IHByb2MgY2FycykKRXZhbDogYXBwbHkKRXZhbDog +cHJvYwpFdmFsOiBjYXJzCkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCIvdG1wL2dp +bXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciICJTbGlkZTIiKSkKQXBwbHkgdG86ICgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiU2xpZGUyIikKRXZhbDogKGFwcGx5IG1hcCAo +Y29ucyBwcm9jIGNkcnMpKQpFdmFsOiBhcHBseQpFdmFsOiBtYXAKRXZhbDogKGNvbnMgcHJvYyBj +ZHJzKQpFdmFsOiBjb25zCkV2YWw6IHByb2MKRXZhbDogY2RycwpBcHBseSB0bzogKCM8Y29ucyBQ +Uk9DRURVUkUgNzY+ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xp +ZGUxIikpKQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCM8Y29ucyBQUk9DRURVUkUgNzY+ICgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgKCJTbGlkZTEiKSkpCkFwcGx5IHRvOiAo +Izxjb25zIFBST0NFRFVSRSA3Nj4gKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +KSAoIlNsaWRlMSIpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoYXBwbHkgcHJvYykgKGlmIChu +dWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIg +bGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBw +cm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkpCkV2YWw6IChudWxsPyBs +aXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIpKSkKRXZhbDogKGlmIChudWxsPyAoY2Fy +IGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAo +Y2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMp +IChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkKRXZhbDogKG51bGw/IChjYXIgbGlzdHMp +KQpFdmFsOiBudWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFsOiBjYXIKRXZhbDogbGlzdHMKQXBw +bHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIp +KSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpKQpFdmFs +OiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1 +bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFw +IChjb25zIHByb2MgY2RycykpKSkKRXZhbDogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykK +RXZhbDogYXBwbHkKRXZhbDogdW56aXAxLXdpdGgtY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAo +IzxDTE9TVVJFPiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRl +MSIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgi +U2xpZGUxIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIGxpc3RzICcoKSAnKCkp +CkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogbGlzdHMKRXZhbDogJygpCkV2 +YWw6ICcoKQpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIp +ICgiU2xpZGUxIikpICgpICgpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNk +cnMpIChsZXQgKChjYXIxIChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlw +MS13aXRoLWNkci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEp +KSAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDog +bnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMS5wbmciKSAoIlNsaWRlMSIpKSkKRXZhbDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAo +Y2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3Rz +KSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpF +dmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIi90 +bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUxIikpKQpFdmFsOiAoY2Fy +IChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5 +IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikgKCJTbGlkZTEiKSkp +CkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSkKRXZhbDog +KGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dp +bXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIpKSkKRXZhbDogKGNkciAoY2Fy +IHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzog +KCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpICgiU2xpZGUxIikpKQpBcHBs +eSB0bzogKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikpCkV2YWw6ICh1bnpp +cDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIx +KSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0ZXJh +dGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFsOiBjZHIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIpKSkKRXZhbDog +KGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKQpFdmFsOiBhcHBlbmQKRXZhbDogY2FycwpFdmFsOiAo +bGlzdCBjYXIxKQpFdmFsOiBsaXN0CkV2YWw6IGNhcjEKQXBwbHkgdG86ICgiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS9TbGlkZTEucG5nIikKRXZhbDogeApBcHBseSB0bzogKCgpICgiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikpCkV2YWw6IChhcHBlbmQgY2RycyAobGlzdCBjZHIx +KSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxpc3QgY2RyMSkKRXZhbDogbGlzdApF +dmFsOiBjZHIxCkFwcGx5IHRvOiAoKCkpCkV2YWw6IHgKQXBwbHkgdG86ICgoKSAoKCkpKQpBcHBs +eSB0bzogKCgoIlNsaWRlMSIpKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIp +ICgoKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2RycykgKGxldCAoKGNh +cjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0 +ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2Ry +cyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBs +aXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMSIpKSkKRXZhbDogKGxldCAoKGNhcjEgKGNhYXIgbGlz +dHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2Ry +IGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIx +KSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzog +KCgoIlNsaWRlMSIpKSkKRXZhbDogKGNhciAoY2FyIHgpKQpFdmFsOiBjYXIKRXZhbDogKGNhciB4 +KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgo +IlNsaWRlMSIpKQpFdmFsOiAoY2RhciBsaXN0cykKRXZhbDogY2RhcgpFdmFsOiBsaXN0cwpBcHBs +eSB0bzogKCgoIlNsaWRlMSIpKSkKRXZhbDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDog +KGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoIlNsaWRlMSIpKSkKQXBwbHkg +dG86ICgoIlNsaWRlMSIpKQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxp +c3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkp +CkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogKGNkciBsaXN0cykKRXZhbDog +Y2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgiU2xpZGUxIikpKQpFdmFsOiAoYXBwZW5kIGNh +cnMgKGxpc3QgY2FyMSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjYXJzCkV2YWw6IChsaXN0IGNhcjEp +CkV2YWw6IGxpc3QKRXZhbDogY2FyMQpBcHBseSB0bzogKCJTbGlkZTEiKQpFdmFsOiB4CkFwcGx5 +IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciKSAoIlNsaWRlMSIpKQpF +dmFsOiAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjZHJzCkV2 +YWw6IChsaXN0IGNkcjEpCkV2YWw6IGxpc3QKRXZhbDogY2RyMQpBcHBseSB0bzogKCgpKQpFdmFs +OiB4CkFwcGx5IHRvOiAoKCgpKSAoKCkpKQpBcHBseSB0bzogKCgpICgiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTEucG5nIiAiU2xpZGUxIikgKCgpICgpKSkKRXZhbDogKGlmIChudWxsPyBs +aXN0cykgKGNvbnMgY2FycyBjZHJzKSAobGV0ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIxIChj +ZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBl +bmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFsOiAo +bnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCkpCkV2YWw6 +IChjb25zIGNhcnMgY2RycykKRXZhbDogY29ucwpFdmFsOiBjYXJzCkV2YWw6IGNkcnMKQXBwbHkg +dG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgIlNsaWRlMSIpICgoKSAo +KSkpCkV2YWw6IChjYXIgdW56KQpFdmFsOiBjYXIKRXZhbDogdW56CkFwcGx5IHRvOiAoKCgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAiU2xpZGUxIikgKCkgKCkpKQpFdmFsOiAo +Y2RyIHVueikKRXZhbDogY2RyCkV2YWw6IHVuegpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUxLnBuZyIgIlNsaWRlMSIpICgpICgpKSkKRXZhbDogKGNvbnMgKGFwcGx5 +IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkKRXZhbDogY29ucwpFdmFs +OiAoYXBwbHkgcHJvYyBjYXJzKQpFdmFsOiBhcHBseQpFdmFsOiBwcm9jCkV2YWw6IGNhcnMKQXBw +bHkgdG86ICgjPGNvbnMgUFJPQ0VEVVJFIDc2PiAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUxLnBuZyIgIlNsaWRlMSIpKQpBcHBseSB0bzogKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMS5wbmciICJTbGlkZTEiKQpFdmFsOiAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpCkV2 +YWw6IGFwcGx5CkV2YWw6IG1hcApFdmFsOiAoY29ucyBwcm9jIGNkcnMpCkV2YWw6IGNvbnMKRXZh +bDogcHJvYwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCgpICgp +KSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgjPGNvbnMgUFJPQ0VEVVJFIDc2PiAoKSAoKSkpCkFw +cGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCkgKCkpCkV2YWw6IChpZiAobnVsbD8gbGlz +dHMpIChhcHBseSBwcm9jKSAoaWYgKG51bGw/IChjYXIgbGlzdHMpKSAnKCkgKGxldCogKCh1bnog +KGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNk +ciB1bnopKSkgKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNk +cnMpKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBs +eSB0bzogKCgoKSAoKSkpCkV2YWw6IChpZiAobnVsbD8gKGNhciBsaXN0cykpICcoKSAobGV0KiAo +KHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2Ry +cyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHBy +b2MgY2RycykpKSkpCkV2YWw6IChudWxsPyAoY2FyIGxpc3RzKSkKRXZhbDogbnVsbD8KRXZhbDog +KGNhciBsaXN0cykKRXZhbDogY2FyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgpICgpKSkKQXBw +bHkgdG86ICgoKSkKRXZhbDogJygpCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpICgpKQpBcHBseSB0bzogKCgiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWlu +dGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTIucG5nIiAuICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBu +ZyIgLiAiU2xpZGUxIikpKQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCgiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5w +bmciIC4gIlNsaWRlMSIpKSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGFwcGx5IHByb2MpIChp +ZiAobnVsbD8gKGNhciBsaXN0cykpICN0IChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1j +ZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChhcHBseSBwcm9j +IGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkKRXZhbDogKG51bGw/IGxpc3Rz +KQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LXFp +bnRmZzh5L1NsaWRlMy5wbmciIC4gIlNsaWRlMyIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTIucG5nIiAuICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBu +ZyIgLiAiU2xpZGUxIikpKSkKRXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgI3QgKGxldCog +KCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNk +cnMgKGNkciB1bnopKSkgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNk +cnMpKSkpCkV2YWw6IChudWxsPyAoY2FyIGxpc3RzKSkKRXZhbDogbnVsbD8KRXZhbDogKGNhciBs +aXN0cykKRXZhbDogY2FyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEu +cG5nIiAuICJTbGlkZTEiKSkpKQpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5w +bmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJT +bGlkZTEiKSkpCkV2YWw6IChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMp +KSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChhcHBseSBwcm9jIGNhcnMpIChh +cHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpCkV2YWw6IChhcHBseSB1bnppcDEtd2l0aC1jZHIg +bGlzdHMpCkV2YWw6IGFwcGx5CkV2YWw6IHVuemlwMS13aXRoLWNkcgpFdmFsOiBsaXN0cwpBcHBs +eSB0bzogKCM8Q0xPU1VSRT4gKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIg +LiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRl +MiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpB +cHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUz +IikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6ICh1bnpp +cDEtd2l0aC1jZHItaXRlcmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNk +ci1pdGVyYXRpdmUKRXZhbDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgo +KCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciIC4gIlNsaWRlMyIpICgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQt +cWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSAoKSAoKSkKRXZhbDogKGlmIChudWxs +PyBsaXN0cykgKGNvbnMgY2FycyBjZHJzKSAobGV0ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIx +IChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChh +cHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFs +OiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgoIi90 +bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50 +Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpFdmFsOiAobGV0ICgoY2FyMSAoY2FhciBs +aXN0cykpIChjZHIxIChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChj +ZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNk +cjEpKSkpCkV2YWw6IChjYWFyIGxpc3RzKQpFdmFsOiBjYWFyCkV2YWw6IGxpc3RzCkFwcGx5IHRv +OiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpFdmFsOiAoY2FyIChjYXIg +eCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAo +KCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIvdG1w +L2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpBcHBseSB0bzogKCgoIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4 +eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6IChjZGFyIGxpc3RzKQpFdmFsOiBjZGFy +CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUz +LnBuZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4g +IlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEi +KSkpKQpFdmFsOiAoY2RyIChjYXIgeCkpCkV2YWw6IGNkcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNh +cgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBu +ZyIgLiAiU2xpZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNs +aWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkp +KQpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xp +ZGUzIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6ICh1 +bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBj +YXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0 +ZXJhdGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFsOiBjZHIKRXZhbDogbGlzdHMKQXBwbHkgdG86 +ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSAoIi90 +bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChhcHBlbmQgY2Fy +cyAobGlzdCBjYXIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNhcnMKRXZhbDogKGxpc3QgY2FyMSkK +RXZhbDogbGlzdApFdmFsOiBjYXIxCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMy5wbmciIC4gIlNsaWRlMyIpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCkgKCgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSkpCkV2YWw6IChhcHBlbmQg +Y2RycyAobGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxpc3QgY2Ry +MSkKRXZhbDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50 +Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUxLnBuZyIgLiAiU2xpZGUxIikpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCkgKCgoIi90bXAvZ2lt +cC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFp +bnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkFwcGx5IHRvOiAoKCkgKCgiL3RtcC9n +aW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSkgKCgoIi90bXAvZ2ltcC1v +dXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChj +b25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0 +cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMg +KGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxp +c3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29ucyBj +YXJzIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoKCgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSkgKCgoIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChjYXIgdW56KQpFdmFs +OiBjYXIKRXZhbDogdW56CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUzLnBuZyIgLiAiU2xpZGUzIikpICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBu +ZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNs +aWRlMSIpKSkpCkV2YWw6IChjZHIgdW56KQpFdmFsOiBjZHIKRXZhbDogdW56CkFwcGx5IHRvOiAo +KCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIgLiAiU2xpZGUzIikpICgoIi90 +bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChhcHBseSBwcm9j +IGNhcnMpCkV2YWw6IGFwcGx5CkV2YWw6IHByb2MKRXZhbDogY2FycwpBcHBseSB0bzogKCM8Q0xP +U1VSRT4gKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSkp +CkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciIC4gIlNsaWRl +MyIpKQpFdmFsOiAocG5nLXRvLWxheWVyIGltZyAoY2FyIG5hbWVzKSAoY2RyIG5hbWVzKSkKRXZh +bDogcG5nLXRvLWxheWVyCkV2YWw6IGltZwpFdmFsOiAoY2FyIG5hbWVzKQpFdmFsOiBjYXIKRXZh +bDogbmFtZXMKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIg +LiAiU2xpZGUzIikpCkV2YWw6IChjZHIgbmFtZXMpCkV2YWw6IGNkcgpFdmFsOiBuYW1lcwpBcHBs +eSB0bzogKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTMucG5nIiAuICJTbGlkZTMiKSkK +QXBwbHkgdG86ICgxICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICJTbGlkZTMi +KQpFdmFsOiAobGV0KiAoKHBuZyAoY2FyIChmaWxlLXBuZy1sb2FkIFJVTi1OT05JTlRFUkFDVElW +RSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKSkpIChwbmdfbGF5ZXIgKGNhciAoZ2ltcC1pbWFn +ZS1nZXQtYWN0aXZlLWxheWVyIHBuZykpKSAoeGNmX2xheWVyIChjYXIgKGdpbXAtbGF5ZXItbmV3 +LWZyb20tZHJhd2FibGUgcG5nX2xheWVyIGltZykpKSkgKGdpbXAtaW1hZ2UtYWRkLWxheWVyIGlt +ZyB4Y2ZfbGF5ZXIgLTEpIChnaW1wLWRyYXdhYmxlLXNldC1uYW1lIHhjZl9sYXllciBsYXllcl9u +YW1lKSkKRXZhbDogKGNhciAoZmlsZS1wbmctbG9hZCBSVU4tTk9OSU5URVJBQ1RJVkUgcG5nX2Zp +bGVuYW1lIHBuZ19maWxlbmFtZSkpCkV2YWw6IGNhcgpFdmFsOiAoZmlsZS1wbmctbG9hZCBSVU4t +Tk9OSU5URVJBQ1RJVkUgcG5nX2ZpbGVuYW1lIHBuZ19maWxlbmFtZSkKRXZhbDogZmlsZS1wbmct +bG9hZApFdmFsOiBSVU4tTk9OSU5URVJBQ1RJVkUKRXZhbDogcG5nX2ZpbGVuYW1lCkV2YWw6IHBu +Z19maWxlbmFtZQpBcHBseSB0bzogKDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBu +ZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIpCkV2YWw6IChhcHBseSBnaW1w +LXByb2MtZGItY2FsbCAoY29ucyAiZmlsZS1wbmctbG9hZCIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6 +IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJmaWxlLXBuZy1sb2FkIiB4KQpFdmFsOiBj +b25zCkV2YWw6ICJmaWxlLXBuZy1sb2FkIgpFdmFsOiB4CkFwcGx5IHRvOiAoImZpbGUtcG5nLWxv +YWQiICgxICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciICIvdG1wL2dpbXAtb3V0 +LXFpbnRmZzh5L1NsaWRlMy5wbmciKSkKQXBwbHkgdG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDk0 +ODk2Mzg3NDYwODQ4PiAoImZpbGUtcG5nLWxvYWQiIDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUzLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUzLnBuZyIpKQpBcHBseSB0 +bzogKCJmaWxlLXBuZy1sb2FkIiAxICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmci +ICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMy5wbmciKQpBcHBseSB0bzogKCgyKSkKRXZh +bDogKGNhciAoZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIHBuZykpCkV2YWw6IGNhcgpFdmFs +OiAoZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIHBuZykKRXZhbDogZ2ltcC1pbWFnZS1nZXQt +YWN0aXZlLWxheWVyCkV2YWw6IHBuZwpBcHBseSB0bzogKDIpCkV2YWw6IChhcHBseSBnaW1wLXBy +b2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiB4KSkKRXZhbDog +YXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtZ2V0 +LWFjdGl2ZS1sYXllciIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZl +LWxheWVyIgpFdmFsOiB4CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciIg +KDIpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTQ4OTYzODc0NjA4NDg+ICgiZ2lt +cC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiAyKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1nZXQt +YWN0aXZlLWxheWVyIiAyKQpBcHBseSB0bzogKCgzKSkKRXZhbDogKGNhciAoZ2ltcC1sYXllci1u +ZXctZnJvbS1kcmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkKRXZhbDogY2FyCkV2YWw6IChnaW1wLWxh +eWVyLW5ldy1mcm9tLWRyYXdhYmxlIHBuZ19sYXllciBpbWcpCkV2YWw6IGdpbXAtbGF5ZXItbmV3 +LWZyb20tZHJhd2FibGUKRXZhbDogcG5nX2xheWVyCkV2YWw6IGltZwpBcHBseSB0bzogKDMgMSkK +RXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWxheWVyLW5ldy1mcm9t +LWRyYXdhYmxlIiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDog +KGNvbnMgImdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUiIHgpCkV2YWw6IGNvbnMKRXZhbDog +ImdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1s +YXllci1uZXctZnJvbS1kcmF3YWJsZSIgKDMgMSkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NF +RFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAzIDEp +KQpBcHBseSB0bzogKCJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAzIDEpCkFwcGx5IHRv +OiAoKDQpKQpFdmFsOiAoZ2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXllciAtMSkKRXZh +bDogZ2ltcC1pbWFnZS1hZGQtbGF5ZXIKRXZhbDogaW1nCkV2YWw6IHhjZl9sYXllcgpFdmFsOiAt +MQpBcHBseSB0bzogKDEgNCAtMSkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25z +ICJnaW1wLWltYWdlLWFkZC1sYXllciIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1k +Yi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWltYWdlLWFkZC1sYXllciIgeCkKRXZhbDogY29ucwpF +dmFsOiAiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFn +ZS1hZGQtbGF5ZXIiICgxIDQgLTEpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTQ4 +OTYzODc0NjA4NDg+ICgiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiIDEgNCAtMSkpCkFwcGx5IHRvOiAo +ImdpbXAtaW1hZ2UtYWRkLWxheWVyIiAxIDQgLTEpCkV2YWw6IChnaW1wLWRyYXdhYmxlLXNldC1u +YW1lIHhjZl9sYXllciBsYXllcl9uYW1lKQpFdmFsOiBnaW1wLWRyYXdhYmxlLXNldC1uYW1lCkV2 +YWw6IHhjZl9sYXllcgpFdmFsOiBsYXllcl9uYW1lCkFwcGx5IHRvOiAoNCAiU2xpZGUzIikKRXZh +bDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWRyYXdhYmxlLXNldC1uYW1l +IiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdp +bXAtZHJhd2FibGUtc2V0LW5hbWUiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtZHJhd2FibGUt +c2V0LW5hbWUiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgKDQg +IlNsaWRlMyIpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTQ4OTYzODc0NjA4NDg+ +ICgiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgNCAiU2xpZGUzIikpCkFwcGx5IHRvOiAoImdpbXAt +ZHJhd2FibGUtc2V0LW5hbWUiIDQgIlNsaWRlMyIpCkV2YWw6IChhcHBseSBtYXAgKGNvbnMgcHJv +YyBjZHJzKSkKRXZhbDogYXBwbHkKRXZhbDogbWFwCkV2YWw6IChjb25zIHByb2MgY2RycykKRXZh +bDogY29ucwpFdmFsOiBwcm9jCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgoKCIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpBcHBseSB0bzogKCM8Q0xP +U1VSRT4gKCM8Q0xPU1VSRT4gKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAu +ICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUx +IikpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +IC4gIlNsaWRlMSIpKSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGFwcGx5IHByb2MpIChpZiAo +bnVsbD8gKGNhciBsaXN0cykpICcoKSAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2Ry +IGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkg +cHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkpKQpFdmFsOiAobnVsbD8g +bGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1v +dXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChpZiAobnVsbD8gKGNhciBsaXN0 +cykpICcoKSAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMg +KGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBw +bHkgbWFwIChjb25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyAoY2FyIGxpc3RzKSkKRXZh +bDogbnVsbD8KRXZhbDogKGNhciBsaXN0cykKRXZhbDogY2FyCkV2YWw6IGxpc3RzCkFwcGx5IHRv +OiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkFwcGx5IHRv +OiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAoIi90 +bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKQpFdmFsOiAobGV0 +KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAo +Y2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25z +IHByb2MgY2RycykpKSkKRXZhbDogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykKRXZhbDog +YXBwbHkKRXZhbDogdW56aXAxLXdpdGgtY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoIzxDTE9T +VVJFPiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAo +Ii90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSkKQXBwbHkg +dG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6ICh1 +bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRo +LWNkci1pdGVyYXRpdmUKRXZhbDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzog +KCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgiL3Rt +cC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpICgpICgpKQpFdmFs +OiAoaWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNkcnMpIChsZXQgKChjYXIxIChjYWFyIGxp +c3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgKGNk +ciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMgKGxpc3QgY2Ry +MSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkg +dG86ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSAo +Ii90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSkKRXZhbDog +KGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdp +dGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChh +cHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2FhcgpF +dmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5w +bmciIC4gIlNsaWRlMiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJT +bGlkZTEiKSkpKQpFdmFsOiAoY2FyIChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2 +YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUyLnBuZyIgLiAiU2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +IC4gIlNsaWRlMSIpKSkpCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTIucG5nIiAuICJTbGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIg +LiAiU2xpZGUxIikpKQpFdmFsOiAoY2RhciBsaXN0cykKRXZhbDogY2RhcgpFdmFsOiBsaXN0cwpB +cHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRl +MiIpICgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpF +dmFsOiAoY2RyIChjYXIgeCkpCkV2YWw6IGNkcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFs +OiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAi +U2xpZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIp +KSkpCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJT +bGlkZTIiKSAoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikp +KQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNh +cnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpCkV2YWw6IHVuemlwMS13 +aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogKGNkciBsaXN0cykKRXZhbDogY2RyCkV2YWw6IGxpc3Rz +CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIgLiAiU2xp +ZGUyIikgKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkp +CkV2YWw6IChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNhcnMK +RXZhbDogKGxpc3QgY2FyMSkKRXZhbDogbGlzdApFdmFsOiBjYXIxCkFwcGx5IHRvOiAoKCIvdG1w +L2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKQpFdmFsOiB4CkFwcGx5 +IHRvOiAoKCkgKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIi +KSkpCkV2YWw6IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNk +cnMKRXZhbDogKGxpc3QgY2RyMSkKRXZhbDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6IHgK +QXBwbHkgdG86ICgoKSAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJT +bGlkZTEiKSkpKQpBcHBseSB0bzogKCgpICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUy +LnBuZyIgLiAiU2xpZGUyIikpICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +IC4gIlNsaWRlMSIpKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2Rycykg +KGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdp +dGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChh +cHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxs +PwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29ucyBjYXJzIGNkcnMpCkV2YWw6 +IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkgKCgoIi90bXAvZ2ltcC1vdXQtcWludGZn +OHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSkKRXZhbDogKGNhciB1bnopCkV2YWw6IGNhcgpF +dmFsOiB1bnoKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5n +IiAuICJTbGlkZTIiKSkgKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJT +bGlkZTEiKSkpKQpFdmFsOiAoY2RyIHVueikKRXZhbDogY2RyCkV2YWw6IHVuegpBcHBseSB0bzog +KCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKSAoKCIv +dG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChj +b25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpCkV2YWw6 +IGNvbnMKRXZhbDogKGFwcGx5IHByb2MgY2FycykKRXZhbDogYXBwbHkKRXZhbDogcHJvYwpFdmFs +OiBjYXJzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMi5wbmciIC4gIlNsaWRlMiIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZn +OHkvU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikpCkV2YWw6IChwbmctdG8tbGF5ZXIgaW1nIChjYXIg +bmFtZXMpIChjZHIgbmFtZXMpKQpFdmFsOiBwbmctdG8tbGF5ZXIKRXZhbDogaW1nCkV2YWw6IChj +YXIgbmFtZXMpCkV2YWw6IGNhcgpFdmFsOiBuYW1lcwpBcHBseSB0bzogKCgiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkKRXZhbDogKGNkciBuYW1lcykKRXZh +bDogY2RyCkV2YWw6IG5hbWVzCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1Ns +aWRlMi5wbmciIC4gIlNsaWRlMiIpKQpBcHBseSB0bzogKDEgIi90bXAvZ2ltcC1vdXQtcWludGZn +OHkvU2xpZGUyLnBuZyIgIlNsaWRlMiIpCkV2YWw6IChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5n +LWxvYWQgUlVOLU5PTklOVEVSQUNUSVZFIHBuZ19maWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBu +Z19sYXllciAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5 +ZXIgKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAo +Z2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0 +LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpKQpFdmFsOiAoY2FyIChmaWxlLXBuZy1sb2FkIFJV +Ti1OT05JTlRFUkFDVElWRSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKSkKRXZhbDogY2FyCkV2 +YWw6IChmaWxlLXBuZy1sb2FkIFJVTi1OT05JTlRFUkFDVElWRSBwbmdfZmlsZW5hbWUgcG5nX2Zp +bGVuYW1lKQpFdmFsOiBmaWxlLXBuZy1sb2FkCkV2YWw6IFJVTi1OT05JTlRFUkFDVElWRQpFdmFs +OiBwbmdfZmlsZW5hbWUKRXZhbDogcG5nX2ZpbGVuYW1lCkFwcGx5IHRvOiAoMSAiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIu +cG5nIikKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJmaWxlLXBuZy1sb2Fk +IiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImZp +bGUtcG5nLWxvYWQiIHgpCkV2YWw6IGNvbnMKRXZhbDogImZpbGUtcG5nLWxvYWQiCkV2YWw6IHgK +QXBwbHkgdG86ICgiZmlsZS1wbmctbG9hZCIgKDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBuZyIpKQpBcHBseSB0bzog +KCM8Rk9SRUlHTiBQUk9DRURVUkUgOTQ4OTYzODc0NjA4NDg+ICgiZmlsZS1wbmctbG9hZCIgMSAi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTIucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4 +eS9TbGlkZTIucG5nIikpCkFwcGx5IHRvOiAoImZpbGUtcG5nLWxvYWQiIDEgIi90bXAvZ2ltcC1v +dXQtcWludGZnOHkvU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUyLnBu +ZyIpCkFwcGx5IHRvOiAoKDMpKQpFdmFsOiAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5 +ZXIgcG5nKSkKRXZhbDogY2FyCkV2YWw6IChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5n +KQpFdmFsOiBnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIKRXZhbDogcG5nCkFwcGx5IHRvOiAo +MykKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWltYWdlLWdldC1h +Y3RpdmUtbGF5ZXIiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFs +OiAoY29ucyAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiB4KQpFdmFsOiBjb25zCkV2YWw6 +ICJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1p +bWFnZS1nZXQtYWN0aXZlLWxheWVyIiAoMykpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVS +RSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiIDMpKQpBcHBs +eSB0bzogKCJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiIDMpCkFwcGx5IHRvOiAoKDYpKQpF +dmFsOiAoY2FyIChnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIHBuZ19sYXllciBpbWcpKQpF +dmFsOiBjYXIKRXZhbDogKGdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUgcG5nX2xheWVyIGlt +ZykKRXZhbDogZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZQpFdmFsOiBwbmdfbGF5ZXIKRXZh +bDogaW1nCkFwcGx5IHRvOiAoNiAxKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNv +bnMgImdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBn +aW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJs +ZSIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSIKRXZh +bDogeApBcHBseSB0bzogKCJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAoNiAxKSkKQXBw +bHkgdG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDk0ODk2Mzg3NDYwODQ4PiAoImdpbXAtbGF5ZXIt +bmV3LWZyb20tZHJhd2FibGUiIDYgMSkpCkFwcGx5IHRvOiAoImdpbXAtbGF5ZXItbmV3LWZyb20t +ZHJhd2FibGUiIDYgMSkKQXBwbHkgdG86ICgoNykpCkV2YWw6IChnaW1wLWltYWdlLWFkZC1sYXll +ciBpbWcgeGNmX2xheWVyIC0xKQpFdmFsOiBnaW1wLWltYWdlLWFkZC1sYXllcgpFdmFsOiBpbWcK +RXZhbDogeGNmX2xheWVyCkV2YWw6IC0xCkFwcGx5IHRvOiAoMSA3IC0xKQpFdmFsOiAoYXBwbHkg +Z2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdpbXAtaW1hZ2UtYWRkLWxheWVyIiB4KSkKRXZhbDog +YXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtYWRk +LWxheWVyIiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLWFkZC1sYXllciIKRXZhbDog +eApBcHBseSB0bzogKCJnaW1wLWltYWdlLWFkZC1sYXllciIgKDEgNyAtMSkpCkFwcGx5IHRvOiAo +IzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWltYWdlLWFkZC1sYXll +ciIgMSA3IC0xKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiIDEgNyAtMSkKRXZh +bDogKGdpbXAtZHJhd2FibGUtc2V0LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpCkV2YWw6IGdp +bXAtZHJhd2FibGUtc2V0LW5hbWUKRXZhbDogeGNmX2xheWVyCkV2YWw6IGxheWVyX25hbWUKQXBw +bHkgdG86ICg3ICJTbGlkZTIiKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMg +ImdpbXAtZHJhd2FibGUtc2V0LW5hbWUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2Mt +ZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgeCkKRXZhbDogY29u +cwpFdmFsOiAiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIKRXZhbDogeApBcHBseSB0bzogKCJnaW1w +LWRyYXdhYmxlLXNldC1uYW1lIiAoNyAiU2xpZGUyIikpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBS +T0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWRyYXdhYmxlLXNldC1uYW1lIiA3ICJTbGlk +ZTIiKSkKQXBwbHkgdG86ICgiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgNyAiU2xpZGUyIikKRXZh +bDogKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKQpFdmFsOiBhcHBseQpFdmFsOiBtYXAKRXZh +bDogKGNvbnMgcHJvYyBjZHJzKQpFdmFsOiBjb25zCkV2YWw6IHByb2MKRXZhbDogY2RycwpBcHBs +eSB0bzogKCM8Q0xPU1VSRT4gKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIg +LiAiU2xpZGUxIikpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgjPENMT1NVUkU+ICgoIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSkKQXBwbHkgdG86ICgj +PENMT1NVUkU+ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUx +IikpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoYXBwbHkgcHJvYykgKGlmIChudWxsPyAoY2Fy +IGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAo +Y2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMp +IChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZh +bDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4 +eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpKQpFdmFsOiAoaWYgKG51bGw/IChjYXIgbGlzdHMp +KSAnKCkgKGxldCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChj +YXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkgKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5 +IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpKQpFdmFsOiAobnVsbD8gKGNhciBsaXN0cykpCkV2YWw6 +IG51bGw/CkV2YWw6IChjYXIgbGlzdHMpCkV2YWw6IGNhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzog +KCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkFw +cGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEi +KSkpCkV2YWw6IChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2Fy +cyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChh +cHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKQpFdmFsOiAoYXBwbHkgdW56aXAxLXdpdGgtY2Ry +IGxpc3RzKQpFdmFsOiBhcHBseQpFdmFsOiB1bnppcDEtd2l0aC1jZHIKRXZhbDogbGlzdHMKQXBw +bHkgdG86ICgjPENMT1NVUkU+ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmci +IC4gIlNsaWRlMSIpKSkpCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIGxp +c3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogbGlzdHMK +RXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkgKCkgKCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMp +IChjb25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBs +aXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNh +cnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/ +IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChsZXQgKChjYXIx +IChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNkci1pdGVy +YXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMg +KGxpc3QgY2RyMSkpKSkKRXZhbDogKGNhYXIgbGlzdHMpCkV2YWw6IGNhYXIKRXZhbDogbGlzdHMK +QXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlk +ZTEiKSkpKQpFdmFsOiAoY2FyIChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6 +IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUx +LnBuZyIgLiAiU2xpZGUxIikpKSkKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5 +L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkKRXZhbDogKGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIK +RXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEu +cG5nIiAuICJTbGlkZTEiKSkpKQpFdmFsOiAoY2RyIChjYXIgeCkpCkV2YWw6IGNkcgpFdmFsOiAo +Y2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtcWlu +dGZnOHkvU2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpKSkKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAt +b3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkKRXZhbDogKHVuemlwMS13aXRo +LWNkci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBw +ZW5kIGNkcnMgKGxpc3QgY2RyMSkpKQpFdmFsOiB1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlCkV2 +YWw6IChjZHIgbGlzdHMpCkV2YWw6IGNkcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1w +L2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSkpCkV2YWw6IChhcHBl +bmQgY2FycyAobGlzdCBjYXIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNhcnMKRXZhbDogKGxpc3Qg +Y2FyMSkKRXZhbDogbGlzdApFdmFsOiBjYXIxCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFp +bnRmZzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCkgKCgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkpCkV2YWw6IChh +cHBlbmQgY2RycyAobGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxp +c3QgY2RyMSkKRXZhbDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCkpCkV2YWw6IHgKQXBw +bHkgdG86ICgoKSAoKCkpKQpBcHBseSB0bzogKCgpICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkv +U2xpZGUxLnBuZyIgLiAiU2xpZGUxIikpICgoKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChj +b25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0 +cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMg +KGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxp +c3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29ucyBj +YXJzIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoKCgi +L3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkgKCgpKSkKRXZh +bDogKGNhciB1bnopCkV2YWw6IGNhcgpFdmFsOiB1bnoKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIiAuICJTbGlkZTEiKSkgKCkpKQpFdmFsOiAoY2RyIHVu +eikKRXZhbDogY2RyCkV2YWw6IHVuegpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LXFpbnRm +Zzh5L1NsaWRlMS5wbmciIC4gIlNsaWRlMSIpKSAoKSkpCkV2YWw6IChjb25zIChhcHBseSBwcm9j +IGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpCkV2YWw6IGNvbnMKRXZhbDogKGFw +cGx5IHByb2MgY2FycykKRXZhbDogYXBwbHkKRXZhbDogcHJvYwpFdmFsOiBjYXJzCkFwcGx5IHRv +OiAoIzxDTE9TVVJFPiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNs +aWRlMSIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIg +LiAiU2xpZGUxIikpCkV2YWw6IChwbmctdG8tbGF5ZXIgaW1nIChjYXIgbmFtZXMpIChjZHIgbmFt +ZXMpKQpFdmFsOiBwbmctdG8tbGF5ZXIKRXZhbDogaW1nCkV2YWw6IChjYXIgbmFtZXMpCkV2YWw6 +IGNhcgpFdmFsOiBuYW1lcwpBcHBseSB0bzogKCgiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlk +ZTEucG5nIiAuICJTbGlkZTEiKSkKRXZhbDogKGNkciBuYW1lcykKRXZhbDogY2RyCkV2YWw6IG5h +bWVzCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L1NsaWRlMS5wbmciIC4gIlNs +aWRlMSIpKQpBcHBseSB0bzogKDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIg +IlNsaWRlMSIpCkV2YWw6IChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5nLWxvYWQgUlVOLU5PTklO +VEVSQUNUSVZFIHBuZ19maWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBuZ19sYXllciAoY2FyIChn +aW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5ZXIgKGNhciAoZ2ltcC1s +YXllci1uZXctZnJvbS1kcmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAoZ2ltcC1pbWFnZS1hZGQt +bGF5ZXIgaW1nIHhjZl9sYXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0LW5hbWUgeGNmX2xheWVy +IGxheWVyX25hbWUpKQpFdmFsOiAoY2FyIChmaWxlLXBuZy1sb2FkIFJVTi1OT05JTlRFUkFDVElW +RSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKSkKRXZhbDogY2FyCkV2YWw6IChmaWxlLXBuZy1s +b2FkIFJVTi1OT05JTlRFUkFDVElWRSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKQpFdmFsOiBm +aWxlLXBuZy1sb2FkCkV2YWw6IFJVTi1OT05JTlRFUkFDVElWRQpFdmFsOiBwbmdfZmlsZW5hbWUK +RXZhbDogcG5nX2ZpbGVuYW1lCkFwcGx5IHRvOiAoMSAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9T +bGlkZTEucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikKRXZhbDogKGFw +cGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJmaWxlLXBuZy1sb2FkIiB4KSkKRXZhbDogYXBw +bHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImZpbGUtcG5nLWxvYWQiIHgp +CkV2YWw6IGNvbnMKRXZhbDogImZpbGUtcG5nLWxvYWQiCkV2YWw6IHgKQXBwbHkgdG86ICgiZmls +ZS1wbmctbG9hZCIgKDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIgIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9D +RURVUkUgOTQ4OTYzODc0NjA4NDg+ICgiZmlsZS1wbmctbG9hZCIgMSAiL3RtcC9naW1wLW91dC1x +aW50Zmc4eS9TbGlkZTEucG5nIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS9TbGlkZTEucG5nIikp +CkFwcGx5IHRvOiAoImZpbGUtcG5nLWxvYWQiIDEgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xp +ZGUxLnBuZyIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvU2xpZGUxLnBuZyIpCkFwcGx5IHRvOiAo +KDQpKQpFdmFsOiAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKSkKRXZhbDog +Y2FyCkV2YWw6IChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKQpFdmFsOiBnaW1wLWlt +YWdlLWdldC1hY3RpdmUtbGF5ZXIKRXZhbDogcG5nCkFwcGx5IHRvOiAoNCkKRXZhbDogKGFwcGx5 +IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiIHgp +KQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1p +bWFnZS1nZXQtYWN0aXZlLWxheWVyIiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLWdl +dC1hY3RpdmUtbGF5ZXIiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1nZXQtYWN0aXZl +LWxheWVyIiAoNCkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0 +OD4gKCJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiIDQpKQpBcHBseSB0bzogKCJnaW1wLWlt +YWdlLWdldC1hY3RpdmUtbGF5ZXIiIDQpCkFwcGx5IHRvOiAoKDkpKQpFdmFsOiAoY2FyIChnaW1w +LWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIHBuZ19sYXllciBpbWcpKQpFdmFsOiBjYXIKRXZhbDog +KGdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUgcG5nX2xheWVyIGltZykKRXZhbDogZ2ltcC1s +YXllci1uZXctZnJvbS1kcmF3YWJsZQpFdmFsOiBwbmdfbGF5ZXIKRXZhbDogaW1nCkFwcGx5IHRv +OiAoOSAxKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdpbXAtbGF5ZXIt +bmV3LWZyb20tZHJhd2FibGUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2Fs +bApFdmFsOiAoY29ucyAiZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSIgeCkKRXZhbDogY29u +cwpFdmFsOiAiZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSIKRXZhbDogeApBcHBseSB0bzog +KCJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAoOSAxKSkKQXBwbHkgdG86ICgjPEZPUkVJ +R04gUFJPQ0VEVVJFIDk0ODk2Mzg3NDYwODQ4PiAoImdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2Fi +bGUiIDkgMSkpCkFwcGx5IHRvOiAoImdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUiIDkgMSkK +QXBwbHkgdG86ICgoMTApKQpFdmFsOiAoZ2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXll +ciAtMSkKRXZhbDogZ2ltcC1pbWFnZS1hZGQtbGF5ZXIKRXZhbDogaW1nCkV2YWw6IHhjZl9sYXll +cgpFdmFsOiAtMQpBcHBseSB0bzogKDEgMTAgLTEpCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGIt +Y2FsbCAoY29ucyAiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBn +aW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiIHgpCkV2 +YWw6IGNvbnMKRXZhbDogImdpbXAtaW1hZ2UtYWRkLWxheWVyIgpFdmFsOiB4CkFwcGx5IHRvOiAo +ImdpbXAtaW1hZ2UtYWRkLWxheWVyIiAoMSAxMCAtMSkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBS +T0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWltYWdlLWFkZC1sYXllciIgMSAxMCAtMSkp +CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtYWRkLWxheWVyIiAxIDEwIC0xKQpFdmFsOiAoZ2ltcC1k +cmF3YWJsZS1zZXQtbmFtZSB4Y2ZfbGF5ZXIgbGF5ZXJfbmFtZSkKRXZhbDogZ2ltcC1kcmF3YWJs +ZS1zZXQtbmFtZQpFdmFsOiB4Y2ZfbGF5ZXIKRXZhbDogbGF5ZXJfbmFtZQpBcHBseSB0bzogKDEw +ICJTbGlkZTEiKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdpbXAtZHJh +d2FibGUtc2V0LW5hbWUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApF +dmFsOiAoY29ucyAiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgeCkKRXZhbDogY29ucwpFdmFsOiAi +Z2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIKRXZhbDogeApBcHBseSB0bzogKCJnaW1wLWRyYXdhYmxl +LXNldC1uYW1lIiAoMTAgIlNsaWRlMSIpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUg +OTQ4OTYzODc0NjA4NDg+ICgiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgMTAgIlNsaWRlMSIpKQpB +cHBseSB0bzogKCJnaW1wLWRyYXdhYmxlLXNldC1uYW1lIiAxMCAiU2xpZGUxIikKRXZhbDogKGFw +cGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKQpFdmFsOiBhcHBseQpFdmFsOiBtYXAKRXZhbDogKGNv +bnMgcHJvYyBjZHJzKQpFdmFsOiBjb25zCkV2YWw6IHByb2MKRXZhbDogY2RycwpBcHBseSB0bzog +KCM8Q0xPU1VSRT4gKCgpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgjPENMT1NVUkU+ICgpKSkK +QXBwbHkgdG86ICgjPENMT1NVUkU+ICgpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoYXBwbHkg +cHJvYykgKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChhcHBseSB1bnpp +cDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIgdW56KSkpIChj +b25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkpCkV2 +YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCkp +KQpFdmFsOiAoaWYgKG51bGw/IChjYXIgbGlzdHMpKSAnKCkgKGxldCogKCh1bnogKGFwcGx5IHVu +emlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkg +KGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpKQpF +dmFsOiAobnVsbD8gKGNhciBsaXN0cykpCkV2YWw6IG51bGw/CkV2YWw6IChjYXIgbGlzdHMpCkV2 +YWw6IGNhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKSkpCkFwcGx5IHRvOiAoKCkpCkV2YWw6 +ICcoKQpBcHBseSB0bzogKCgjdCkgKCkpCkFwcGx5IHRvOiAoKCN0KSAoKCN0KSkpCkV2YWw6IChn +aW1wLWltYWdlLXJlc2l6ZS10by1sYXllcnMgaW1nKQpFdmFsOiBnaW1wLWltYWdlLXJlc2l6ZS10 +by1sYXllcnMKRXZhbDogaW1nCkFwcGx5IHRvOiAoMSkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1k +Yi1jYWxsIChjb25zICJnaW1wLWltYWdlLXJlc2l6ZS10by1sYXllcnMiIHgpKQpFdmFsOiBhcHBs +eQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1pbWFnZS1yZXNpemUt +dG8tbGF5ZXJzIiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLXJlc2l6ZS10by1sYXll +cnMiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1yZXNpemUtdG8tbGF5ZXJzIiAoMSkp +CkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWlt +YWdlLXJlc2l6ZS10by1sYXllcnMiIDEpKQpBcHBseSB0bzogKCJnaW1wLWltYWdlLXJlc2l6ZS10 +by1sYXllcnMiIDEpCkV2YWw6IChnaW1wLWltYWdlLXVuZG8tZW5hYmxlIGltZykKRXZhbDogZ2lt +cC1pbWFnZS11bmRvLWVuYWJsZQpFdmFsOiBpbWcKQXBwbHkgdG86ICgxKQpFdmFsOiAoYXBwbHkg +Z2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdpbXAtaW1hZ2UtdW5kby1lbmFibGUiIHgpKQpFdmFs +OiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1pbWFnZS11 +bmRvLWVuYWJsZSIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS11bmRvLWVuYWJsZSIK +RXZhbDogeApBcHBseSB0bzogKCJnaW1wLWltYWdlLXVuZG8tZW5hYmxlIiAoMSkpCkFwcGx5IHRv +OiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWltYWdlLXVuZG8t +ZW5hYmxlIiAxKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS11bmRvLWVuYWJsZSIgMSkKRXZhbDog +KGdpbXAtZmlsZS1zYXZlIFJVTi1OT05JTlRFUkFDVElWRSBpbWcgKGNhciAoZ2ltcC1pbWFnZS1n +ZXQtYWN0aXZlLWxheWVyIGltZykpICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L3Rlc3Quc3ZnLnhj +ZiIgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvdGVzdC5zdmcueGNmIikKRXZhbDogZ2ltcC1maWxl +LXNhdmUKRXZhbDogUlVOLU5PTklOVEVSQUNUSVZFCkV2YWw6IGltZwpFdmFsOiAoY2FyIChnaW1w +LWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgaW1nKSkKRXZhbDogY2FyCkV2YWw6IChnaW1wLWltYWdl +LWdldC1hY3RpdmUtbGF5ZXIgaW1nKQpFdmFsOiBnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIK +RXZhbDogaW1nCkFwcGx5IHRvOiAoMSkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChj +b25zICJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBn +aW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVy +IiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiCkV2YWw6 +IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiAoMSkpCkFwcGx5IHRv +OiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5NDg5NjM4NzQ2MDg0OD4gKCJnaW1wLWltYWdlLWdldC1h +Y3RpdmUtbGF5ZXIiIDEpKQpBcHBseSB0bzogKCJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIi +IDEpCkFwcGx5IHRvOiAoKDEwKSkKRXZhbDogIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvdGVzdC5z +dmcueGNmIgpFdmFsOiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS90ZXN0LnN2Zy54Y2YiCkFwcGx5 +IHRvOiAoMSAxIDEwICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L3Rlc3Quc3ZnLnhjZiIgIi90bXAv +Z2ltcC1vdXQtcWludGZnOHkvdGVzdC5zdmcueGNmIikKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1k +Yi1jYWxsIChjb25zICJnaW1wLWZpbGUtc2F2ZSIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAt +cHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWZpbGUtc2F2ZSIgeCkKRXZhbDogY29ucwpF +dmFsOiAiZ2ltcC1maWxlLXNhdmUiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1maWxlLXNhdmUi +ICgxIDEgMTAgIi90bXAvZ2ltcC1vdXQtcWludGZnOHkvdGVzdC5zdmcueGNmIiAiL3RtcC9naW1w +LW91dC1xaW50Zmc4eS90ZXN0LnN2Zy54Y2YiKSkKQXBwbHkgdG86ICgjPEZPUkVJR04gUFJPQ0VE +VVJFIDk0ODk2Mzg3NDYwODQ4PiAoImdpbXAtZmlsZS1zYXZlIiAxIDEgMTAgIi90bXAvZ2ltcC1v +dXQtcWludGZnOHkvdGVzdC5zdmcueGNmIiAiL3RtcC9naW1wLW91dC1xaW50Zmc4eS90ZXN0LnN2 +Zy54Y2YiKSkKQXBwbHkgdG86ICgiZ2ltcC1maWxlLXNhdmUiIDEgMSAxMCAiL3RtcC9naW1wLW91 +dC1xaW50Zmc4eS90ZXN0LnN2Zy54Y2YiICIvdG1wL2dpbXAtb3V0LXFpbnRmZzh5L3Rlc3Quc3Zn +LnhjZiIpCkdpdmVzOiAoI3QpCnRzPiAKRXZhbDogKGdpbXAtcXVpdCAwKQpFdmFsOiBnaW1wLXF1 +aXQKRXZhbDogMApBcHBseSB0bzogKDApCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAo +Y29ucyAiZ2ltcC1xdWl0IiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwK +RXZhbDogKGNvbnMgImdpbXAtcXVpdCIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1xdWl0IgpF +dmFsOiB4CkFwcGx5IHRvOiAoImdpbXAtcXVpdCIgKDApKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQ +Uk9DRURVUkUgOTQ4OTYzODc0NjA4NDg+ICgiZ2ltcC1xdWl0IiAwKSkKQXBwbHkgdG86ICgiZ2lt +cC1xdWl0IiAwKQ== + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="test.svg.xcf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: test.svg.xcf + +Z2ltcCB4Y2YgZmlsZQAAAAPoAAAD6AAAAAAAAAARAAAAAQEAAAATAAAACELAAABCwAAAAAAAFAAA +AAQAAAAEAAAAFgAAAAQAAAABAAAAFQAAARwAAAAQZ2ltcC1pbWFnZS1ncmlkAAAAAAEAAAEAKHN0 +eWxlIHNvbGlkKQooZmdjb2xvciAoY29sb3ItcmdiYSAwLjAwMDAwMCAwLjAwMDAwMCAwLjAwMDAw +MCAxLjAwMDAwMCkpCihiZ2NvbG9yIChjb2xvci1yZ2JhIDEuMDAwMDAwIDEuMDAwMDAwIDEuMDAw +MDAwIDEuMDAwMDAwKSkKKHhzcGFjaW5nIDEwLjAwMDAwMCkKKHlzcGFjaW5nIDEwLjAwMDAwMCkK +KHNwYWNpbmctdW5pdCBpbmNoZXMpCih4b2Zmc2V0IDAuMDAwMDAwKQooeW9mZnNldCAwLjAwMDAw +MCkKKG9mZnNldC11bml0IGluY2hlcykKAAAAAAAAAAAAAAABiwAATJ4AAO1iAAAAAAAAAAAAAAPo +AAAD6AAAAAEAAAAHU2xpZGUxAAAAAAIAAAAAAAAABgAAAAQAAAD/AAAACAAAAAQAAAABAAAACQAA +AAQAAAAAAAAAHAAAAAQAAAAAAAAACgAAAAQAAAAAAAAACwAAAAQAAAAAAAAADAAAAAQAAAAAAAAA +DQAAAAQAAAAAAAAADwAAAAgAAAAAAAAAAAAAAAcAAAAEAAAAAAAAABQAAAAEAAAABAAAAAAAAAAA +AAACQgAAAAAAAAPoAAAD6AAAAAQAAAJmAABMbgAATHoAAEyGAABMkgAAAAAAAAPoAAAD6AAABnIA +AAaCAAAGkgAABqIAAAayAAAGwgAABtIAAAbiAAAG8gAABwIAAAcSAAAHIgAABzIAAAdCAAAHUgAA +B2IAAAdyAAAHggAACNUAAAtAAAANVAAAD18AABICAAAVzwAAF3sAABo8AAAaTAAAGlwAABpsAAAa +fAAAGowAABqcAAAarAAAGrwAABrMAAAa3AAAGuwAAButAAAcNAAAHf8AAB40AAAecQAAHoEAAB6R +AAAeoQAAHrEAAB7BAAAe0QAAHuEAAB7xAAAgvQAAINUAACKlAAAksQAAJMkAACThAAAm6QAAJvkA +ACv8AAAsKQAALJEAADFSAAAxYgAAMXIAADGCAAAxkgAAMwIAADMaAAA0hgAANjYAADZWAAA2dgAA +OCYAADg2AAA8jQAAPMgAAD0nAABBPgAAQU4AAEFeAABBbgAAQX4AAEGOAABBngAAQa4AAEG+AABB +zgAAQd4AAEHuAABB/gAAQg4AAEIeAABCLgAAQj4AAEJOAABCXgAAQm4AAEJ+AABCjgAAQp4AAEKu +AABCvgAAQs4AAELeAABC7gAAQv4AAEMOAABDHgAAQy4AAEM+AABDTgAAQ14AAENuAABDfgAAQ44A +AEOeAABDrgAAQ74AAEPOAABD3gAAQ+4AAEP+AABEDgAARB4AAEQuAABEPgAARE4AAEReAABEbgAA +RH4AAESOAABEngAARK4AAES+AABEzgAARN4AAETuAABE/gAARQ4AAEUeAABFLgAART4AAEVOAABF +XgAARW4AAEV+AABFjgAARZ4AAEWuAABFvgAARc4AAEXeAABF7gAARf4AAEYOAABGHgAARi4AAEY+ +AABGTgAARl4AAEZuAABGfgAARo4AAEaeAABGrgAARr4AAEbOAABG3gAARu4AAEb+AABHDgAARx4A +AEcuAABHPgAAR04AAEdeAABHbgAAR34AAEeOAABHngAAR64AAEe+AABHzgAAR94AAEfuAABH/gAA +SA4AAEgeAABILgAASD4AAEhOAABIXgAASG4AAEh+AABIjgAASJ4AAEiuAABIvgAASM4AAEjeAABI +7gAASP4AAEkOAABJHgAASS4AAEk+AABJTgAASV4AAEluAABJfgAASY4AAEmeAABJrgAASb4AAEnO +AABJ3gAASe4AAEn+AABKDgAASh4AAEouAABKPgAASk4AAEpeAABKbgAASn4AAEqOAABKngAASq4A +AEq+AABKzgAASt4AAEruAABK/gAASw4AAEseAABLLgAASz4AAEtOAABLXgAAS24AAEt+AABLjgAA +S54AAEuuAABLvgAAS84AAEveAABL7gAAS/4AAEwOAABMHgAATC4AAEw+AABMTgAATF4AAAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +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 +KACpxeG3twd82aSg49kRAACfzN+mrv18AABV+q2Vr8wAFADw5WwAROTkQwBs5AAAqf49AAEA/hEA +AQDvDd9zAACf/0oAAGr4HQC6kQABAP4GABQA8aKvAIehoYYAr6EAAKnIAAMA9RBKYWbJnwAAn9kA +AQD3BfRkAKfSSQQAFgDxYO8DyV1eyQPvXwAAqasAAgD0U/LOq6reswAAn7oAAgD22IMAHrj88q0x +ABQA8R3/RvwbG/xG/xwAAKmoAAIA/ed8AAEA+bKzAACfygACAP3pbwABAPoSUb7xFAAUAPfZyNYA +ANfI2AABAP2pqAABAO0H/k4AABLvswAAn/ocAAA3/zkAAwD8Iv86ABQA95f/kwAAlP+WAAEA/amo +AAIA5sbRT1XN4LMAAJ/lz1Nb4bgAALJ5Skis5QwAFAD3P6o9AAA9qj8AAQD9cXAAAgDnHaTXwFdo +eAAAn7JUw9eVDwAAabTUz50lAC8A/Z+yADwA/Z+yADwA/XWDAH8NEQB/EAAAfxAAAH8QAAA0APR7 +4y8iDgDA1zQABAAzAPQUtfD/ZgASqfz2+wA7APwPMCAAfw8/AH8QAAB/EAAAfxAAAO4xXAAR35wA +Ed+cAABH/EIiFAAtAO7xfAGu1AoAADj6WgACmun/mQAtAP4FAH8PfgB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfwIkABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4Aj +ABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMA +G4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAb +gCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuA +IwAbgH8CJAAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb +/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/ +IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8j +ABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMA +G/9/EAAAfxAAAH8CAAB/DgCAfwIAAH8OAP9/EAAAfxAAAH8CAAAHgDcAB4A3AAeANwAHgDcAB4A3 +AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcA +B4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAH +gDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeA +NwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AH8CAAAH/zcAB/83AAf/NwAH/zcAB/83 +AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcA +B/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH +/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/ +NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83ACMAG/8jABv/IwAb/yMAG/8jABv/IwAb +/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8LAH8QAAB/EAAAIwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMA +G/8jABv/IwAb/yMAG/8jABv/IwAb/yMAD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/wsAfwQA/38MAAB/EAAA +fxAAAH8EAP9/DAAAfwQA/38MAAB/EAAAfxAAAH8EAP9/DAAAO/8DADv/AwA7/wMAO/8DADv/AwA7 +/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8DAH8QAAB/EAAAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/ +AwA7/wMAO/8DADv/AwA7/wMAO/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8DAH8QAAB/EAAAfxAAAH8Q +AAB/BDsA+gIsXYChADYA+y99uvH/Av80APwrjN3/Bv8xAPwFVsD/Cf8vAPwCW9z/C/8uAP1E0v8N +/ywA/BCZ/v8O/ysA/UXn/xD/KQD8AXj8/xH/KAD9B6n/E/8nAP0KuP8U/yYA/QvB/xX/JQD9A7D/ +Fv8lAP6Q/xf/JAD+Wv8Y/yMA/Rzu/xj/IwD+vf8Z/yIA/lP/Gv8hAP0F2v8a/yEA/mP/G/8hAP7N +/xv/IAD+PP8c/yAA/pj/HP8fAP0B4/8c/x8A/jD/Hf8fAP5p/x3/HwD+lf8d/x8A/sH/Hf8fAP7c +/x3/HwD+6/8d/x8A/vj/Hf8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB// +HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/zkA/YCCgAKANAD9gIKAB4AxAP2HgYAKgC4A/ouA +DoAsAP6DgBCAKgAUgCgA/oKAFIAmAP6DgBaAJAD9gIGAF4AjAP6CgBmAIQAdgCAAHoAfAP6CgB2A +HgAggB0AIYAcAP6BgCCAGwD+gYAcgPqBlq7A0AAZAP6BgBqA+5e+3fj/Av8ZAP6CgBiA/JXG7v8G +/xgA/oOAFoD8gqvg/wn/FwAXgPyBre7/C/8XABaA/aLp/w3/FgAVgPyIzP7/Dv8VAP6HgBOA/aLz +/xD/FQAUgP28/v8R/xQA/oKAEYD9g9T/E/8UABKA/YXc/xT/EwASgP2F4P8V/xMAEYD9gdj/Fv8S +ABKA/sj/F/8SABGA/q3/GP8RABGA/Y73/xj/EQD+gYAPgP7e/xn/EQAQgP6p/xr/EAD+hoAOgP2C +7f8a/xAAEID+sf8b/xAAEID+5v8b/xAAD4D+nv8c/w8A/oWADoD+zP8c/w8AEID+8f8c/w8AD4D+ +mP8d/w8AD4D+tP8d/w8AD4D+yv8d/w8AD4D+4P8d/w8AD4D+7v8d/w8AD4D+9f8d/w8AD4D+/P8d +/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8A +D4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/w8AD4Af/38QAAA5APkWO1x+ +oMEAMwD6BCtmotX/BP8xAPsRVaLy/wj/LgD7C2S6+v8L/ywA/CWI7f8O/yoA/EK8/v8Q/ygA/TWz +/xP/JgD8J67+/xT/JAD8BHf3/xb/IwD9L8z/GP8hAPwCgvv/Gf8gAP0SuP8b/x8A/S/d/xz/HgD9 +UPX/Hf8dAP1Y+v8e/xwA/WX9/x//GwD9bf7/IP8aAP1T/f8h/xkA/Tf2/yL/GAD9Ien/I/8XAP0I +0v8k/xcA/o//Jf8WAP1E/v8l/xUA/RHj/yb/FQD+mf8n/xQA/Sv8/yf/FAD+tf8o/xMA/kL/Kf8T +AP7G/yn/EgD+Mv8q/xIA/p//Kv8RAP0U9/8q/xEA/nX/K/8RAP7I/yv/EAD9Ff3/K/8QAP5e/yz/ +EAD+qf8s/xAA/uv/LP8PAP4Z/y3/DwD+Rv8t/w8A/nL/Lf8PAP6f/y3/DwD+vv8t/w8A/sz/Lf8P +AP7c/y3/DwD+6v8t/w8A/vj/Lf8PAC//DwAv/w8AL/8PAC//DwAv/w8AL/8PAC//DwAv/w8AL/8P +AC//DwAv/w8AL/8PAC//DwAv/w8AL/8PAC//DwAv/38EAAD6w9zk7vz/fwv6/38EAID64e7y9/7/ +fwv6/38QAAD6zN3k7vz/fw/6/38EAAAy//X87uTdw6GAXCsCAAEAO//78Ll8Lf9/C3//OYD+gYAB +gAEAfwPAgDL/9f738u7h0MCulYGAAYA7//v43L6W/38Lf/9/EAAAMv/y/O7k3MzBn31cOhYAAP88 +//3ms/9/D3//fwSAAPzciyoAOwAC//y+VQQAOAAE//zaWQIANgAG//3QQgA1AAj//aoTADMACf/9 +5kMAMgAK//z8dQEAMAAM//2oBgAvAA3//bcJAC4ADv/9vwoALQAP//2uAgAsABD//owALAAR//5X +ACsAEf/97x4AKgAS//65ACoAE//+TgApABP//dgFACgAFP/+YQAoABT//s8AKAAV//45ACcAFf/+ +lQAnABX//eIBACYAFv/+LQAmABb//mYAJgAW//6SACYAFv/+vgAmABb//toAJgAW//7pACYAFv/+ ++AAmABf/JwAX/ycAF/8nABf/JwAX/ycAF/8nABf/JwAX/ycAF/8nABf/JwAX/ycAF/8nABf/JwAX +/ycAF/8nABf/JwAX/ycAPwD8gYCAADsABYA5AAaA/YGLADUACoA0AAyAMgANgP6CAC8AEIAuABKA +LAASgP6CACoAE4D9gYAAKAAVgP6HACcAF4AnABiAJgAZgCUAGYD+gQAjABuAIwAbgP6BACEA/O7F +lYAYgP6CACAAAv/836qCgBeAIAAE//ztrIGAFYD+kgAeAAb//eihgBWAHwAI//3ViYATgP6BAB0A +Cf/986GAE4D+iAAcAAr//f66gBOAHQAM//3Ug4ASgBwADf/924SAEYAcAA7//d+FgBGAGwAP//3X +gYAQgBsAEP/+xoAQgP6CABkAEf/+q4AQgBoAEf/994+AEIAZABL//tyAD4D+gQAYABP//qeAD4AZ +ABP//eyCgA6A/oYAFwAU//6wgA+AGAAU//7ngA+AGAAV//6cgA6AGAAV//7KgA+AFwAV//7xgA+A +FwAW//6WgA2A/oEAFgAW//6zgA6AFwAW//7JgA6AFwAW//7fgA6AFwAW//7tgA6AFwAW//70gA6A +FwAW//78gA6AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+A +FwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwB/ +EAAAPwD8dzwIADsAAf/79rNmFgA4AAT/+/q6YwsANQAH//zxmSwAMwAJ//z+ukAAMQAM//27NQAv +AA3//P6tJgAtAA///PeABgArABH//dE1ACoAEv/8+38CACgAFP/9thEAJwAV//3hNAAmABb//fVO +ACUAF//9/F4AJAAY//38YwAjABn//f5qACIAGv/9/VEAIQAb//31NQAgABz//ecgAB8AHf/90AcA +HgAe//6LAB4AHv/9/UEAHQAf//3hDwAcACD//pQAHAAg//37KAAbACH//rEAGwAi//5AABoAIv/+ +xAAaACP//jMAGQAj//6cABkAI//99hIAGAAk//5xABgAJP/+wgAYACT//fwTABcAJf/+WgAXACX/ +/qYAFwAl//7pABcAJv/+GAAWACb//kQAFgAm//5xABYAJv/+nQAWACb//rwAFgAm//7LABYAJv/+ +2gAWACb//ukAFgAm//74ABYAJ/8XACf/FwAn/xcAJ/8XACf/FwAn/xcAJ/8XACf/FwAn/xcAJ/8X +ACf/FwAn/xcAJ/8XACf/FwAn/xcAJ/8XACf/FwB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAAjABuAIwAbgCMAG4Aj +ABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMA +G4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAb +gCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuAIwAbgH8FAAAjABv/ +IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8j +ABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMA +G/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb +/38FAAB/EAAAfxAAAH8LAIB/BQAAfwsA/38FAAB/EAAAfxAAAAeANwAHgDcAB4A3AAeANwAHgDcA +B4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAH +gDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeA +NwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgH8FOAAH/zcAB/83AAf/NwAH +/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/ +NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83 +AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/9/BTgAIwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8j +ABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/38DAAB/EAAAfxAAACMAD/8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8jABv/IwAb/yMAG/8j +ABv/IwAb/yMAG/8jABv/IwAb/yMAG/9/AwAAfwkAAH8EAP9/AwAAfxAAAH8QAAB/CQAAfwQA/38D +AAB/CQAAfwQA/38DAAB/EAAAfxAAAH8JAAB/BAD/fwMAACsAD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMA +O/8DADv/AwA7/wMAO/9/AwQAfxAAAH8QAAArAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8D +ADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMAO/8DADv/AwA7/wMA +O/8DADv/fwMEAH8QAAB/EAAAfxAAAH8QAAAfAB//HwAf/x8AH/8fAB//HwAf/x8A/vj/Hf8fAP7r +/x3/HwD+3P8d/x8A/sH/Hf8fAP6U/x3/HwD+af8d/x8A/i//Hf8gAP7g/xz/IAD+l/8c/yAA/jr/ +HP8hAP7M/xv/IQD+Yv8b/yEA/QTV/xr/IgD+UP8a/yMA/rv/Gf8jAP0b7f8Y/yQA/lj/GP8lAP6N +/xf/JQD9Aq7/Fv8mAP0Kv/8V/ycA/Qew/xT/KAD9Bqf/E/8pAPwBdPv/Ef8rAP1B5P8Q/ywA/A+Q +/f8O/y4A/UDO/w3/LwD8AVfZ/wv/MQD7BFK8/v8I/zQA/CmJ2v8G/zcA+yx7t+//Av86APoCKlt+ +oAB/Bv8ADwAPgB//DwAPgB//DwAPgB//DwAPgB//DwAPgB//DwAPgP78/x3/DwAPgP71/x3/DwAP +gP7u/x3/DwAPgP7g/x3/DwAPgP7K/x3/DwAPgP60/x3/DwAPgP6X/x3/DwAQgP7w/xz/DwD+hYAO +gP7L/xz/EAAPgP6d/xz/EAAQgP7m/xv/EAD+gYAOgP6x/xv/EAAQgP2C6v8a/xEAEID+qP8a/xEA +EYD+3f8Z/xEA/oeAD4D9jfb/GP8SABGA/qz/GP8SAP6CgBCA/sb/F/8TABGA/YHX/xb/EwD+gYAQ +gP2F3/8V/xQAEoD9g9j/FP8UAP6DgBGA/YPT/xP/FQAUgP26/f8R/xUAFYD9oPL/EP8WAP6CgBOA +/IfI/v8O/xcAFoD9oOf/Df8XAP6SgBaA/avs/wv/GAAYgPuCqd7+/wj/GQAagPyUxO3/Bv8aAP6B +gBqA+5a92/f/Av8bAB6A+oGVrb/QABsAIoAdAP6BgB+AHgAggB8AH4AgAB6AIQAdgCMAG4AkAP2A +gYAXgCYA/oOAFoAoABaAKgAUgCwAEoAuABCAMQD9i4GACoA0AP2AgoAHgDkA/YCCgAKAfwMAAH8Q +AAAPAC//DwAv/w8AL/8PAC//DwAv/w8A/vj/Lf8PAP7q/y3/DwD+3P8t/w8A/sz/Lf8PAP69/y3/ +DwD+n/8t/w8A/nL/Lf8PAP5G/y3/DwD+Gf8t/xAA/ur/LP8QAP6o/yz/EAD+Xf8s/xAA/RL8/yv/ +EQD+xf8r/xEA/nT/K/8RAP0R9f8q/xIA/p7/Kv8SAP4x/yr/EwD+xf8p/xMA/kH/Kf8UAP6y/yj/ +FAD9Kfv/J/8VAP6X/yf/FQD9EOL/Jv8WAP09/P8l/xcA/oz/Jf8XAP0H0f8k/xgA/SDo/yP/GQD9 +NvX/Iv8aAP1R/f8h/xsA/Wr+/yD/HAD9XPv/H/8dAP1X+v8e/x4A/U71/x3/HwD9KNf/HP8gAP0O +rv8b/yEA/AJ++v8Z/yMA/S7K/xj/JAD8BG/0/xb/JgD8Jar+/xT/KAD9LKr/E/8qAPw+uP7/EP8s +APwkiOz/Dv8uAPsKYrn6/wv/MQD7C02i8f8I/zQA+QQrZqLV/v8D/zkA+RQ5WnydvwB/Av8AfwjA +//rB2+Pu/P85/38HAAB/CMD/+uDt8ff+/zn/fwQAgH8DAAB/EAAAfwzA//rM2uPu/P85/38DAAB/ +CLz/++62eSr/Mf/1/O7j2sGfflspAQB/BwIAfwi8//v327yV/zH/9v738e3gz7+tlIB/A/2A/oGA +AYB/AwIAfxAAAH8Mvv/95rP/Mf/0/O7i2sy+nXtaOBQAfwMBABf/JwAX/ycAF/8nABf/JwAX/ycA +Fv/++AAmABb//ugAJgAW//7ZACYAFv/+vwAmABb//pIAJgAW//5mACYAFv/+LAAmABX//uAAJwAV +//6TACcAFf/+NwAnABT//s4AKAAU//5gACgAE//91wQAKAAT//5LACkAEv/+tgAqABH//e4dACoA +Ef/+VAArABD//ooALAAP//2rAgAsAA7//b0JAC0ADf/9tgkALgAM//2mBgAvAAr//ftyADEACf/9 +4z8AMgAH//z+oRIAMwAG//3NPwA1AAT//NdUAQA2AAH/+/67UQMAOAD82YgoAH8HvAAX/w+AFwAX +/w+AFwAX/w+AFwAX/w+AFwAX/w+AFwAW//78gA6AFwAW//70gA6AFwAW//7sgA6AFwAW//7fgA6A +FwAW//7JgA6AFwAW//6zgA6AFwAW//6WgA6AFwAV//7wgA6A/oEAFgAV//7JgA6A/oUAFgAV//6b +gA6AGAAU//7ngA+AGAAU//6wgA+AGAAT//3rgoAOgP6GABcAE//+pYAPgBkAEv/+24APgP6BABgA +Ef/9946AEIAZABH//qqAEIAaABD//sWAEYAaAA///dWBgBCAGwAO//3ehIAQgP6CABoADf/924SA +EYAcAAz//dODgBGA/oMAGwAK//39uYATgB0ACf/98Z+AFIAdAAf//P7QiYAUgB4ABv/95p+AFYAf +AAT//euqgBeAHwAB//v+3aiBgBeAIAD87MSUgBiA/oIAIAAbgP6BACEAGoD+gQAiABqAJAAZgCUA +GIAmABaA/oIAJgAVgP6HACcAFIAqABKA/oIAKgAQgP2BqgArAA+A/oMALQANgP6CAC8ADIAyAAqA +NAAIgDYABYA5APyBgJIAfwN8AH8QAAAn/xcAJ/8XACf/FwAn/xcAJ/8XACb//vgAFgAm//7oABYA +Jv/+2QAWACb//soAFgAm//67ABYAJv/+nAAWACb//nAAFgAm//5DABYAJv/+FwAWACX//ukAFwAl +//6lABcAJf/+WgAXACT//fwTABcAJP/+wQAYACT//m8AGAAj//31EgAYACP//poAGQAj//4yABkA +Iv/+wgAaACL//j8AGgAh//6vABsAIP/9+icAGwAg//6TABwAH//93w4AHAAe//39QAAdAB7//okA +HgAd//3OBgAeABz//eYeAB8AG//99DMAIAAa//38TwAhABn//f5nACIAGP/9/GIAIwAX//37XAAk +ABb//fRMACUAFf/92y0AJgAU//20EQAnABL//Pp6AQAoABH//dAzACoAD//89ncDACsADf/8/qkj +AC0ADP/9uzMALwAJ//z9tzwAMQAH//zwmSoAMwAE//v5uGIKADUAAf/79rNeEAA4APx3PAcAfwN8 +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/ +CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8K +AAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoA +AH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAA +fwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/ +BkAAfwZAAH8GQAB/BkAAAAAB9AAAAfQAAAAAAAAA+gAAAPoAAAAAAAAAfQAAAH0AAAAAAAAAPgAA +AD4AAAAAAAAD6AAAA+gAAAABAAAAB1NsaWRlMgAAAAAGAAAABAAAAP8AAAAIAAAABAAAAAEAAAAJ +AAAABAAAAAAAAAAcAAAABAAAAAAAAAAKAAAABAAAAAAAAAALAAAABAAAAAAAAAAMAAAABAAAAAAA +AAANAAAABAAAAAAAAAAPAAAACAAAAAAAAAAAAAAABwAAAAQAAAAAAAAAFAAAAAQAAAADAAAAAAAA +AAAAAE1NAAAAAAAAA+gAAAPoAAAABAAATXEAAO0yAADtPgAA7UoAAO1WAAAAAAAAA+gAAAPoAABR +fQAAUY0AAFGdAABRrQAAUb0AAFHNAABR3QAAUe0AAFH9AABSDQAAUh0AAFItAABSPQAAUk0AAFJd +AABSbQAAUn0AAFKNAABSnQAAUq0AAFK9AABSzQAAUt0AAFLtAABS/QAAUw0AAFMdAABTLQAAUz0A +AFNNAABTXQAAU20AAFN9AABTjQAAU50AAFOtAABTvQAAU80AAFPdAABT7QAAU/0AAFQNAABUHQAA +VC0AAFQ9AABUTQAAVF0AAFRtAABUfQAAVI0AAFSdAABUrQAAVL0AAFTNAABU3QAAVO0AAFT9AABV +DQAAVR0AAFUtAABVPQAAVU0AAFVdAABVbQAAVX0AAFWNAABVnQAAVa0AAFW9AABVzQAAVd0AAFXt +AABV/QAAVg0AAFYdAABWLQAAVj0AAFZNAABWXQAAVm0AAFZ9AABWjQAAVp0AAFatAABWvQAAVs0A +AFbdAABW7QAAVv0AAFcNAABXHQAAVy0AAFc9AABXTQAAV10AAFdtAABXfQAAV40AAFm+AABbPgAA +XHoAAF6CAABgrgAAYcsAAGTGAABk1gAAaNIAAGtAAABvpQAAcV8AAHFvAABxfwAAcY8AAHGfAABz +6wAAdWAAAHbAAAB4/wAAeysAAHw2AAB/agAAf3oAAIPVAACGmAAAiyQAAI0DAACNEwAAjSMAAI0z +AACNQwAAjVMAAI1jAACNcwAAjYMAAI2TAACNowAAjbMAAI3DAACN0wAAjeMAAI3zAACOAwAAjhMA +AI4jAACOMwAAjkMAAJAqAACRQwAAkZ0AAJR9AACVmgAAlaoAAJdHAACXbQAAl30AAJmUAACbNQAA +nBYAAJwmAACcNgAAnEYAAJxWAACdhgAAoHoAAKOxAACkGQAAplYAAKdjAACn/QAAqpEAAKuXAACt +tAAArcQAALBIAACwWAAAsGgAALB4AACwiAAAsJgAALDuAACxIAAAsTAAALFAAACxUAAAsWAAALFw +AACxpgAAsbYAALHGAACx1gAAseYAALH2AACyBgAAshYAALImAAC4SAAAvGAAALxwAADBrQAAxdcA +AMaOAADGngAAxq4AAMa+AADGzgAAxt4AAMbuAADG/gAAxw4AAMceAADIVQAAztIAANYXAADW2gAA +3U8AAOSFAADk/gAA5Q4AAOUeAADlLgAA5T4AAOVOAADlXgAA5W4AAOV+AADljgAA5Z4AAOgGAADo +FgAA6CYAAOrKAADregAA67IAAOvCAADr0gAA6+IAAOvyAADsAgAA7BIAAOwiAADsMgAA7EIAAOxS +AADsYgAA7HIAAOyCAADskgAA7KIAAOyyAADswgAA7NIAAOziAADs8gAA7QIAAO0SAADtIgAAAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/BX4A/YOAADoA/ouAAYA6AP6BgAKAOAD+g4AEgDcA/oGABYA1 +AP6ZgAeANAD+hYAIgDMA/oOACYAyAP6CgAqAMQD+goALgDAADoAvAP6DgA2ALgAQgC0A/pKAD4At +ABGALAASgCsAE4ArABOAKgD+gYASgCkAFYApABWAKAD+g4AUgCgAFoAnAP6EgBWAJwAXgCYA/oaA +FoAmABiAJgAYgCUA/oOAF4AlABmAJQAZgCQA/oSAGIAkABqAJAAagCQAGoAjABuAIwD+goAZgCMA +G4AjABuAIwAbgCMAG4AjABuAIwAbgH8FfgD9IZEAOgD7C4j7/wA5AP1N4/8B/zgA/SG+/wP/NwD9 +T+7/BP81APwFiP7/Bf80AP0Zy/8H/zMA/SHa/wj/MgD9LeX/Cf8xAP0/8f8K/zAA/S7v/wv/LwD9 +I+f/DP8uAP0W2v8N/y0A/QfL/w7/LQD+kv8P/ywA/Uz+/w//KwD9Hu3/EP8qAP0Bvv8R/yoA/lv/ +Ev8pAP0O5f8S/ykA/pL/E/8oAP0l/P8T/ygA/p3/FP8nAP0d+f8U/ycA/pT/Ff8mAP0V9v8V/yYA +/m7/Fv8mAP7L/xb/JQD+Kf8X/yUA/of/F/8lAP7a/xf/JAD+G/8Y/yQA/l7/GP8kAP6f/xj/JAD+ +4f8Y/yMA/hT/Gf8jAP47/xn/IwD+Yv8Z/yMA/on/Gf8jAP6v/xn/IwD+x/8Z/yMA/tP/Gf8jAP7g +/xn/fxAAAH8QAAB/BAwA/oaAEID+hgAmAP2AgYAXgP6EAB8A/oOAH4AaACWA/YGAABQAKoD+hAAS +ACyA/oMAEAAvgA8AMIAOADGA/oQACwAygP6BAAoANYAJADWA/oUABwA2gP6DAAYAN4D+ggAFADiA +/oIABAA6gAQAO4ADADyAAgA9gAEAPYABAD6A/gCAPYD+g4B/Bn+AfwQMAOsTOmKIr8fS3e75+e7d +0seuiGI6EwAmAPsYVZne/xL/++aqZh8AHwD8KYfa/xr//NmFKAAZAPwUbsv/IP/8yW0UABQA/B6R +9f8k//z4mR0AEgD+9/8o//z6oicAEAAs//z7kQ4ADgAu//zmXgEADAAw//28HwALADH//fBVAAoA +Mv/8/pEGAAgANP/9yBcABwA1//3eJQAGADb//egxAAUAN//98T0ABAA4//3xMgADADn//eomAAIA +Ov/93RgAAQA7//vIBgAA/zv//I0AAP87//z+UAD/PP/97iH/Pf/+u/9/Bj//fxAAAH8QAAB/CcAA +/oEAPQD9gIgAPAABgD0AAYD+gwA7AAKAPAACgP6EADoAA4A7AAOA/oYAOQADgP6BADkABIA6AASA +/oMAOAAFgDkABYA5AAWA/oQANwAFgP6BADcABoA4AAaAOAAHgDcAB4A3AAaA/oEANgAHgDcAB4A3 +AAeANwAHgDcAB4A3AH8JwAD+VwA9AP3nDwA8AP3/jgA8APz/+yMAOwAB//6aADsAAf/9+h8AOgAC +//6RADoAAv/99hMAOQAD//5rADkAA//+yAA5AAT//icAOAAE//6CADgABP/+1gA4AAX//hsANwAF +//5bADcABf/+nAA3AAX//t4ANwAG//4SADYABv/+OAA2AAb//l8ANgAG//6GADYABv/+rQA2AAb/ +/sQANgAG//7RADYABv/+3gA2AH8GvwD+/wA7AAL/OwAD/zkABf84AAb/NgAI/zUACf80AAr/MwAL +/zIADP8wAA7/LwAP/y4AEP8uABD/LQAR/ywAEv8rABP/KgAU/yoAFP8pABX/KAAW/ygAFf8oABX/ +KAAV/ykAFP8qABP/KgAT/ysAEv8rABP/KwAS/ywAEf8tABH/LAAR/y0AEf8tABH/LQAQ/y4AEP8u +ABD/CgB/EAAAfxAAAH8GvwD+JgA7APwKifkAOgD7P9j//wA4AP0PoP8C/zgA/Tnc/wP/NgD8BIb8 +/wT/NQD9F7//Bv80AP065P8H/zMA/Vn4/wj/MgD9b/3/Cf8wAP0BlP8L/y8A/QKb/wz/LgD9AqH/ +Df8uAP6S/w7/LQD+ev8P/ywA/Vr+/w//KwD9MPX/EP8qAP0R3P8R/yoA/q3/Ev8pAP5c/xL//v4A +JwD9Gu7/Ef/980sAJwD+pv8R//3nMwAnAP04/v8Q//3gIgAnAP0Bx/8Q//3dHwAoAP5I/xD//eol +ACkA/rz/D//98zEAKQD+M/8P//3+VQAqAP6Y/w///owAKgD9Buz/Dv/91ggAKgD+T/8O//39NgAr +AP6e/w7//qAALAD+3v8N//36HQArAP4g/w7//qIALAD+Wv8O//48ACwA/oL/Df/93wEALAD+qv8N +//6YAC0A/s//Df/+WwAtAP7h/w3//jEACQB/AjwAA/8yAAz/LAAS/ycAF/8iABz/HgAg/xsAI/8X +ACf/FAAq/xEALf8PAC//DAAy/woANP8IADb/BQA5/wMAO/8BAD3//gD/Ov8CADT/CgAu/xAAKf8V +ACX/GQAh/x0AHv8gABr/JAAY/yYAFf8pABL/LAAQ/y4ADv8wAAz/MgAK/zQACP82AAb/OAAF/zkA +A/87AAL/PAAB/38EvgB/EAAAfxAAAH8CPAD7DiI2SgAxAPYCHDxdfp+/4Pr/Av8sAPgIM2KRudn4 +/wr/JwD5ETxvosz4/xD/IgD6AzNwrun/Fv8eAPoEM2+q7v8a/xsA+yp3wPf/Hv8XAPsDPIjW/yL/ +FAD7Dlak7f8l/xEA+wJEovX/KP8PAPwogOD/K/8MAPwQZsT/Lv8KAPwjkfb/MP8IAPw8qvz/Mv8F +APwCTcX/Nf8DAPwFZtz/N/8BAPwCXNz/Nf/4+ubTwABI1P8v//b948KhgF8+HgMAAQD+tP8s//ng +sYNUJwYACQAo//n8z5xtPxAADwAk//r7zJFVEgAUACD/+vm9fkAJABgAHf/77apeEAAcABr/+9qM +PwMAHwAX//zmiiwAIwAU//v3qUoDACUAEv/8yWgRACgAD//8/bNEACsADf/895gmAC0AC//87YEW +AC8ACf/88oIPADEAB//8+5IVADMABv/9vS0ANQAE//3mVAA3AAL//P6aEAA4AAH//elNADoA/P+2 +FgA7AP2IAgB/BL0AfwIAACP/GwAs/xIAMv8MADf/BwA8/wIAfwLP/wEALv8iABz/KgAU/zAADv81 +AAn/OQAF/z0AAf9/CEAAfxAAAH8QAAB/AgAA211wg5aru8HMzNfd3e7u9P//9O7u3d3XzMzBu6uW +g3BdSTYiDgAaACP/9vrgv55+XTwbAQARACv/+PjZuJBiMwgACwAx//n73bOATSIABgA3//rornAy +AwABADv/+/O7gET/fwJ//9utmIRxXks8MzMmIiEREQsAAAsRESEiJjMzPEtecoWZrcDU5/r/Gv8i +APYDHj9ggKLD4/3/Ev8qAPkHJ1WEsuD/Df8wAPkRP26c0Pz/B/81APoMRIC7+P8D/zkA+QpBf776 +/wA8AP0LTQB/CD8AfwNAAP7/AD0AA/87AAf/NwAK/zQADf8xAA//LwAS/ywAFP8qABb/KAAZ/yUA +G/8jAB3/IQAe/yAAIP8eACL/HAAj/xsAJf8ZACb/GQAn/xsAJP8cACP/HgAh/yAAH/8hAB//IQAe +/yIAHf8jABv/JQAa/yYAGf8mABn/JwAY/ycAF/8oABf/KQAW/ykAFf8qABX/KgAU/ysAFP8rABP/ +LAAT/ywAEv8sABP/LAAS/y0AEf8tABH/LgAR/y0AEf8tABH/LgAQ/y4AEP8uABD/AwB/EAAAfxAA +AH8DQAD+CAA9APv2v3YpADoAA//73pFEBQA2AAb/++2jVg4AMwAJ//v4s1UEADAADP/85pEwAC4A +D//81XcVACsAEf/8+KIqACkAE//8/bNEACcAFv/8zV4EACQAGP/83GUFACIAGv/821oCACAAHP/9 +0kYAHwAe//2xJQAdAB///PmGCQAbACH//d1FABoAIv/8/p0OABgA/Zno/yH//eA+ABgA+wRAjdv/ +H//8/IMDABoA/CyL5v8e//28FQAbAPsDS6r4/xz//eM3AB0A/BFpyv8b//33VgAfAPwzovz/Gf/9 +/oAAIAD8J5n3/xn//ZEBACAA/BaC7f8Y//2XAQAhAPwPg/P/F//9nAIAIgD8FpT7/xb//o8AJAD9 +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 +AiBFaoahvNbz/xb/GAD4DDhhhqzS9/8e/xMA+RNEdqfY/f8k/w4A+gQ2c6/h/yr/CgD6CD59ufP/ +Lv8HAPsoc734/zL/AwD7CEiT3f82//oACliv9f85//2k8/9/C73/fwYAAAHu8uPazLyuoZSHclxD +KxQALwAO//b548enhGE/HAEAJgAW//j31Kp8TyIBACAAHP/58saYYSgBABsAIf/67bR8QgwAFwAl +//r6wn04AwATACn/++6tZxsAEAAs//v+xnMgAA0AMP/8zHghAAoAMv/7/b1bCQAHADX//O+WNAAF +ADX//OmQMgAFADL/+/irTQUABwAw//zFaBEACgAt//zfgiUADQAq//v2qkQBAA8AJ//7/LdaCQAS +ACX//NN0GgAVACL//OmPMQAYAB//+/eqTAQAGgAd//zMbhQAHQAa//ziiCUAIAAX//vxnD4BACIA +FP/7/LZZCQAlABL//NV/HwAoAA///OiOMAArAAz/+/iyVQUALQAJ//v+w2UQADAAB//83YAjADMA +BP/78KFEAQA1AAH/+/y1WAkAOAD80HIYAH8CPAB/AgAACoD6gYCAg4sALgAWgP2EgAAlAByA/YKO +AB8AIID8gYCAABoAJ4D+mQAVACqA/YGAABEALoD+ggAOADKA/pIACgA1gP6OAAcAN4D9gZIABAA6 +gP6CAAIAPID8gYAAgH8A/4AB9/Lx7ebe19DKw7muoZWKgC+ADv/3/PHj08Kwn46AJ4AW//n76tW+ +p5GAIYAc//r548ywlIAcgCH/+vbavqGGgBeAJf/6/eG+nIGAE4Ap//v31rONgBCALP/7/uO5kIAN +gDD//Oa8kIAKgDL/+/7erYSAB4A1//z3y5qABYA1//z0yJmABYAy//v81aaCgAeAMP/84rSIgAqA +Lf/878GSgA2AKv/8+9WigBCAJ//7/tuthIASgCX//Om6jYAVgCL//PTHmIAYgB//+/vVpoKAGoAd +//zmt4qAHYAa//zxxJKAIIAX//z4zp+AI4AU//v+26yEgCWAEv/86r+PgCiAD//89MeYgCuADP/7 +/NmqgoAqgPyBhgD/CP/7/uGyiIAsgAMAB//87sCRgCuA/YKAAAQABP/8+NCigC2ACAAB//v+2qyE +gCqA/YGAAAoA/Oi5jIAsgA4ALID9gZkADwApgP2BgAASACeA/oMAFQAlgBkAIoD+iwAaAB+A/oUA +HQAcgP6CACAAGYD9gZkAIgB/EAAAfwIAAAHu8ePd0MK1p5mJfG1UPCULAC4AD//29NnCp4ViQB0C +ACUAF//4+Ne0jGAzCQAfAB3/+fzYqn1QGgAaACP/+uGnbjYFABUAJ//69sKFQQYAEQAr//v0tXAr +AA4AL//75J1MBwAKADL/+/GlUgkABwA1//v0qlUHAAQAOP/87ZEvAAIAO//71XcUAP88//33n/9/ +Bz3//fis/zr/+8xvFQD/N//84IMmAAIANf/78p4/AgAEADL/+/3EZgwABwAw//zTdRoACgAt//zp +kDIADQAq//v4q00FAA8AKP/8zG8UABIAJf/834IlABUAIv/78Z0+AQAXAB//+/3EZgsAGgAd//zS +dBkAHQAa//zojzEAIAAX//v4s1UFACIAfxAAAH8FAAD+gAA9AAKAPAAFgDkABoD+qgA2AAiANgAJ +gP6BADMAC4D+hAAxAA2AMQAPgC8AD4D+gQAtABKALAASgP6BACoAFYApABeAJwAXgP6DACUAGID9 +gYAAIwAagP6DACIAHID+qgAgAB2AIQAcgCIAF4D9gYAAJAAWgCgAEoD9gZkAKQARgC0ADoAwAAqA +/YGqADEACYA1AAWA/oQANwADgDsA/YCZAH8DvQB/EAAAfwUAAP4sAD0A/P63RAA7AAL//NFmCAA4 +AAT//OBgAwA2AAb//NVQAQA0AAj//chBADMACv/9tB0AMQAL//zwZAEALwAN//25HgAuAA7//PFn +AQAsABD//bwgACsAEf/882kBACkAE//9viIAKAAU//z0bAIAJgAW//3BIwAlABf//PVvAgAjABn/ +/cMlACIAGv/89nIDACAAG//982gAIAAY//v9xGYMACEAFv/81XccACQAE//865I0ACcAEP/7+K1P +BQApAA7//MdqEgAsAAv//OSRLgAvAAj/+/aqTQMAMQAF//v8uVwKADQAA//81HYbADcA+//umTwA +OgD9TgUAfwO9AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAACMAG4AjABuAIwAbgCMAG4AjABuAIwAbgCMAG4AjABuA +IwAbgCMA/oGAGYAjABuAIwAbgCQAGoAkABqAJAAagCQAGoAlABmAJQAZgCUAGYAmABiAJgD+gYAW +gCYAGIAnABeAJwAXgCgAFoAoAP6DgBSAKQAVgCkA/omAE4AqABSAKwATgCsA/oSAEYAsABKALQAR +gC0AEYAuAP6GgA6ALwAPgDAA/oKADIAxAA2AMgAMgDMA/oOACYA0AP6FgAiANQAJgDcA/oGABYA4 +AP6EgASAOgD+gYACgDsAA4A9AAGAfwRAACMA/u3/Gf8jAP75/xn/IwD++f8Z/yMA/u3/Gf8jAP7g +/xn/IwD+0/8Z/yMA/sf/Gf8jAP6v/xn/IwD+iP8Z/yMA/mH/Gf8jAP46/xn/IwD+Ev8Z/yQA/uD/ +GP8kAP6f/xj/JAD+Xv8Y/yQA/hr/GP8lAP7Y/xf/JQD+hv8X/yUA/ib/F/8mAP7K/xb/JgD+bf8W +/yYA/RT2/xX/JwD+kv8V/ycA/Rz5/xT/KAD+m/8U/ygA/SP7/xP/KQD+j/8T/ykA/Q3k/xL/KgD+ +WP8S/ysA/rz/Ef8rAP0d7P8Q/ywA/Uz+/w//LQD+j/8P/y0A/QbI/w7/LgD9Fdj/Df8vAP0i5v8M +/zAA/S3v/wv/MQD9PvD/Cv8yAP0s5P8J/zMA/SHZ/wj/NAD9F8j/B/81APwEgP3/Bf83AP1N7f8E +/zgA/R+7/wP/OgD9TeL/Af87APsOjvv/ADwA/SCRAH8EPwB/EAAAfxAAAH8H/oD9gQCAPIABADyA +/JkAAIA6gP6FAAEAOoD+gwACADmA/oIAAwA5gAUAOIAGADeABwA1gP6GAAcANYAJADKA/oEACgAx +gP6EAAsAMIAOAC+ADwAsgP6DABAA/oWAKYAVAP2GgYAkgBoAIID+gwAfAP2AgYAXgP6EACYAEID8 +gYCHAH8DHwB/B3///rn/PP/97iD/O//8/k8A/zv//IoAAP86//vFBQAA/zn//dwXAAEAOf/95iEA +AgA4//3xMQADADf//fA8AAQANv/95zAABQA1//3dJAAGADT//cUVAAcAMv/8/pEGAAgAMf/98FMA +CgAw//25HQALAC7//eVeAA0ALP/8+owMAA4A/vf/KP/8+aIlABAA/BeI9f8k//z4mRwAFAD8E2vI +/yD//MdqEgAZAPwmg9b/Gv/81YElAB8A+xZVmd3/Ev/75qpmHQAmAOsSOGCHrcXQ3e35+e3d0MSt +hl84EQB/Ax8AfxAAAH8QAAAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcAB4A3AAeANwAHgDcA +BoD+ggA2AAeANwAGgDgABoA4AAaAOAAFgP6FADcABYA5AAWAOQAEgP6DADgABIA6AAOA/oEAOQAD +gP6GADkAA4A7AAKA/oQAOgACgDwAAYD+gwA7AAGAPQABgD0A/oAAfwj+AAb//usANgAG//74ADYA +Bv/++AA2AAb//usANgAG//7eADYABv/+0QA2AAb//sQANgAG//6tADYABv/+hQA2AAb//l4ANgAG +//43ADYABv/+EgA2AAX//t4ANwAF//6bADcABf/+WgA3AAT//f4ZADcABP/+1QA4AAT//oEAOAAE +//4nADgAA//+xgA5AAP//mkAOQAC//31EwA5AAL//o8AOgAB//34GwA6AAH//pcAOwD8//ohADsA +/f+LADwA/eYOADwA/lQAfwj+ACMAEP8uABD/LgAQ/y4AEP8uABD/LgAQ/y4AEP8uABH/LQAR/y0A +Ef8uABH/LQAR/y0AEv8sABP/LAAS/ywAE/8sABP/KwAU/ysAFP8qABX/KgAV/ykAFv8pABX/KgAU +/yoAFP8rABP/LAAS/y0AEf8uABD/LgAQ/y8AD/8wAA7/MgAM/zMAC/80AAr/NQAJ/zYACP84AAb/ +OQAF/zsAA/88AAL/PgD+/wB/BX8AfxAAAH8QAAAjAP7s/w3//hMALQD++f8N//4GAC0A/vn/Df/+ +BgAtAP7t/w3//hQALQD+4f8N//4xAC0A/s7/Df/+XAAtAP6p/w3//pkALQD+gv8N//3hAQAsAP5a +/w7//j0ALAD+IP8O//6kAC0A/t3/Df/9+x8ALAD+nf8O//6jACwA/k3/Dv/9/jgAKwD9Bez/Dv/9 +1wkAKwD+l/8P//6QACsA/jH/EP/+WAArAP66/w///fQ0ACoA/kX/EP/96ycAKgD+xP8Q//3fIQAp +AP02/v8Q//3iJQApAP6i/xH//ew8ACgA/Rns/xH//fVSACgA/lj/Ev/+/gApAP6q/xL/KgD9ENv/ +Ef8rAP0u9P8Q/ywA/Vj+/w//LQD+dv8P/y4A/o3/Dv8uAP0CnP8N/y8A/QGX/wz/MAD9AZD/C/8y +AP1v/f8J/zMA/VX3/wj/NAD9NuL/B/81AP0VvP8G/zYA/AOC/P8E/zgA/Tfb/wP/OQD8DZv+/wH/ +OwD7Pdf//wA7APwIhPcAPQD+HwB/BX8AfwWAAAH/PQAC/zwAA/87AAX/OQAG/zgACP82AAr/NAAM +/zIADv8wABD/LgAS/ywAFf8pABj/JgAa/yQAHv8gACH/HQAl/xkAKf8VAC7/EAA0/wsAO/8FADz/ +AwA7/wUAOf8IADb/CgA0/wwAMv8PAC//EQAt/xQAKv8XACf/GwAj/x4AIP8iABz/JwAX/ywAEv8z +AAv/OwAD/38BAAB/EAAAfxAAAH8FgAD9iAMAPAD8/7sYADsAAf/96lAAOgAD//2fEgA4AAT//ehZ +ADcABv/9xzwANQAH//z+qiMAMwAJ//z5jhIAMQAL//zvhBgALwAN//z4mykALQAP//z+u00AKwAS +//zNbBMAKAAU//v5rE0EACUAF//86I0uACMAGv/73Y9CBAAfAB3/+/SzXhAAHAAg//r6v4BDCwAY +ACT/+vvMkVUTABQAKP/5/dGecEISAA8A/aP9/yv/+eO1hlcrCAAKAP0rtf8w//fuzKqIZkQiBAAE +AP1K1P81//v76NXCAAIA/ANj2/83/wUA/AJNxP81/wgA/DOi/P8y/woA/CKR9f8w/wwA+w9eu/7/ +Lf8PAPwngN7/K/8RAPsCPJn0/yj/FAD7Ck2Z5/8l/xcA+wIzgMz/Iv8bAPsmdL31/x7/HgD6BDNv +qu3/Gv8iAPoDMG6s5/8W/ycA+RE8b5nE9/8Q/ywA+AYwXoy11ff/Cv8zAPcZOlt7nL3e+P8C/zsA ++wwfNEgAfwD/AH8JfgAB/zkABf81AAn/MAAO/yoAFP8jACr/AQB/Ayz/AgA3/wcAMv8MACv/EwAj +/38BHAB/EAAAfxAAAH8JfgD9C00AOAD5C0SBwPv/ADQA+g1EgLv4/wP/MAD5E0JwntH9/wf/KgD5 +CSxYh7bk/w3/IwD3ETNVd5m73f3/Ev/br5yHc2BNQTMzKiIiEhEMAAAMERIiIiozM0FNYHOHnK/C +1ej7/38C1//787uARP82//rnq24wAgABADH/+fvVqoBNGQAGACv/+PbVtIxeMAYACwAj//f43b2c +e1o5GAASANtbboGUqLu8zMzU3d3s7vP///Pu7N3d1MzMvLunlIFuW0g0HwwAfwEbACoAEP8uABD/ +LgAQ/y4AEP8uABD/LgAQ/y4AEP8tABH/LQAR/y0AEf8sABH/LQAR/ywAEv8rABP/KwAS/ysAE/8q +ABP/KgAU/ykAFP8pABX/KAAV/ygAFv8mABf/JgAX/yYAGP8kABn/JAAZ/yMAGv8iABv/IQAd/x8A +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 +8KE0AAIAOP/8w1UEAAIANf/885YqAAUAMv/7/cNmDQAHADD//MpvGAAKACz/+/zAdCUADQAp//vw +qVsSABAAJf/69bt7OwUAEwAh//rvuXw8BgAXABz/+fLBjVgkAQAbABb/+PLKoXhRJgIAIAAO//f4 +2ryef2FCHAAnAPDu4NvMxruxoo98aVNALBgAfwUwABiAJgAUgP6DACgAF4AnABmA/oIAIwAcgP6C +ACAAIIAeACKA/oIAGgAmgBgAKYAVACuA/oIAEQAvgA8A/omAL4D+ggALAPv+4beLgDCACQAC//v9 +27GJgDCABgAF//v927CIgC+A/oIAAgAI//v+4beKgDCA/gD/Cv/7/NmviIAugA7/+/zZroeAK4AR +//v82K6HgCiAFP/7/Nmuh4AlgBf/+/vZroeAIoAa//v72a6HgB+AHf/7+9arhYAcgCD/+/rVq4WA +GYAj//v72a6GgBaAJv/7+tSphIATgCn/+/nTqYSAEIAs//v506iEgA2AL//7+dKohIAKgDL/+/jS +p4SAB4A1//v62a6FgASAOP/8+NCagAKAOP/84aqCgAKANf/8+cuVgAWAMv/7/uGzhoAHgDD//OW3 +jIAKgCz/+/7gupKADYAp//v41K2JgBCAJf/6+t29nYKAE4Ah//r33L6eg4AXgBz/+vngxqySgByA +Fv/4+eXQvKiTgYAggA7/9/zt3s+/sKGOgCeA8Pfw7ebj3djRx760qaCWjIB/AW6A/YkAgDqAAwA3 +gP2BqgAEADSA/YGAAAcAMYD9gYAACgAtgP2BgwAOACyAEgAlgPyBgoAAFQAggPyBgIgAGgAcgP2C +jgAfABOA+oGAgoOqACUACoD6gYCAg4gAfwEvAH8QAAAU//v+xGYQACUAE//9uiUAKAAU//vjjzoB +ACUAF//74o45AQAiABr/++GNNwEAHwAd//vgjDYBABwAIP/834o1ABoAI//74ZE8AQAWACb//N2I +MgAUACn//NyHMQARACz/++CRPAEADQAv//zahC8ACwAy//zfkTwACAA1//zXgiwABQA4//zWgSsA +AgA7//vdiCoA/z3//tT/fwe9//3ymf86//vVag0A/zf/++2ZPAEAAQA1//vzokcDAAQAMv/776dX +CgAHAC//+9uOQQQACgAr//vzt3UpAA4AJ//687d4OAQAEQAi//n+2aVxOQQAFQAd//n93at3Qg8A +GgAX//j40qqCWDEJAB8AD//29ta4m31ePyEDACUA7+7l3c/Lu7aqnIZyX0w4JQ8AfwEvAH8QAAB/ +BAAA/YCDADwAAoD9gYAAOQAGgP6DADYACoA0AAyA/oMAMAAPgP6DAC0AEYD9gYAAKgAVgP6DACcA +GID+gwAkABqA/YGEACEAH4AfACCAHgAegCAAHID+hQAgAByAIgAagCQAGYAlABeAJwAVgP6DACcA +FYApABKA/oEAKgARgP6FACsAEIAuAA+ALwAOgDAAC4D+hAAxAAqANAAHgP2BgAA0AAaA/qoANgAD +gP2BgAA4AAGA/oEAOwD+ggB/BD4AfxAAAH8EAAD9fikAPAAB//zTfSgAOQAE//zRfCcANgAH//zV +gCgAMwAK//zVgCcAMAAN//zVgCcALQAQ//zNdyIAKgAT//zLdiEAJwAW//zVgCUAJAAY//v+yXMf +ACEAG//7/sdyHgAeAB3//P6JAgAdABz//ehGAB8AG//9uBcAIAAZ//z7gAIAIQAY//3aNAAjABf/ +/aoQACQAFf/98lwAJgAU//3MJQAnABL//P6LBgAoABH//ehHACoAEP/9uBcAKwAO//z5dAEALAAN +//3aNAAuAAv//PR6CAAvAAn//P6kGwAxAAj//cs6ADMABv/81lsCADQABP/81V4DADYAAv/80lUC +ADgA+/66TQEAOgD+KwB/BD4AfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoA +AH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/AtgA+huGqoUiADgA/Sfr/wH//PyoMgA2AP6w/wX//btFADQA/un/B//8zlkEADEA +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 +ADwAAoA1AAGA+oGAgIEAgAGA/oYALQABgP6BgAeA/gCAAoD+hwAlAAGAAYEMgPyBAACABIAfAPuZ +gIGBgBGAAgAGgBgA/IuCgYAYgAIABoD+kgAQAPyAgoGAHYADAAiACgD9gIKAI4D+ggACAAiA/qoA +AgD+h4AqgAQACYD+gYAtgP6DAAMAOYAFADmABQA4gAYAOIAGAP7GgCSA+YebsMXWh4AJgAcA/f/B +gB2A+Yidssfc8f8C//7HgAqABwAB//68gBaA+IiZrsTZ7v7/Bv/9+YuACYAIAAL//rqAD4D5iJ2z +yN3z/w3//r2ACoAIAAL//f60gAiA+Yyis8jd9P8S//30hoAJgAkAA//9/rGAAYD5jKK3zOH5/xj/ +/rSACYAKAAT/+/3W5/v/Hf/97YKACYAKACf//quACYALACb//uaACYD+gwAKACb//qKACYAMACX/ +/t+ACYD+hAALACT//f6bgAmADQAk//7VgAqADQAj//39k4AJgA4AI//+y4AKgA4AIv/9+46ACYAP +ACL//sKACoAPACH//feIgAmAEAB/EAAAfwfAAP4hAD0A/eEfADwA/P/aGAA0APQaRG+ZxFUA///S +EwAtAPkaRG+ZxPP/Av/82AQA/wH//c8RACUA+AQiTXeizPX/CP/8UQAA/wL//cYMAB4A+AUiTXei +zPf/Df/7yQEAAP8D//28CAAXAPgLM12HsNv8/xP//kAAAQAF//25BwAQAPgOM1WAqtX9/xj//rUA +AgAG//2sBAAJAPkSPWaQuuP/Hv/9/S8AAgAH//2qAwACAPkRPGaIs93/JP/+owADAAj/+qJvmcPt +/yn//fkhAAMAOP/+kgAEADf//fIWAAQAN//+gAAFADb//eoOAAUANv/+bgAGADX//d4GAAYANf/+ +WgAHADT//dECAAcANP/+SAAIADP//sEACQAy//3+OAAJADL//q0ACgAx//38KQAKADH//pwACwAw +//33HQALADD//okADAAv//3vEgAMAC///ngADQAu//3lCgANAC7//mQADgAt//3YBAAOAC3//lIA +DwB/EAAAfxAAAH8QAAB/EAAAfwbzAP4aAD0A/aFpADwA/Mn+YwA7APvv//xYADkA/hj/Af/9+k0A +OAD+P/8C//35SQA3AP5m/wP//fU/ADYA/o3/BP/98TYANQD+tP8F//3wMwA0AP7b/wb//eorADIA +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 +/kr/H/8dAP4n/x//HQD9Bvz/Hv8eAP7g/x7/HgD+vf8e/x4A/pr/Hv8eAP53/x3/APIh//5yABsA +IP/95AkAGwAg//5gABwAH//91wQAHAAf//5OAB0AHv/9yAEAHQAe//5AAB4AHf/+swAfABz//f0w +AB8AHP/+oQAgABv//fggACAAG//+jgAhABr//fIWACEAGv/+fQAiABn//ekNACIAGf/+awAjABn/ +/j8AIwAZ//7CACMAGv/+RAAiABr//scAIgAb//5MACEAG//90gIAIAAc//5UACAAHP/92AMAHwAd +//5cAB8AHf/92wUAHgAe//5kAB4AHv/94QcAHQAf//5sAB0AH//95goAHAAg//51ABwAIP/97A4A +GwAh//59ABsAIf/98BIAGgAi//6EABoAIv/99BYAGQAj//6NABkAI//99xwAGAAk//6UABgAJP/9 ++SAAFwAl//6dABcAJf/9/CgAFgAm//6lABYABP/82b3s/x3//f0sABUAA//12BgAABE7bpnD9/8Y +//6tABUAAv/92BkABgD4BCpVf7Ld/v8S//3+NgAUAAH//dkaAA0A+RA7ZpDD9P8O//61ABQA/P/a +GgAUAPkZTH+q1P3/Cf/+PgATAP3aGwAaAPkNM12Qu+v/BP/+wgATAP4fACEA9xlEbqHU/P9CADsA +/Ak0OAB/A1MAIf/+uYAJgBEAIP/98oSACYARACD//rCACYASAB///euCgAmAEgAf//6ngAmAEwAe +//7kgAmA/oMAEgAe//6ggAmAFAAd//7ZgAqAFAAc//3+mIAJgBUAHP/+0IAKgBUAG//9/JCACID+ +gQAVABv//seACYD+kgAVABr//fmLgAmAFwAa//6+gAqAFwAZ//30hoAJgBgAGf/+tYAJgBkAGf/+ +n4AJgBkAGf/+4YAKgBgAGv/+ooAJgBgAGv/+44AKgBcAG//+poAJgBcAG//96YGACYAWABz//qqA +CYAWABz//eyBgAmAFQAd//6ugAmAFQAd//3tgoAJgBQAHv/+soAJgBQAHv/98IOACID+ggASAB// +/raACYATAB///fOFgAmAEgAg//66gAmAEgAg//32h4AJgBEAIf/+voAJgBEAIf/9+ImACYAQACL/ +/sKACYAQACL//fqLgAiA/oEADgAj//7GgAmADwAj//37joAIgP6BAA0AJP/+yoAKgA0AJP/9/JCA +CID+gQAMACX//s6ACoAMACX//f6UgAiA/oEACwAm//7SgAmA/pIACgAE//zs3vb/Hf/9/paACID+ +gQAKAAP/9eyMgICInbfM4fv/GP/+1oAKgAoAAv/97IyABoD4gpWqv9nu/v8S//3+m4AIgP6BAAkA +Af/97I2ADYD5iJ2zyOH6/w7//tqACYD+iQAIAPz/7Y2AFID5jKa/1er+/wn//p+ACYAJAP3tjYAa +gPmGma7I3fX/BP/+4YAKgAgA/o+AIYD3jKK30Or+/6GACYAIACiA/ISanIAJgP6GAAYAN4AHADiA +BgA4gAYACID+gYAtgP6EAAQACIACAPyqgIGAKYAFAAaA/oIACAD9gIKAJID+gwADAAWA/oIADwD9 +gIGAH4AEAASA/oIAFQD9gIKAG4ADAASAHQABgP6BgBSAAwACgP6CACIA/JmCgYAPgP6CAAEAAYD+ +ggApAA6AAgABgDAA/KqAgYAFgPuCAACCADYA/YiCgAGAAQB/EAAALP/9ygEADwAs//5CABAAK//+ +twARACr//f4yABEAKv/+pQASACn//fojABIAKf/+kwATACj//fMYABMAKP/+gAAUACf//esOABQA +J//+bwAVACb//d8HABUAJv/+XAAWACX//dICABYAJf/+SgAXACT//sEAGAAk//6FABgAJP/98BIA +FwAl//6FABcAJf/98xYAFgAm//6MABYAJv/99xwAFQAn//6VABUAJ//9+iIAFAAo//6dABQAKP/9 +/CgAEwAp//6lABMAKf/9/S8AEgAq//6tABIAKv/9/jYAEQAr//61ABEALP/+PgAQACz//r4AEAAt +//5CAA8ALf/9ygEADgAu//5LAA4ALv/9zQEADQAv//5TAA0AL//91AIADAAw//5bAAwAMP/92gQA +CwAx//5jAAsAMf/94QcACgAy//5rAAoAMv/95goACQAz//5zAAkAM//96w0ACAA0//58AAgANP/9 +8BIABwA1//6DAAcANf/98xUABgA2//6LAAYANv/99hoABQA3//6UAAUAB//66nefzPf/Kf/9+R8A +BAAG//3uMgABAPgDIk2AqtX+/yT//psABAAF//3vMwAIAPkOM16Ru+z/H//9/CcAAwAE//3tMQAO +APgBIlF+q9r9/xr//qQAAwAD//3vNQAVAPkGK16Is+j/Ff/9/S4AAgAC//3vNAAcAPkcSnem0/r/ +EP/+rQACAAH//fA3ACIA+QUrVYCz3f8L//3+NQABAPz/8TcAKQD5EDxmkcT1/wb//rQAAQD99D4A +LwD4AyJNgKrV/v8B//s9AAA7ADYA+g89apiFAAAAfxAAAH8DPwD+gAA7AAKAOgAEgDgABoA2AAiA +NAD+goAIgDMAC4A0AAqANgD+mYAGgDgA/ZmBgAOAOgD9gIGAAYA8APyZgIAAPQD+gAB/Cb8AfxAA +AH8DPwD+FgA7APwglvgAOQD6IpH4//8ANwD8LKL7/wL/NgD8NK/+/wT/NAD8O7P+/wb/MwD9Mtz/ +CP80APwEYt3/Bv82APwFXtv/BP84APwFZeD/Av86APoGZ+H//wA7APwFXt0APQD+BgB/Cb8ALAD+ +Jf8Q/ywA/mP/EP8qAP07sv8R/ygA/Tu9/xP/JQD8AUzK/xX/IwD8AkzN/xf/IQD8BV3Y/xn/HwD8 +Bl3b/xv/HQD8C27k/x3/GwD8DW7n/x//GQD8E3/u/yH/FwD8FX/w/yP/FQD8HpD2/yX/EwD8I5z5 +/yf/EQD8KqH7/yn/DwD8LqH8/yv/DQD8ObT+/y3/CwD9O7L/MP8KAP6H/zL/CwD9Q8T/MP8NAP07 +vv8u/w8A/UfH/yz/EQD9Scj/Kv8TAP1Eyf8o/xUA/UTK/yb/FwD9RMr/JP8ZAP1Ey/8i/xsA/UTM +/yD/HAD8AUzN/x7/HgD8AUzN/xz/IAD8AUzO/xr/IgD8AUzP/xj/JAD8AkzQ/xb/JgD8AlXX/xT/ +KAD8AlXY/xL/KgD8A13h/xD/LAD+f/8Q/ywA/lz/EP8sAP45/xD/LAD+Fv8Q/y0A/vH/D/8tAP7P +/w//LQD+q/8P/y0A/oj/D/8tAP5m/w//LQD+Qv8P/y0A/h//D/8tAP0C+P8O/y4A/tn/Dv8uAP61 +/w7/LgD+kv8O/y4A/m//Dv8uAP5M/w7/LgD+Kf8O/y4A/Qf9/w3/LwD+4f8N/y8A/r7/Df8vAP6b +/w3/LwD+ef8N/y8A/lb/Df8vAP4y/wz//uUALgD+Dv8L//3pKgAvAP7r/wn//egpADAA/sn/CP/9 +6iwAAAAXABSA/pL/EP8VABaA/rH/EP8TAP6CgBSA/Z3Z/xH/EQAWgP2d3v8T/w8AFoD9puX/Ff8M +AP2AgYATgPyBpub/F/8KAP2AgYATgPyCruz/Gf8IABaA/IOu7f8b/wYA/pKAFID8hbfy/x3/BAD9 +gIGAE4D8hrfz/x//AgD9iYGAE4D8ib/3/yH//gCAFYD8ir/4/yP/FYD8j8j7/yX/E4D8kc78/yf/ +EYD8ldD9/yn/D4D8l9D+/yv/DYD8nNr+/y3/C4D9ndn/MP8KgP7D/zL/C4D9oeL/MP8NgP2d3/8u +/w+A/aPj/yz/EYD9pOT/Kv8TgP2i5P8o/xWA/aLl/yb//gCAFYD9ouX/JP8CABaA/aLl/yL/BAAW +gP2i5v8g/wYAFoD9pub/Hv8IAP6SgBSA/abm/xz/CgD9gIGAE4D9puf/Gv8MAP2LgYATgP2m5/8Y +/w4A/YuBgBKA/IGm6P8W/xAA/YuBgBKA/IGq6/8U/xIA/YuBgBKA/IGq7P8S/xQAFYD8ga7w/xD/ +FgD9gIGAEoD+v/8Q/xgA/YCBgBCA/q7/EP8aAP2JgYAOgP6c/xD/HAD+h4ANgP6L/xD/HgD9iYGA +C4D++P8P/yAADID+5/8P/yIA/oaACID+1f8P/yMACYD+xP8P/yMA/oGAB4D+s/8P/yMACYD+of8P +/yMACYD+j/8P/yMACYD9gfz/Dv8kAAmA/uz/Dv8kAAmA/tr/Dv8kAAmA/sn/Dv8kAAmA/rf/Dv8k +AAmA/qb/Dv8kAAmA/pT/Dv8kAP6EgAeA/YP+/w3/JAAKgP7w/w3/JQAJgP7f/w3/JQAJgP7N/w3/ +JQAJgP68/w3/JQD+gYAHgP6r/w3/JQAJgP6Z/wz//vIAJAD+g4AHgP6H/wv//fSVACQACoD+9f8J +//z0lIAAJQAJgP7k/wj//fWWgACAfxAAABcA/Cyi+/8j/xUA/DSv/v8l/xMA/Duz/v8n/xEA/Tyz +/yr/DwD9RMf/LP8MAPwCTcv/Lv8KAPwCVdb/MP8IAPwGXtn/Mv8GAPwHZuL/NP8EAPwMb+X/Nv8C +APwNd+3/OP/7ABSA7/86//2I9f9/Av3//V7d/zz/+wAGZuP/Ov8CAPwGZuT/OP8EAPwGZuT/Nv8G +APwGZuX/NP8IAPwHZuX/Mv8KAPwKb+b/MP8MAPwLb+f/Lv8OAPwLb+f/LP8QAPwLb+j/Kv8SAPwL +b+j/KP8UAPwOfO3/Jv8WAPwMd+7/JP8YAPwMd+7/Iv8aAPwNd+7/IP8cAPwRgvH/Hv8eAPwNd+// +HP8gAPwSgPD/Gv8iAP0T0/8Z/yMA/qD/Gf8jAP59/xn/IwD+Wv8Z/yMA/jb/Gf8jAP4U/xn/JAD+ +7/8Y/yQA/s3/GP8kAP6q/xj/JAD+h/8Y/yQA/mT/GP8kAP5A/xj/JAD+Hf8Y/yQA/QL3/xf/JQD+ +1v8X/yUA/rP/F/8lAP6Q/xf/JQD+bf8X/yUA/kr/F/8lAP4n/xf/JQD9Bvz/Fv8mAP7g/xb/Kv/9 +9hsAEQAq//6FABIAKf/97hEAEgAp//5yABMAKP/95AkAEwAo//5gABQAJ//91wQAFAAn//5OABUA +Jv/9yAEAFQAm//5AABYAJf/+sgAXACT//f0vABcAJP/+oAAYACP//fgfABgAI//+jgAZACL//fIW +ABkAIv/+fQAaACH//ekNABoAIf/+awAbACH//kAAGwAh//7DABsAIv/+RAAaACL//scAGgAj//5M +ABkAI//90gIAGAAk//5UABgAJP/92AQAFwAl//5dABcAJf/93wYAFgAm//5lABYAJv/94QcAFQAn +//5tABUAJ//95woAFAAo//51ABQAKP/97A4AEwAp//59ABMAKf/98BIAEgAq//6FABIAKv/99BcA +EQAr//6OABEAK//99xwAEAAs//6VABAALP/9+SAADwAt//6eAA8ALf/9/CgADgAu//6lAA4ADP/8 +2bzr/x3//f0tAA0AC//11xgAABE7bpnD9v8Y//6tAA0ACv/92BkABgD4BCJMf7Ld/v8S//3+NgAM +AAn//dkaAA0A+Q87ZpDD9P8O//62AAwACP/92hoAFAD5GUx3odT9/wn//j4ACwAH//3aGwAaAPkN +M12Qu+r/BP/+wgALAAb//dsbACEA9xlEbqHM+f9DAAoABf/93B0AJwD8CTM4AAoABP/94SEANwAD +//3fHwA4AAL//eAgADkAAf/94iIAOgD8/+MjADsA/ecpADwA/iYAfwD+ACr//fuNgAmABwAq//7C +gAqABwAp//33iIAJgAgAKf/+uYAJgAkAKP/98oSACYAJACj//rCACYAKACf//euCgAiA/oIACQAn +//6ngAmACwAm//7kgAmA/oMACgAm//6ggAmADAAl//7ZgAmA/oUACwAk//3+l4AJgA0AJP/+0IAK +gA0AI//9/I+ACID+gQANACP//seACYD+kgANACL//fmLgAmADwAi//6+gAqADwAh//30hoAIgP6B +AA8AIf/+tYAJgBEAIf/+oIAJgBEAIf/+4YAKgBAAIv/+ooAJgBAAIv/+44AKgA8AI//+poAJgA8A +I//96YGACYAOACT//qqACYAOACT//eyCgAmADQAl//6ugAmADQAl//3vg4AJgAwAJv/+soAJgAwA +Jv/98IOACID+ggAKACf//raACYALACf//fOFgAmACgAo//66gAmACgAo//32h4AJgAkAKf/+voAJ +gAkAKf/9+ImACID+gQAHACr//sKACYAIACr//fqLgAiA/oEABgAr//7HgAmABwAr//37joAIgP6B +AAUALP/+yoAKgAUALP/9/JCACYAFAC3//s+ACoAEAC3//f6UgAmABAAu//7SgAmA/pIAAgAM//zs +3vX/Hf/9/paACYADAAv/9euMgICInbfM4fv/GP/+1oAKgAIACv/97IyABoD4gpGmv9nu/v8S//3+ +m4AJgAIACf/97I2ADYD5h52zyOH6/w7//tuACYD8iQAA/wf//e2NgBSA+Yymu9Dq/v8J//6fgAmA +AQAH//3tjYAagPmGma7I3fX/BP/+4YAKgP4A/wX//e2NgCGA94yit9Dm/P+hgAmA/gD/BP/97o6A +J4D8hJmcgAmA/ob/A//98JCAN4AD//3vj4A4gAL//fCQgDmAAf/98ZGAOoD8//GRgAuA/oIAAQD8 +qoCBgCeA/fOUgAuA/oIACAD9gIKAIoD+k4AMgBAAAYD+gYAogP6CABUA/YCCgCOA/oIAHAD8hICB +gByAIwD8gIKBgAuAfxAAADb//mQABgA1//3YBAAGADX//lIABwA0//3KAQAHADT//kIACAAz//62 +AAkAMv/9/TEACQAy//6kAAoAMf/9+iMACgAx//6SAAsAMP/98xcACwAw//6AAAwAL//96w4ADAAv +//5vAA0ALv/93wcADQAu//5cAA4ALf/90QIADgAt//5JAA8ALP/+wQAQACz//oUAEAAs//3wEgAP +AC3//oYADwAt//3zFgAOAC7//o0ADgAu//33HAANAC///pUADQAv//36IgAMADD//p0ADAAw//38 +KAALADH//qUACwAx//39LwAKADL//q4ACgAz//42AAkAM//+tgAJADT//j4ACAA0//6/AAgANf/+ +QwAHADX//coBAAYANv/+SwAGADb//c4BAAUAN//+UwAFADf//dQCAAQAOP/+XAAEADj//dsEAAMA +Of/+ZAADADn//eEHAAIAOv/+bAACADr//eYKAAEAO//+dAABADv/++sNAAD/O//8fAAA/zv//PAS +AP88//2DAP88//3zFf89//6M/z3//vb/Tv/66naezPf/OP/96i0AAQD4AyJNgKrV/f8x//3uMwAI +APkOM16Ru+v/K//97TAADgD4ASJQfavZ/P8k//3vNQAVAPkGK16Is+j/Hv/97zMAHAD5G0h3pdL6 +/xf//fA2ACIA+QQrVYCz3f8I/38QAAB/DcAA/oAAPQD+gAA9AP2AhAA8AAGAPQABgP6DADsAAoA8 +AAOAOwADgDsAA4D+ggA5AH8QAAB/DcAA/hoAPQD+lQA9AP35HwA8AP3/nAA8APz//CcAOwAB//6l +ADsAAf/9/S4AOgAC//6tADoAAv/9/jUAOQB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAKAD+PP8E//3vNAA1AP4Z/wP//fA1ADYA/QH0/wH//fA2ADgA+tL///A3 +ADkA+6//8TgAOgD8jPQ+ADsA/Vw7AH8OUwAeAAmA/p7/BP/995qADIAeAP6CgAeA/oz/A//9+JqA +C4D+gQAeAAqA/vr/Af/9+JuADIAhAAmA+un///ibgAuA/oEAIQAJgPvX//icgAyAIwAJgPzG+p+A +C4D+gQAjAAmA/a6dgAyAJQAXgP6BACUAF4AnAP6FgBOA/oEAKAAUgCoAE4ArABGA/oEAKwARgC0A +/oGADoAuAA+ALwD+g4ALgP6BAC8A/qqACoD+gQAxAAqA/oEAMgAKgDQACYA1AP6BgAaANgAHgDcA +/oKAA4D+gQA3AAWAOgADgDsAAYD+gQA7AAGAPQD+gAB/CNsAfxAAAB4A/lT/HP/99UAAHQD+Mf8b +//31QQAeAP4O/xr//fVCACAA/ur/GP/99kMAIQD+x/8X//34SgAiAP6k/xb//flLACMA/oD/Ff/9 +90gAJAD+Xv8U//35TQAlAP46/xP//flOACYA/hf/Ev/9+k8AKAD+8v8Q//36UAApAP7R/w///fxY +ACoA/q3/Dv/9/FkAKwD+iv8N//38WgAsAP5n/wz//fxYAC0A/kT/C//9/FwALgD+If8K//39XQAv +AP0D+f8I//39XwAxAP7a/wf//f5nADIA/rf/Bv/9/mgAMwD+lP8F//3+agA0AP5x/wT//f5qADUA +/k7/A//9/mwANgD+K/8C//3+bQA3AP0I/f8B//52ADkA++T//3gAOgD8wf95ADsA/Z56ADwA/h4A +fwjbAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAMAD+pf8H//3qLQAyAP6C/wb//est +ADMA/l//Bf/97C8ANAD+PP8E//3vNAA1AP4Z/wP//e81ADYA/QH0/wH//fA2ADgA+tL///A2ADkA ++6//8TcAOgD8jPQ+ADsA/Vs7AH8NiwAmAAmA/tL/B//99ZaAAYAmAAmA/sH/Bv/99ZaAAoAmAAmA +/q//Bf/99peAA4AmAAmA/p7/BP/995qABIAmAP6CgAeA/oz/A//995qABYAmAP6JgAiA/vr/Af/9 ++JuABoAnAAmA+un///ibgAeAJwAJgPvX//ibgAiAJwAJgPzG+p+ACYAnAAmA/a2dgAqAJwD+gYAV +gCcAF4AnAP6FgBSAKQAUgCoAEoD+gQAqABKALAARgC0A/oGADYD+gQAtAA+ALwD+g4ALgP6BAC8A +/qqAC4AyAAqA/oEAMgAKgDQACID+gQA0AP6BgAaANgAGgP6BADYABoA4AAWAOgACgP6BADoAAoA8 +AAGAPQD+hAB/CBMAfxAAACYA/r3/Fv8mAP6a/xb/JgD+dv8W/yYA/lT/Fv8mAP4x/xb/JgD+Df8W +/ycA/ur/Ff8nAP7H/xX/JwD+pP8V/ycA/oD/Ff8nAP5d/xT//vkAJgD+Ov8T//35TgAmAP4X/xL/ +/flOACgA/vL/EP/9+lAAKQD+0P8P//38VwAqAP6t/w7//fxYACsA/or/Df/9/FoALAD+Z/8M//38 +VwAtAP5E/wv//fxcAC4A/iH/Cv/9/F0ALwD9A/n/CP/9/V4AMQD+2v8H//3+ZwAyAP63/wb//f5o +ADMA/pT/Bf/9/mkANAD+cf8E//3+agA1AP5O/wP//f5rADYA/ir/Av/9/mwANwD5CP3///5uADkA +++T//3cAOgD8wf94ADsA/Z16ADwA/h0AfwgTAH8QAAAJgP6CACkAE4AwAPyqgIGACYA2AAeANwAF +gP6BADcABID+gQA4AASAOgACgP6BADoAAYD+gQA7AP2AgQA8AP6BAH8NfgB/EAAACP/98TcAKQD5 +EDxmkcT0/wr//fQ+AC8A+gMiTYCq/wX//fI6ADUABf/99UAANgAE//31QQA3AAP//fVBADgAAv/9 +9UIAOQAB//32QwA6APz/+EsAOwD990cAPAD+TQB/DX4AfxAAAASAOgAFgDoA+oiAgYCAAH8PeQB/ +EAAAA//+tAA5AP3V/f8B//4+ADkA+g88aZiEAH8PeQB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoA +AH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAA +fwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/ +CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8K +AAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoA +AH8GQAB/BkAAfwZAAH8GQAAAAAH0AAAB9AAAAAAAAAD6AAAA+gAAAAAAAAB9AAAAfQAAAAAAAAA+ +AAAAPgAAAAAAAAPoAAAD6AAAAAEAAAAHU2xpZGUzAAAAAAYAAAAEAAAA/wAAAAgAAAAEAAAAAQAA +AAkAAAAEAAAAAAAAABwAAAAEAAAAAAAAAAoAAAAEAAAAAAAAAAsAAAAEAAAAAAAAAAwAAAAEAAAA +AAAAAA0AAAAEAAAAAAAAAA8AAAAIAAAAAAAAAAAAAAAHAAAABAAAAAAAAAAUAAAABAAAAAIAAAAA +AAAAAAAA7hEAAAAAAAAD6AAAA+gAAAAEAADuNQABEWYAARFyAAERfgABEYoAAAAAAAAD6AAAA+gA +APJBAADyUQAA8mEAAPJxAADygQAA8pEAAPKhAADysQAA8sEAAPLRAADy4QAA8vEAAPMBAADzEQAA +8yEAAPMxAADzQQAA81EAAPNhAADzcQAA84EAAPORAADzoQAA87EAAPPBAADz0QAA8+EAAPPxAAD0 +AQAA9BEAAPQhAAD0MQAA9EEAAPRRAAD0YQAA9HEAAPSBAAD0kQAA9KEAAPSxAAD0wQAA9NEAAPTh +AAD08QAA9QEAAPURAAD1IQAA9TEAAPVBAAD1UQAA9WEAAPVxAAD1gQAA9ZEAAPWhAAD1sQAA9cEA +APXRAAD14QAA9fEAAPYBAAD2EQAA9iEAAPYxAAD2QQAA9lEAAPZhAAD2cQAA9oEAAPaRAAD2oQAA +9rEAAPbBAAD20QAA9uEAAPbxAAD3AQAA9xEAAPchAAD3MQAA90EAAPdRAAD3YQAA93EAAPeBAAD3 +kQAA96EAAPexAAD3wQAA99EAAPfhAAD5QgAA+VwAAPl2AAD5kAAA+pgAAPqoAAD6uAAA+sgAAPrY +AAD66AAA+vgAAPsIAAD7GAAA+ygAAPs4AAD7SAAA/hAAAP4gAAD+MAAA/kAAAQBIAAEAWAABAGgA +AQB4AAEAiAABAJgAAQCoAAEAuAABAMgAAQDYAAEA6AABAPgAAQPAAAED0AABA+AAAQPwAAEF+AAB +BggAAQYYAAEGKAABBjgAAQZIAAEGWAABBmgAAQZ4AAEGiAABBpgAAQaoAAEInAABCLYAAQjQAAEI +6gABClYAAQpmAAEKdgABCoYAAQqWAAEKpgABCrYAAQrGAAEK1gABCuYAAQr2AAELBgABCxYAAQsm +AAELNgABC0YAAQtWAAELZgABC3YAAQuGAAELlgABC6YAAQu2AAELxgABC9YAAQvmAAEL9gABDAYA +AQwWAAEMJgABDDYAAQxGAAEMVgABDGYAAQx2AAEMhgABDJYAAQymAAEMtgABDMYAAQzWAAEM5gAB +DPYAAQ0GAAENFgABDSYAAQ02AAENRgABDVYAAQ1mAAENdgABDYYAAQ2WAAENpgABDbYAAQ3GAAEN +1gABDeYAAQ32AAEOBgABDhYAAQ4mAAEONgABDkYAAQ5WAAEOZgABDnYAAQ6GAAEOlgABDqYAAQ62 +AAEOxgABDtYAAQ7mAAEO9gABDwYAAQ8WAAEPJgABDzYAAQ9GAAEPVgABD2YAAQ92AAEPhgABD5YA +AQ+mAAEPtgABD8YAAQ/WAAEP5gABD/YAARAGAAEQFgABECYAARA2AAEQRgABEFYAARBmAAEQdgAB +EIYAARCWAAEQpgABELYAARDGAAEQ1gABEOYAARD2AAERBgABERYAAREmAAERNgABEUYAARFWAAAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8ISwA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0 +/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/ +CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/38QAAB/EAAAfwhLAP4HCjIKCgD+WYAygAoA/lmA +MoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAy +gAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKA +CgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAK +AP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKAfwhAAH8HwP9/EAAAfxAAAH8IQAA/Cn8HgIB/CEAA +fwfA/38QAAB/EAAAfwhAAD8KfweAgH8IQAB/B8D/fxAAAH8QAAB/CEAAPwp/B4CAfwhAAAP/OwAD +/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/ +OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87 +AAP/OwB/EAAAfxAAAH8IQAADCjsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsA +A4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwAD +gDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAAKADT/CgA0/woANP8KADT/CgA0/woANP8K +ADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woA +NP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0 +/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/ +CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8K +ADT/fxAAAH8QAAAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5Z +gDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmA +MoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAy +gAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKA +CgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAK +AP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA +/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+ +WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5Z +gDKAfxAA/38QAAB/EAAAfxAAgH8QAP9/EAAAfxAAAH8QAIB/EAD/fxAAAH8QAAB/EACAA/87AAP/ +OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87 +AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsA +A/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD +/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/ +OwAD/zsAA/87AAP/OwAD/zsAA/87AH8QAAB/EAAAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7 +AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsA +A4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwAD +gDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOA +OwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7 +AH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAACgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0 +/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/ +CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8K +ADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woA +NP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/38QAAB/EAAACgD+WYAygAoA/lmAMoAK +AP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA +/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+ +WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5Z +gDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmA +MoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAy +gAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKA +CgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAK +AP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygH8QAP9/EAAAfxAAAH8QAIB/EAD/fxAA +AH8QAAB/EACAfxAA/38QAAB/EAAAfxAAgAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsA +A/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD +/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/ +OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87 +AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwB/EAAA +fxAAAAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwAD +gDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOA +OwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7 +AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsA +A4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAAoANP8KADT/CgA0/woANP8KADT/ +CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8K +ADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woA +NP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/CgA0/woANP8KADT/fwUAAH8QAAB/EAAACgD+ +WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5Z +gDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmA +MoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAy +gAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKA +CgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAKAP5ZgDKACgD+WYAygAoA/lmAMoAK +AP5ZgDKACgD+WYAygAoA/iY3Mjd/BQAAfwsA/38FAAB/EAAAfxAAAH8KwIA/N38FAAB/CwD/fwUA +AH8QAAB/EAAAfwrAgD83fwUAAH8LAP9/BQAAfxAAAH8QAAB/CsCAPzd/BQAAA/87AAP/OwAD/zsA +A/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD +/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/ +OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/OwAD/zsAA/87AAP/fwU8AH8QAAB/ +EAAAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOA +OwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7 +AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsAA4A7AAOAOwADgDsA +A4A7AAM3fwU8AH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwoAAH8KAAB/CgAAfwoAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8K +AAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoA +AH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAA +fwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/ +CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/BkAAfwZAAH8GQAB/BkAAAAAB9AAA +AfQAAAAAAAAA+gAAAPoAAAAAAAAAfQAAAH0AAAAAAAAAPgAAAD4AAAAA + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/gimp/ba387a2bf0dfa5d22b061bfbe6fae05b.msg b/share/extensions/tests/data/cmd/gimp/ba387a2bf0dfa5d22b061bfbe6fae05b.msg new file mode 100644 index 0000000..e6bcb22 --- /dev/null +++ b/share/extensions/tests/data/cmd/gimp/ba387a2bf0dfa5d22b061bfbe6fae05b.msg @@ -0,0 +1,2918 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: gimp +Arguments: - --batch-interpreter=plug-in-script-fu-eval -b -i + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +V2VsY29tZSB0byBUaW55U2NoZW1lLCBWZXJzaW9uIDEuNDAKQ29weXJpZ2h0IChjKSBEaW1pdHJp +b3MgU291ZmxpcwoKdHM+IApHaXZlczogMAp0cz4gCkV2YWw6IChkZWZpbmUgKHBuZy10by1sYXll +ciBpbWcgcG5nX2ZpbGVuYW1lIGxheWVyX25hbWUpIChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5n +LWxvYWQgUlVOLU5PTklOVEVSQUNUSVZFIHBuZ19maWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBu +Z19sYXllciAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5 +ZXIgKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAo +Z2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0 +LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpKSkKRXZhbDogKGxhbWJkYSAoaW1nIHBuZ19maWxl +bmFtZSBsYXllcl9uYW1lKSAobGV0KiAoKHBuZyAoY2FyIChmaWxlLXBuZy1sb2FkIFJVTi1OT05J +TlRFUkFDVElWRSBwbmdfZmlsZW5hbWUgcG5nX2ZpbGVuYW1lKSkpIChwbmdfbGF5ZXIgKGNhciAo +Z2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIHBuZykpKSAoeGNmX2xheWVyIChjYXIgKGdpbXAt +bGF5ZXItbmV3LWZyb20tZHJhd2FibGUgcG5nX2xheWVyIGltZykpKSkgKGdpbXAtaW1hZ2UtYWRk +LWxheWVyIGltZyB4Y2ZfbGF5ZXIgLTEpIChnaW1wLWRyYXdhYmxlLXNldC1uYW1lIHhjZl9sYXll +ciBsYXllcl9uYW1lKSkpCkFwcGx5IHRvOiAoKChpbWcgcG5nX2ZpbGVuYW1lIGxheWVyX25hbWUp +IChsZXQqICgocG5nIChjYXIgKGZpbGUtcG5nLWxvYWQgUlVOLU5PTklOVEVSQUNUSVZFIHBuZ19m +aWxlbmFtZSBwbmdfZmlsZW5hbWUpKSkgKHBuZ19sYXllciAoY2FyIChnaW1wLWltYWdlLWdldC1h +Y3RpdmUtbGF5ZXIgcG5nKSkpICh4Y2ZfbGF5ZXIgKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1k +cmF3YWJsZSBwbmdfbGF5ZXIgaW1nKSkpKSAoZ2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9s +YXllciAtMSkgKGdpbXAtZHJhd2FibGUtc2V0LW5hbWUgeGNmX2xheWVyIGxheWVyX25hbWUpKSkp +CkV2YWw6IChpZiAobWFjcm8/IGZvcm0pIChtYWNyby1leHBhbmQtYWxsIChtYWNyby1leHBhbmQg +Zm9ybSkpIGZvcm0pCkV2YWw6IChtYWNybz8gZm9ybSkKRXZhbDogbWFjcm8/CkV2YWw6IGZvcm0K +QXBwbHkgdG86ICgoKGltZyBwbmdfZmlsZW5hbWUgbGF5ZXJfbmFtZSkgKGxldCogKChwbmcgKGNh +ciAoZmlsZS1wbmctbG9hZCBSVU4tTk9OSU5URVJBQ1RJVkUgcG5nX2ZpbGVuYW1lIHBuZ19maWxl +bmFtZSkpKSAocG5nX2xheWVyIChjYXIgKGdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciBwbmcp +KSkgKHhjZl9sYXllciAoY2FyIChnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIHBuZ19sYXll +ciBpbWcpKSkpIChnaW1wLWltYWdlLWFkZC1sYXllciBpbWcgeGNmX2xheWVyIC0xKSAoZ2ltcC1k +cmF3YWJsZS1zZXQtbmFtZSB4Y2ZfbGF5ZXIgbGF5ZXJfbmFtZSkpKSkKRXZhbDogZm9ybQpHaXZl +czogcG5nLXRvLWxheWVyCnRzPiAKRXZhbDogKGxldCogKChpbWcgKGNhciAoZ2ltcC1pbWFnZS1u +ZXcgMjAwIDIwMCBSR0IpKSkpIChnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uIGltZyA5Ni4wIDk2 +LjApIChnaW1wLWltYWdlLXVuZG8tZGlzYWJsZSBpbWcpIChmb3ItZWFjaCAobGFtYmRhIChuYW1l +cykgKHBuZy10by1sYXllciBpbWcgKGNhciBuYW1lcykgKGNkciBuYW1lcykpKSAobWFwIGNvbnMg +JygiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIikgJygiU2xpZGUyIikpKSAoZ2lt +cC1pbWFnZS1yZXNpemUtdG8tbGF5ZXJzIGltZykgKGZvci1lYWNoIChsYW1iZGEgKGhHdWlkZSkg +KGdpbXAtaW1hZ2UtYWRkLWhndWlkZSBpbWcgaEd1aWRlKSkgJyg5NTEuMDIyNyA0OS4wMjQxMjgp +KSAoZm9yLWVhY2ggKGxhbWJkYSAodkd1aWRlKSAoZ2ltcC1pbWFnZS1hZGQtdmd1aWRlIGltZyB2 +R3VpZGUpKSAnKDQ2LjkzNjU3NyA5NTMuMDE2NTkpKSAoZ2ltcC1pbWFnZS1ncmlkLXNldC1zcGFj +aW5nIGltZyAxMDAgMTAwKSAoZ2ltcC1pbWFnZS1ncmlkLXNldC1vZmZzZXQgaW1nIDAgMCkgKGdp +bXAtaW1hZ2UtdW5kby1lbmFibGUgaW1nKSAoZ2ltcC1maWxlLXNhdmUgUlVOLU5PTklOVEVSQUNU +SVZFIGltZyAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIgaW1nKSkgIi90bXAvZ2lt +cC1vdXQtM3NoMjV4bmovcmVmX2d1aWRlcy5zdmcueGNmIiAiL3RtcC9naW1wLW91dC0zc2gyNXhu +ai9yZWZfZ3VpZGVzLnN2Zy54Y2YiKSkKRXZhbDogKGNhciAoZ2ltcC1pbWFnZS1uZXcgMjAwIDIw +MCBSR0IpKQpFdmFsOiBjYXIKRXZhbDogKGdpbXAtaW1hZ2UtbmV3IDIwMCAyMDAgUkdCKQpFdmFs +OiBnaW1wLWltYWdlLW5ldwpFdmFsOiAyMDAKRXZhbDogMjAwCkV2YWw6IFJHQgpBcHBseSB0bzog +KDIwMCAyMDAgMCkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWlt +YWdlLW5ldyIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChj +b25zICJnaW1wLWltYWdlLW5ldyIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1uZXci +CkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1uZXciICgyMDAgMjAwIDApKQpBcHBseSB0 +bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2ltcC1pbWFnZS1uZXci +IDIwMCAyMDAgMCkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtbmV3IiAyMDAgMjAwIDApCkFwcGx5 +IHRvOiAoKDEpKQpFdmFsOiAoZ2ltcC1pbWFnZS1zZXQtcmVzb2x1dGlvbiBpbWcgOTYuMCA5Ni4w +KQpFdmFsOiBnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uCkV2YWw6IGltZwpFdmFsOiA5Ni4wCkV2 +YWw6IDk2LjAKQXBwbHkgdG86ICgxIDk2LjAgOTYuMCkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1k +Yi1jYWxsIChjb25zICJnaW1wLWltYWdlLXNldC1yZXNvbHV0aW9uIiB4KSkKRXZhbDogYXBwbHkK +RXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2Utc2V0LXJlc29s +dXRpb24iIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtaW1hZ2Utc2V0LXJlc29sdXRpb24iCkV2 +YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1zZXQtcmVzb2x1dGlvbiIgKDEgOTYuMCA5Ni4w +KSkKQXBwbHkgdG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAt +aW1hZ2Utc2V0LXJlc29sdXRpb24iIDEgOTYuMCA5Ni4wKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFn +ZS1zZXQtcmVzb2x1dGlvbiIgMSA5Ni4wIDk2LjApCkV2YWw6IChnaW1wLWltYWdlLXVuZG8tZGlz +YWJsZSBpbWcpCkV2YWw6IGdpbXAtaW1hZ2UtdW5kby1kaXNhYmxlCkV2YWw6IGltZwpBcHBseSB0 +bzogKDEpCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS11 +bmRvLWRpc2FibGUiIHgpKQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFs +OiAoY29ucyAiZ2ltcC1pbWFnZS11bmRvLWRpc2FibGUiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdp +bXAtaW1hZ2UtdW5kby1kaXNhYmxlIgpFdmFsOiB4CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtdW5k +by1kaXNhYmxlIiAoMSkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5Mzk2MTEzMTU1 +MjQ5Nj4gKCJnaW1wLWltYWdlLXVuZG8tZGlzYWJsZSIgMSkpCkFwcGx5IHRvOiAoImdpbXAtaW1h +Z2UtdW5kby1kaXNhYmxlIiAxKQpFdmFsOiAoZm9yLWVhY2ggKGxhbWJkYSAobmFtZXMpIChwbmct +dG8tbGF5ZXIgaW1nIChjYXIgbmFtZXMpIChjZHIgbmFtZXMpKSkgKG1hcCBjb25zICcoIi90bXAv +Z2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpICcoIlNsaWRlMiIpKSkKRXZhbDogZm9yLWVh +Y2gKRXZhbDogKGxhbWJkYSAobmFtZXMpIChwbmctdG8tbGF5ZXIgaW1nIChjYXIgbmFtZXMpIChj +ZHIgbmFtZXMpKSkKQXBwbHkgdG86ICgoKG5hbWVzKSAocG5nLXRvLWxheWVyIGltZyAoY2FyIG5h +bWVzKSAoY2RyIG5hbWVzKSkpKQpFdmFsOiAoaWYgKG1hY3JvPyBmb3JtKSAobWFjcm8tZXhwYW5k +LWFsbCAobWFjcm8tZXhwYW5kIGZvcm0pKSBmb3JtKQpFdmFsOiAobWFjcm8/IGZvcm0pCkV2YWw6 +IG1hY3JvPwpFdmFsOiBmb3JtCkFwcGx5IHRvOiAoKChuYW1lcykgKHBuZy10by1sYXllciBpbWcg +KGNhciBuYW1lcykgKGNkciBuYW1lcykpKSkKRXZhbDogZm9ybQpFdmFsOiAobWFwIGNvbnMgJygi +L3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIikgJygiU2xpZGUyIikpCkV2YWw6IG1h +cApFdmFsOiBjb25zCkV2YWw6ICcoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIp +CkV2YWw6ICcoIlNsaWRlMiIpCkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCIvdG1w +L2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciKSAoIlNsaWRlMiIpKQpFdmFsOiAoaWYgKG51 +bGw/IGxpc3RzKSAoYXBwbHkgcHJvYykgKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQq +ICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChj +ZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMg +cHJvYyBjZHJzKSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlz +dHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciKSAoIlNs +aWRlMiIpKSkKRXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChh +cHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIg +dW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJz +KSkpKSkKRXZhbDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBudWxsPwpFdmFsOiAoY2FyIGxp +c3RzKQpFdmFsOiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNz +aDI1eG5qL1NsaWRlMi5wbmciKSAoIlNsaWRlMiIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1v +dXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpKQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAx +LXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29u +cyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkKRXZhbDog +KGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykKRXZhbDogYXBwbHkKRXZhbDogdW56aXAxLXdp +dGgtY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKCIvdG1wL2dpbXAtb3V0 +LTNzaDI1eG5qL1NsaWRlMi5wbmciKSAoIlNsaWRlMiIpKSkKQXBwbHkgdG86ICgoIi90bXAvZ2lt +cC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpICgiU2xpZGUyIikpCkV2YWw6ICh1bnppcDEtd2l0 +aC1jZHItaXRlcmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVy +YXRpdmUKRXZhbDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgoIi90bXAv +Z2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpICgiU2xpZGUyIikpICgpICgpKQpFdmFsOiAo +aWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNkcnMpIChsZXQgKChjYXIxIChjYWFyIGxpc3Rz +KSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgKGNkciBs +aXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkp +KSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86 +ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciKSAoIlNsaWRlMiIpKSkKRXZh +bDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAx +LXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkp +IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZhbDogY2Fh +cgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUy +LnBuZyIpICgiU2xpZGUyIikpKQpFdmFsOiAoY2FyIChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAo +Y2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC0zc2gy +NXhuai9TbGlkZTIucG5nIikgKCJTbGlkZTIiKSkpCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0 +LTNzaDI1eG5qL1NsaWRlMi5wbmciKSkKRXZhbDogKGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZh +bDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmci +KSAoIlNsaWRlMiIpKSkKRXZhbDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4 +KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmov +U2xpZGUyLnBuZyIpICgiU2xpZGUyIikpKQpBcHBseSB0bzogKCgiL3RtcC9naW1wLW91dC0zc2gy +NXhuai9TbGlkZTIucG5nIikpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIg +bGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEp +KSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFs +OiBjZHIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1Ns +aWRlMi5wbmciKSAoIlNsaWRlMiIpKSkKRXZhbDogKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKQpF +dmFsOiBhcHBlbmQKRXZhbDogY2FycwpFdmFsOiAobGlzdCBjYXIxKQpFdmFsOiBsaXN0CkV2YWw6 +IGNhcjEKQXBwbHkgdG86ICgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIikKRXZh +bDogeApBcHBseSB0bzogKCgpICgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIikp +CkV2YWw6IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMK +RXZhbDogKGxpc3QgY2RyMSkKRXZhbDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCkpCkV2 +YWw6IHgKQXBwbHkgdG86ICgoKSAoKCkpKQpBcHBseSB0bzogKCgoIlNsaWRlMiIpKSAoIi90bXAv +Z2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpICgoKSkpCkV2YWw6IChpZiAobnVsbD8gbGlz +dHMpIChjb25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2Rh +ciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5k +IGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51 +bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMiIp +KSkKRXZhbDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAo +dW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3Qg +Y2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0cykKRXZh +bDogY2FhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMiIpKSkKRXZhbDogKGNhciAo +Y2FyIHgpKQpFdmFsOiBjYXIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0 +bzogKCgoIlNsaWRlMiIpKSkKQXBwbHkgdG86ICgoIlNsaWRlMiIpKQpFdmFsOiAoY2RhciBsaXN0 +cykKRXZhbDogY2RhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoIlNsaWRlMiIpKSkKRXZhbDog +KGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4KQpFdmFsOiBjYXIKRXZhbDogeApB +cHBseSB0bzogKCgoIlNsaWRlMiIpKSkKQXBwbHkgdG86ICgoIlNsaWRlMiIpKQpFdmFsOiAodW56 +aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2Fy +MSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVy +YXRpdmUKRXZhbDogKGNkciBsaXN0cykKRXZhbDogY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAo +KCgiU2xpZGUyIikpKQpFdmFsOiAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpCkV2YWw6IGFwcGVu +ZApFdmFsOiBjYXJzCkV2YWw6IChsaXN0IGNhcjEpCkV2YWw6IGxpc3QKRXZhbDogY2FyMQpBcHBs +eSB0bzogKCJTbGlkZTIiKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LTNzaDI1 +eG5qL1NsaWRlMi5wbmciKSAoIlNsaWRlMiIpKQpFdmFsOiAoYXBwZW5kIGNkcnMgKGxpc3QgY2Ry +MSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjZHJzCkV2YWw6IChsaXN0IGNkcjEpCkV2YWw6IGxpc3QK +RXZhbDogY2RyMQpBcHBseSB0bzogKCgpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCgpKSAoKCkpKQpB +cHBseSB0bzogKCgpICgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAiU2xpZGUy +IikgKCgpICgpKSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGNvbnMgY2FycyBjZHJzKSAobGV0 +ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIxIChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1j +ZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVu +ZCBjZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFsOiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2 +YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCkpCkV2YWw6IChjb25zIGNhcnMgY2RycykKRXZhbDogY29u +cwpFdmFsOiBjYXJzCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4 +bmovU2xpZGUyLnBuZyIgIlNsaWRlMiIpICgoKSAoKSkpCkV2YWw6IChjYXIgdW56KQpFdmFsOiBj +YXIKRXZhbDogdW56CkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIu +cG5nIiAiU2xpZGUyIikgKCkgKCkpKQpFdmFsOiAoY2RyIHVueikKRXZhbDogY2RyCkV2YWw6IHVu +egpBcHBseSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgIlNsaWRl +MiIpICgpICgpKSkKRXZhbDogKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29u +cyBwcm9jIGNkcnMpKSkKRXZhbDogY29ucwpFdmFsOiAoYXBwbHkgcHJvYyBjYXJzKQpFdmFsOiBh +cHBseQpFdmFsOiBwcm9jCkV2YWw6IGNhcnMKQXBwbHkgdG86ICgjPGNvbnMgUFJPQ0VEVVJFIDc2 +PiAoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgIlNsaWRlMiIpKQpBcHBseSB0 +bzogKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciICJTbGlkZTIiKQpFdmFsOiAo +YXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpCkV2YWw6IGFwcGx5CkV2YWw6IG1hcApFdmFsOiAo +Y29ucyBwcm9jIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogcHJvYwpFdmFsOiBjZHJzCkFwcGx5IHRv +OiAoIzxjb25zIFBST0NFRFVSRSA3Nj4gKCgpICgpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgj +PGNvbnMgUFJPQ0VEVVJFIDc2PiAoKSAoKSkpCkFwcGx5IHRvOiAoIzxjb25zIFBST0NFRFVSRSA3 +Nj4gKCkgKCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAoaWYgKG51bGw/ +IChjYXIgbGlzdHMpKSAnKCkgKGxldCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0 +cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkgKGNvbnMgKGFwcGx5IHByb2Mg +Y2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpKSkKRXZhbDogKG51bGw/IGxpc3Rz +KQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKSAoKSkpCkV2YWw6IChpZiAo +bnVsbD8gKGNhciBsaXN0cykpICcoKSAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2Ry +IGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkg +cHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyAo +Y2FyIGxpc3RzKSkKRXZhbDogbnVsbD8KRXZhbDogKGNhciBsaXN0cykKRXZhbDogY2FyCkV2YWw6 +IGxpc3RzCkFwcGx5IHRvOiAoKCgpICgpKSkKQXBwbHkgdG86ICgoKSkKRXZhbDogJygpCkFwcGx5 +IHRvOiAoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpICgp +KQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIu +cG5nIiAuICJTbGlkZTIiKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAo +aWYgKG51bGw/IChjYXIgbGlzdHMpKSAjdCAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgt +Y2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJv +YyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyBsaXN0 +cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC0z +c2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkpKQpFdmFsOiAoaWYgKG51bGw/IChjYXIg +bGlzdHMpKSAjdCAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNh +cnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkg +bWFwIChjb25zIHByb2MgY2RycykpKSkKRXZhbDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBu +dWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFsOiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgo +KCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkpKQpBcHBs +eSB0bzogKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikp +KQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMg +KGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFw +IChjb25zIHByb2MgY2RycykpKQpFdmFsOiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKQpF +dmFsOiBhcHBseQpFdmFsOiB1bnppcDEtd2l0aC1jZHIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgj +PENMT1NVUkU+ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRl +MiIpKSkpCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAu +ICJTbGlkZTIiKSkpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIGxpc3RzICcoKSAn +KCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogbGlzdHMKRXZhbDogJygp +CkV2YWw6ICcoKQpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5w +bmciIC4gIlNsaWRlMiIpKSkgKCkgKCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNh +cnMgY2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAo +dW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3Qg +Y2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpF +dmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1 +eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKSkpCkV2YWw6IChsZXQgKChjYXIxIChjYWFyIGxp +c3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgKGNk +ciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMgKGxpc3QgY2Ry +MSkpKSkKRXZhbDogKGNhYXIgbGlzdHMpCkV2YWw6IGNhYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86 +ICgoKCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkpKQpF +dmFsOiAoY2FyIChjYXIgeCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFs +OiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgLiAi +U2xpZGUyIikpKSkKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5w +bmciIC4gIlNsaWRlMiIpKSkKRXZhbDogKGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZhbDogbGlz +dHMKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJT +bGlkZTIiKSkpKQpFdmFsOiAoY2RyIChjYXIgeCkpCkV2YWw6IGNkcgpFdmFsOiAoY2FyIHgpCkV2 +YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xp +ZGUyLnBuZyIgLiAiU2xpZGUyIikpKSkKQXBwbHkgdG86ICgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1 +eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKSkKRXZhbDogKHVuemlwMS13aXRoLWNkci1pdGVy +YXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMg +KGxpc3QgY2RyMSkpKQpFdmFsOiB1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlCkV2YWw6IChjZHIg +bGlzdHMpCkV2YWw6IGNkcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0 +LTNzaDI1eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKSkpCkV2YWw6IChhcHBlbmQgY2FycyAo +bGlzdCBjYXIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNhcnMKRXZhbDogKGxpc3QgY2FyMSkKRXZh +bDogbGlzdApFdmFsOiBjYXIxCkFwcGx5IHRvOiAoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1Ns +aWRlMi5wbmciIC4gIlNsaWRlMiIpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCkgKCgiL3RtcC9naW1w +LW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkpCkV2YWw6IChhcHBlbmQgY2Ry +cyAobGlzdCBjZHIxKSkKRXZhbDogYXBwZW5kCkV2YWw6IGNkcnMKRXZhbDogKGxpc3QgY2RyMSkK +RXZhbDogbGlzdApFdmFsOiBjZHIxCkFwcGx5IHRvOiAoKCkpCkV2YWw6IHgKQXBwbHkgdG86ICgo +KSAoKCkpKQpBcHBseSB0bzogKCgpICgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBu +ZyIgLiAiU2xpZGUyIikpICgoKSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMg +Y2RycykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56 +aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2Fy +MSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFs +OiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29ucyBjYXJzIGNkcnMp +CkV2YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoKCgiL3RtcC9naW1w +LW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkgKCgpKSkKRXZhbDogKGNhciB1 +bnopCkV2YWw6IGNhcgpFdmFsOiB1bnoKQXBwbHkgdG86ICgoKCgiL3RtcC9naW1wLW91dC0zc2gy +NXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkgKCkpKQpFdmFsOiAoY2RyIHVueikKRXZhbDog +Y2RyCkV2YWw6IHVuegpBcHBseSB0bzogKCgoKCIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRl +Mi5wbmciIC4gIlNsaWRlMiIpKSAoKSkpCkV2YWw6IChhcHBseSBwcm9jIGNhcnMpCkV2YWw6IGFw +cGx5CkV2YWw6IHByb2MKRXZhbDogY2FycwpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCgiL3RtcC9n +aW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkpCkFwcGx5IHRvOiAoKCIv +dG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciIC4gIlNsaWRlMiIpKQpFdmFsOiAocG5n +LXRvLWxheWVyIGltZyAoY2FyIG5hbWVzKSAoY2RyIG5hbWVzKSkKRXZhbDogcG5nLXRvLWxheWVy +CkV2YWw6IGltZwpFdmFsOiAoY2FyIG5hbWVzKQpFdmFsOiBjYXIKRXZhbDogbmFtZXMKQXBwbHkg +dG86ICgoIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgLiAiU2xpZGUyIikpCkV2 +YWw6IChjZHIgbmFtZXMpCkV2YWw6IGNkcgpFdmFsOiBuYW1lcwpBcHBseSB0bzogKCgiL3RtcC9n +aW1wLW91dC0zc2gyNXhuai9TbGlkZTIucG5nIiAuICJTbGlkZTIiKSkKQXBwbHkgdG86ICgxICIv +dG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciICJTbGlkZTIiKQpFdmFsOiAobGV0KiAo +KHBuZyAoY2FyIChmaWxlLXBuZy1sb2FkIFJVTi1OT05JTlRFUkFDVElWRSBwbmdfZmlsZW5hbWUg +cG5nX2ZpbGVuYW1lKSkpIChwbmdfbGF5ZXIgKGNhciAoZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxh +eWVyIHBuZykpKSAoeGNmX2xheWVyIChjYXIgKGdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUg +cG5nX2xheWVyIGltZykpKSkgKGdpbXAtaW1hZ2UtYWRkLWxheWVyIGltZyB4Y2ZfbGF5ZXIgLTEp +IChnaW1wLWRyYXdhYmxlLXNldC1uYW1lIHhjZl9sYXllciBsYXllcl9uYW1lKSkKRXZhbDogKGNh +ciAoZmlsZS1wbmctbG9hZCBSVU4tTk9OSU5URVJBQ1RJVkUgcG5nX2ZpbGVuYW1lIHBuZ19maWxl +bmFtZSkpCkV2YWw6IGNhcgpFdmFsOiAoZmlsZS1wbmctbG9hZCBSVU4tTk9OSU5URVJBQ1RJVkUg +cG5nX2ZpbGVuYW1lIHBuZ19maWxlbmFtZSkKRXZhbDogZmlsZS1wbmctbG9hZApFdmFsOiBSVU4t +Tk9OSU5URVJBQ1RJVkUKRXZhbDogcG5nX2ZpbGVuYW1lCkV2YWw6IHBuZ19maWxlbmFtZQpBcHBs +eSB0bzogKDEgIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgIi90bXAvZ2ltcC1v +dXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAo +Y29ucyAiZmlsZS1wbmctbG9hZCIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1kYi1j +YWxsCkV2YWw6IChjb25zICJmaWxlLXBuZy1sb2FkIiB4KQpFdmFsOiBjb25zCkV2YWw6ICJmaWxl +LXBuZy1sb2FkIgpFdmFsOiB4CkFwcGx5IHRvOiAoImZpbGUtcG5nLWxvYWQiICgxICIvdG1wL2dp +bXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRl +Mi5wbmciKSkKQXBwbHkgdG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAo +ImZpbGUtcG5nLWxvYWQiIDEgIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIgIi90 +bXAvZ2ltcC1vdXQtM3NoMjV4bmovU2xpZGUyLnBuZyIpKQpBcHBseSB0bzogKCJmaWxlLXBuZy1s +b2FkIiAxICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL1NsaWRlMi5wbmciICIvdG1wL2dpbXAtb3V0 +LTNzaDI1eG5qL1NsaWRlMi5wbmciKQpBcHBseSB0bzogKCgyKSkKRXZhbDogKGNhciAoZ2ltcC1p +bWFnZS1nZXQtYWN0aXZlLWxheWVyIHBuZykpCkV2YWw6IGNhcgpFdmFsOiAoZ2ltcC1pbWFnZS1n +ZXQtYWN0aXZlLWxheWVyIHBuZykKRXZhbDogZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyCkV2 +YWw6IHBuZwpBcHBseSB0bzogKDIpCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAoY29u +cyAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2lt +cC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciIg +eCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIgpFdmFsOiB4 +CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciIgKDIpKQpBcHBseSB0bzog +KCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2ltcC1pbWFnZS1nZXQtYWN0 +aXZlLWxheWVyIiAyKSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1nZXQtYWN0aXZlLWxheWVyIiAy +KQpBcHBseSB0bzogKCgzKSkKRXZhbDogKGNhciAoZ2ltcC1sYXllci1uZXctZnJvbS1kcmF3YWJs +ZSBwbmdfbGF5ZXIgaW1nKSkKRXZhbDogY2FyCkV2YWw6IChnaW1wLWxheWVyLW5ldy1mcm9tLWRy +YXdhYmxlIHBuZ19sYXllciBpbWcpCkV2YWw6IGdpbXAtbGF5ZXItbmV3LWZyb20tZHJhd2FibGUK +RXZhbDogcG5nX2xheWVyCkV2YWw6IGltZwpBcHBseSB0bzogKDMgMSkKRXZhbDogKGFwcGx5IGdp +bXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiB4KSkK +RXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtbGF5 +ZXItbmV3LWZyb20tZHJhd2FibGUiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtbGF5ZXItbmV3 +LWZyb20tZHJhd2FibGUiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1sYXllci1uZXctZnJvbS1k +cmF3YWJsZSIgKDMgMSkpCkFwcGx5IHRvOiAoIzxGT1JFSUdOIFBST0NFRFVSRSA5Mzk2MTEzMTU1 +MjQ5Nj4gKCJnaW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAzIDEpKQpBcHBseSB0bzogKCJn +aW1wLWxheWVyLW5ldy1mcm9tLWRyYXdhYmxlIiAzIDEpCkFwcGx5IHRvOiAoKDQpKQpFdmFsOiAo +Z2ltcC1pbWFnZS1hZGQtbGF5ZXIgaW1nIHhjZl9sYXllciAtMSkKRXZhbDogZ2ltcC1pbWFnZS1h +ZGQtbGF5ZXIKRXZhbDogaW1nCkV2YWw6IHhjZl9sYXllcgpFdmFsOiAtMQpBcHBseSB0bzogKDEg +NCAtMSkKRXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWltYWdlLWFk +ZC1sYXllciIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChj +b25zICJnaW1wLWltYWdlLWFkZC1sYXllciIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFn +ZS1hZGQtbGF5ZXIiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1hZGQtbGF5ZXIiICgx +IDQgLTEpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgi +Z2ltcC1pbWFnZS1hZGQtbGF5ZXIiIDEgNCAtMSkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtYWRk +LWxheWVyIiAxIDQgLTEpCkV2YWw6IChnaW1wLWRyYXdhYmxlLXNldC1uYW1lIHhjZl9sYXllciBs +YXllcl9uYW1lKQpFdmFsOiBnaW1wLWRyYXdhYmxlLXNldC1uYW1lCkV2YWw6IHhjZl9sYXllcgpF +dmFsOiBsYXllcl9uYW1lCkFwcGx5IHRvOiAoNCAiU2xpZGUyIikKRXZhbDogKGFwcGx5IGdpbXAt +cHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWRyYXdhYmxlLXNldC1uYW1lIiB4KSkKRXZhbDogYXBw +bHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtZHJhd2FibGUtc2V0 +LW5hbWUiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtZHJhd2FibGUtc2V0LW5hbWUiCkV2YWw6 +IHgKQXBwbHkgdG86ICgiZ2ltcC1kcmF3YWJsZS1zZXQtbmFtZSIgKDQgIlNsaWRlMiIpKQpBcHBs +eSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2ltcC1kcmF3YWJs +ZS1zZXQtbmFtZSIgNCAiU2xpZGUyIikpCkFwcGx5IHRvOiAoImdpbXAtZHJhd2FibGUtc2V0LW5h +bWUiIDQgIlNsaWRlMiIpCkV2YWw6IChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJzKSkKRXZhbDog +YXBwbHkKRXZhbDogbWFwCkV2YWw6IChjb25zIHByb2MgY2RycykKRXZhbDogY29ucwpFdmFsOiBw +cm9jCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgoKSkpCkFwcGx5IHRvOiAoIzxD +TE9TVVJFPiAoIzxDTE9TVVJFPiAoKSkpCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKSkKRXZhbDog +KGlmIChudWxsPyBsaXN0cykgKGFwcGx5IHByb2MpIChpZiAobnVsbD8gKGNhciBsaXN0cykpICco +KSAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1 +bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFw +IChjb25zIHByb2MgY2RycykpKSkpKQpFdmFsOiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2 +YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgpKSkKRXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkg +JygpIChsZXQqICgodW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2Fy +IHVueikpIChjZHJzIChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBt +YXAgKGNvbnMgcHJvYyBjZHJzKSkpKSkKRXZhbDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBu +dWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFsOiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgo +KCkpKQpBcHBseSB0bzogKCgpKQpFdmFsOiAnKCkKRXZhbDogKGdpbXAtaW1hZ2UtcmVzaXplLXRv +LWxheWVycyBpbWcpCkV2YWw6IGdpbXAtaW1hZ2UtcmVzaXplLXRvLWxheWVycwpFdmFsOiBpbWcK +QXBwbHkgdG86ICgxKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdpbXAt +aW1hZ2UtcmVzaXplLXRvLWxheWVycyIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1k +Yi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWltYWdlLXJlc2l6ZS10by1sYXllcnMiIHgpCkV2YWw6 +IGNvbnMKRXZhbDogImdpbXAtaW1hZ2UtcmVzaXplLXRvLWxheWVycyIKRXZhbDogeApBcHBseSB0 +bzogKCJnaW1wLWltYWdlLXJlc2l6ZS10by1sYXllcnMiICgxKSkKQXBwbHkgdG86ICgjPEZPUkVJ +R04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAtaW1hZ2UtcmVzaXplLXRvLWxheWVy +cyIgMSkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtcmVzaXplLXRvLWxheWVycyIgMSkKRXZhbDog +KGZvci1lYWNoIChsYW1iZGEgKGhHdWlkZSkgKGdpbXAtaW1hZ2UtYWRkLWhndWlkZSBpbWcgaEd1 +aWRlKSkgJyg5NTEuMDIyNyA0OS4wMjQxMjgpKQpFdmFsOiBmb3ItZWFjaApFdmFsOiAobGFtYmRh +IChoR3VpZGUpIChnaW1wLWltYWdlLWFkZC1oZ3VpZGUgaW1nIGhHdWlkZSkpCkFwcGx5IHRvOiAo +KChoR3VpZGUpIChnaW1wLWltYWdlLWFkZC1oZ3VpZGUgaW1nIGhHdWlkZSkpKQpFdmFsOiAoaWYg +KG1hY3JvPyBmb3JtKSAobWFjcm8tZXhwYW5kLWFsbCAobWFjcm8tZXhwYW5kIGZvcm0pKSBmb3Jt +KQpFdmFsOiAobWFjcm8/IGZvcm0pCkV2YWw6IG1hY3JvPwpFdmFsOiBmb3JtCkFwcGx5IHRvOiAo +KChoR3VpZGUpIChnaW1wLWltYWdlLWFkZC1oZ3VpZGUgaW1nIGhHdWlkZSkpKQpFdmFsOiBmb3Jt +CkV2YWw6ICcoOTUxLjAyMjcgNDkuMDI0MTI4KQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKDk1MS4w +MjI3IDQ5LjAyNDEyOCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAoaWYg +KG51bGw/IChjYXIgbGlzdHMpKSAjdCAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2Ry +IGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJvYyBj +YXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyBsaXN0cykK +RXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDk1MS4wMjI3IDQ5LjAyNDEyOCkp +KQpFdmFsOiAoaWYgKG51bGw/IChjYXIgbGlzdHMpKSAjdCAobGV0KiAoKHVueiAoYXBwbHkgdW56 +aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAo +YXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkKRXZhbDogKG51 +bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBudWxsPwpFdmFsOiAoY2FyIGxpc3RzKQpFdmFsOiBjYXIK +RXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDk1MS4wMjI3IDQ5LjAyNDEyOCkpKQpBcHBseSB0bzog +KCg5NTEuMDIyNyA0OS4wMjQxMjgpKQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdp +dGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkg +cHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKQpFdmFsOiAoYXBwbHkgdW56 +aXAxLXdpdGgtY2RyIGxpc3RzKQpFdmFsOiBhcHBseQpFdmFsOiB1bnppcDEtd2l0aC1jZHIKRXZh +bDogbGlzdHMKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgoOTUxLjAyMjcgNDkuMDI0MTI4KSkpCkFw +cGx5IHRvOiAoKDk1MS4wMjI3IDQ5LjAyNDEyOCkpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRl +cmF0aXZlIGxpc3RzICcoKSAnKCkpCkV2YWw6IHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUKRXZh +bDogbGlzdHMKRXZhbDogJygpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgoOTUxLjAyMjcgNDkuMDI0 +MTI4KSkgKCkgKCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2RycykgKGxl +dCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgt +Y2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBl +bmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpF +dmFsOiBsaXN0cwpBcHBseSB0bzogKCgoOTUxLjAyMjcgNDkuMDI0MTI4KSkpCkV2YWw6IChsZXQg +KChjYXIxIChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNk +ci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5k +IGNkcnMgKGxpc3QgY2RyMSkpKSkKRXZhbDogKGNhYXIgbGlzdHMpCkV2YWw6IGNhYXIKRXZhbDog +bGlzdHMKQXBwbHkgdG86ICgoKDk1MS4wMjI3IDQ5LjAyNDEyOCkpKQpFdmFsOiAoY2FyIChjYXIg +eCkpCkV2YWw6IGNhcgpFdmFsOiAoY2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAo +KCg5NTEuMDIyNyA0OS4wMjQxMjgpKSkKQXBwbHkgdG86ICgoOTUxLjAyMjcgNDkuMDI0MTI4KSkK +RXZhbDogKGNkYXIgbGlzdHMpCkV2YWw6IGNkYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDk1 +MS4wMjI3IDQ5LjAyNDEyOCkpKQpFdmFsOiAoY2RyIChjYXIgeCkpCkV2YWw6IGNkcgpFdmFsOiAo +Y2FyIHgpCkV2YWw6IGNhcgpFdmFsOiB4CkFwcGx5IHRvOiAoKCg5NTEuMDIyNyA0OS4wMjQxMjgp +KSkKQXBwbHkgdG86ICgoOTUxLjAyMjcgNDkuMDI0MTI4KSkKRXZhbDogKHVuemlwMS13aXRoLWNk +ci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5k +IGNkcnMgKGxpc3QgY2RyMSkpKQpFdmFsOiB1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlCkV2YWw6 +IChjZHIgbGlzdHMpCkV2YWw6IGNkcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoOTUxLjAyMjcg +NDkuMDI0MTI4KSkpCkV2YWw6IChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkKRXZhbDogYXBwZW5k +CkV2YWw6IGNhcnMKRXZhbDogKGxpc3QgY2FyMSkKRXZhbDogbGlzdApFdmFsOiBjYXIxCkFwcGx5 +IHRvOiAoOTUxLjAyMjcpCkV2YWw6IHgKQXBwbHkgdG86ICgoKSAoOTUxLjAyMjcpKQpFdmFsOiAo +YXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjZHJzCkV2YWw6IChs +aXN0IGNkcjEpCkV2YWw6IGxpc3QKRXZhbDogY2RyMQpBcHBseSB0bzogKCg0OS4wMjQxMjgpKQpF +dmFsOiB4CkFwcGx5IHRvOiAoKCkgKCg0OS4wMjQxMjgpKSkKQXBwbHkgdG86ICgoKSAoOTUxLjAy +MjcpICgoNDkuMDI0MTI4KSkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2Ry +cykgKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAx +LXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkp +IChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBu +dWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgpKQpFdmFsOiAoY29ucyBjYXJzIGNkcnMpCkV2 +YWw6IGNvbnMKRXZhbDogY2FycwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoKDk1MS4wMjI3KSAoKDQ5 +LjAyNDEyOCkpKQpFdmFsOiAoY2FyIHVueikKRXZhbDogY2FyCkV2YWw6IHVuegpBcHBseSB0bzog +KCgoOTUxLjAyMjcpICg0OS4wMjQxMjgpKSkKRXZhbDogKGNkciB1bnopCkV2YWw6IGNkcgpFdmFs +OiB1bnoKQXBwbHkgdG86ICgoKDk1MS4wMjI3KSAoNDkuMDI0MTI4KSkpCkV2YWw6IChhcHBseSBw +cm9jIGNhcnMpCkV2YWw6IGFwcGx5CkV2YWw6IHByb2MKRXZhbDogY2FycwpBcHBseSB0bzogKCM8 +Q0xPU1VSRT4gKDk1MS4wMjI3KSkKQXBwbHkgdG86ICg5NTEuMDIyNykKRXZhbDogKGdpbXAtaW1h +Z2UtYWRkLWhndWlkZSBpbWcgaEd1aWRlKQpFdmFsOiBnaW1wLWltYWdlLWFkZC1oZ3VpZGUKRXZh +bDogaW1nCkV2YWw6IGhHdWlkZQpBcHBseSB0bzogKDEgOTUxLjAyMjcpCkV2YWw6IChhcHBseSBn +aW1wLXByb2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS1hZGQtaGd1aWRlIiB4KSkKRXZhbDog +YXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtYWRk +LWhndWlkZSIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1hZGQtaGd1aWRlIgpFdmFs +OiB4CkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtYWRkLWhndWlkZSIgKDEgOTUxLjAyMjcpKQpBcHBs +eSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2ltcC1pbWFnZS1h +ZGQtaGd1aWRlIiAxIDk1MS4wMjI3KSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1hZGQtaGd1aWRl +IiAxIDk1MS4wMjI3KQpFdmFsOiAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpCkV2YWw6IGFw +cGx5CkV2YWw6IG1hcApFdmFsOiAoY29ucyBwcm9jIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogcHJv +YwpFdmFsOiBjZHJzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKDQ5LjAyNDEyOCkpKQpBcHBseSB0 +bzogKCM8Q0xPU1VSRT4gKCM8Q0xPU1VSRT4gKDQ5LjAyNDEyOCkpKQpBcHBseSB0bzogKCM8Q0xP +U1VSRT4gKDQ5LjAyNDEyOCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAo +aWYgKG51bGw/IChjYXIgbGlzdHMpKSAnKCkgKGxldCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRo +LWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkgKGNvbnMgKGFw +cGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpKSkKRXZhbDogKG51 +bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoNDkuMDI0MTI4 +KSkpCkV2YWw6IChpZiAobnVsbD8gKGNhciBsaXN0cykpICcoKSAobGV0KiAoKHVueiAoYXBwbHkg +dW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikp +KSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkp +CkV2YWw6IChudWxsPyAoY2FyIGxpc3RzKSkKRXZhbDogbnVsbD8KRXZhbDogKGNhciBsaXN0cykK +RXZhbDogY2FyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCg0OS4wMjQxMjgpKSkKQXBwbHkgdG86 +ICgoNDkuMDI0MTI4KSkKRXZhbDogKGxldCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBs +aXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkgKGNvbnMgKGFwcGx5IHBy +b2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpCkV2YWw6IChhcHBseSB1bnpp +cDEtd2l0aC1jZHIgbGlzdHMpCkV2YWw6IGFwcGx5CkV2YWw6IHVuemlwMS13aXRoLWNkcgpFdmFs +OiBsaXN0cwpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCg0OS4wMjQxMjgpKSkKQXBwbHkgdG86ICgo +NDkuMDI0MTI4KSkKRXZhbDogKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgbGlzdHMgJygpICco +KSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiBsaXN0cwpFdmFsOiAnKCkK +RXZhbDogJygpCkFwcGx5IHRvOiAoKCg0OS4wMjQxMjgpKSAoKSAoKSkKRXZhbDogKGlmIChudWxs +PyBsaXN0cykgKGNvbnMgY2FycyBjZHJzKSAobGV0ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIx +IChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChh +cHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFs +OiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCg0OS4w +MjQxMjgpKSkKRXZhbDogKGxldCAoKGNhcjEgKGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0 +cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMg +KGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpKQpFdmFsOiAoY2FhciBsaXN0 +cykKRXZhbDogY2FhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoNDkuMDI0MTI4KSkpCkV2YWw6 +IChjYXIgKGNhciB4KSkKRXZhbDogY2FyCkV2YWw6IChjYXIgeCkKRXZhbDogY2FyCkV2YWw6IHgK +QXBwbHkgdG86ICgoKDQ5LjAyNDEyOCkpKQpBcHBseSB0bzogKCg0OS4wMjQxMjgpKQpFdmFsOiAo +Y2RhciBsaXN0cykKRXZhbDogY2RhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoNDkuMDI0MTI4 +KSkpCkV2YWw6IChjZHIgKGNhciB4KSkKRXZhbDogY2RyCkV2YWw6IChjYXIgeCkKRXZhbDogY2Fy +CkV2YWw6IHgKQXBwbHkgdG86ICgoKDQ5LjAyNDEyOCkpKQpBcHBseSB0bzogKCg0OS4wMjQxMjgp +KQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNh +cnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAobGlzdCBjZHIxKSkpCkV2YWw6IHVuemlwMS13 +aXRoLWNkci1pdGVyYXRpdmUKRXZhbDogKGNkciBsaXN0cykKRXZhbDogY2RyCkV2YWw6IGxpc3Rz +CkFwcGx5IHRvOiAoKCg0OS4wMjQxMjgpKSkKRXZhbDogKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEp +KQpFdmFsOiBhcHBlbmQKRXZhbDogY2FycwpFdmFsOiAobGlzdCBjYXIxKQpFdmFsOiBsaXN0CkV2 +YWw6IGNhcjEKQXBwbHkgdG86ICg0OS4wMjQxMjgpCkV2YWw6IHgKQXBwbHkgdG86ICgoKSAoNDku +MDI0MTI4KSkKRXZhbDogKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKQpFdmFsOiBhcHBlbmQKRXZh +bDogY2RycwpFdmFsOiAobGlzdCBjZHIxKQpFdmFsOiBsaXN0CkV2YWw6IGNkcjEKQXBwbHkgdG86 +ICgoKSkKRXZhbDogeApBcHBseSB0bzogKCgpICgoKSkpCkFwcGx5IHRvOiAoKCkgKDQ5LjAyNDEy +OCkgKCgpKSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGNvbnMgY2FycyBjZHJzKSAobGV0ICgo +Y2FyMSAoY2FhciBsaXN0cykpIChjZHIxIChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHIt +aXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBj +ZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFsOiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6 +IGxpc3RzCkFwcGx5IHRvOiAoKCkpCkV2YWw6IChjb25zIGNhcnMgY2RycykKRXZhbDogY29ucwpF +dmFsOiBjYXJzCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgoNDkuMDI0MTI4KSAoKCkpKQpFdmFsOiAo +Y2FyIHVueikKRXZhbDogY2FyCkV2YWw6IHVuegpBcHBseSB0bzogKCgoNDkuMDI0MTI4KSAoKSkp +CkV2YWw6IChjZHIgdW56KQpFdmFsOiBjZHIKRXZhbDogdW56CkFwcGx5IHRvOiAoKCg0OS4wMjQx +MjgpICgpKSkKRXZhbDogKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBw +cm9jIGNkcnMpKSkKRXZhbDogY29ucwpFdmFsOiAoYXBwbHkgcHJvYyBjYXJzKQpFdmFsOiBhcHBs +eQpFdmFsOiBwcm9jCkV2YWw6IGNhcnMKQXBwbHkgdG86ICgjPENMT1NVUkU+ICg0OS4wMjQxMjgp +KQpBcHBseSB0bzogKDQ5LjAyNDEyOCkKRXZhbDogKGdpbXAtaW1hZ2UtYWRkLWhndWlkZSBpbWcg +aEd1aWRlKQpFdmFsOiBnaW1wLWltYWdlLWFkZC1oZ3VpZGUKRXZhbDogaW1nCkV2YWw6IGhHdWlk +ZQpBcHBseSB0bzogKDEgNDkuMDI0MTI4KQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwg +KGNvbnMgImdpbXAtaW1hZ2UtYWRkLWhndWlkZSIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAt +cHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWltYWdlLWFkZC1oZ3VpZGUiIHgpCkV2YWw6 +IGNvbnMKRXZhbDogImdpbXAtaW1hZ2UtYWRkLWhndWlkZSIKRXZhbDogeApBcHBseSB0bzogKCJn +aW1wLWltYWdlLWFkZC1oZ3VpZGUiICgxIDQ5LjAyNDEyOCkpCkFwcGx5IHRvOiAoIzxGT1JFSUdO +IFBST0NFRFVSRSA5Mzk2MTEzMTU1MjQ5Nj4gKCJnaW1wLWltYWdlLWFkZC1oZ3VpZGUiIDEgNDku +MDI0MTI4KSkKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1hZGQtaGd1aWRlIiAxIDQ5LjAyNDEyOCkK +RXZhbDogKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKQpFdmFsOiBhcHBseQpFdmFsOiBtYXAK +RXZhbDogKGNvbnMgcHJvYyBjZHJzKQpFdmFsOiBjb25zCkV2YWw6IHByb2MKRXZhbDogY2RycwpB +cHBseSB0bzogKCM8Q0xPU1VSRT4gKCgpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgjPENMT1NV +UkU+ICgpKSkKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3Rz +KSAoYXBwbHkgcHJvYykgKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgodW56IChh +cHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJzIChjZHIg +dW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJz +KSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkg +dG86ICgoKCkpKQpFdmFsOiAoaWYgKG51bGw/IChjYXIgbGlzdHMpKSAnKCkgKGxldCogKCh1bnog +KGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNk +ciB1bnopKSkgKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNk +cnMpKSkpKQpFdmFsOiAobnVsbD8gKGNhciBsaXN0cykpCkV2YWw6IG51bGw/CkV2YWw6IChjYXIg +bGlzdHMpCkV2YWw6IGNhcgpFdmFsOiBsaXN0cwpBcHBseSB0bzogKCgoKSkpCkFwcGx5IHRvOiAo +KCkpCkV2YWw6ICcoKQpBcHBseSB0bzogKCgyKSAoKSkKRXZhbDogKGZvci1lYWNoIChsYW1iZGEg +KHZHdWlkZSkgKGdpbXAtaW1hZ2UtYWRkLXZndWlkZSBpbWcgdkd1aWRlKSkgJyg0Ni45MzY1Nzcg +OTUzLjAxNjU5KSkKRXZhbDogZm9yLWVhY2gKRXZhbDogKGxhbWJkYSAodkd1aWRlKSAoZ2ltcC1p +bWFnZS1hZGQtdmd1aWRlIGltZyB2R3VpZGUpKQpBcHBseSB0bzogKCgodkd1aWRlKSAoZ2ltcC1p +bWFnZS1hZGQtdmd1aWRlIGltZyB2R3VpZGUpKSkKRXZhbDogKGlmIChtYWNybz8gZm9ybSkgKG1h +Y3JvLWV4cGFuZC1hbGwgKG1hY3JvLWV4cGFuZCBmb3JtKSkgZm9ybSkKRXZhbDogKG1hY3JvPyBm +b3JtKQpFdmFsOiBtYWNybz8KRXZhbDogZm9ybQpBcHBseSB0bzogKCgodkd1aWRlKSAoZ2ltcC1p +bWFnZS1hZGQtdmd1aWRlIGltZyB2R3VpZGUpKSkKRXZhbDogZm9ybQpFdmFsOiAnKDQ2LjkzNjU3 +NyA5NTMuMDE2NTkpCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoNDYuOTM2NTc3IDk1My4wMTY1OSkp +CkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAoaWYgKG51bGw/IChjYXIgbGlz +dHMpKSAjdCAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMg +KGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFw +IChjb25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZh +bDogbGlzdHMKQXBwbHkgdG86ICgoKDQ2LjkzNjU3NyA5NTMuMDE2NTkpKSkKRXZhbDogKGlmIChu +dWxsPyAoY2FyIGxpc3RzKSkgI3QgKGxldCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBs +aXN0cykpIChjYXJzIChjYXIgdW56KSkgKGNkcnMgKGNkciB1bnopKSkgKGFwcGx5IHByb2MgY2Fy +cykgKGFwcGx5IG1hcCAoY29ucyBwcm9jIGNkcnMpKSkpCkV2YWw6IChudWxsPyAoY2FyIGxpc3Rz +KSkKRXZhbDogbnVsbD8KRXZhbDogKGNhciBsaXN0cykKRXZhbDogY2FyCkV2YWw6IGxpc3RzCkFw +cGx5IHRvOiAoKCg0Ni45MzY1NzcgOTUzLjAxNjU5KSkpCkFwcGx5IHRvOiAoKDQ2LjkzNjU3NyA5 +NTMuMDE2NTkpKQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3Rz +KSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoYXBwbHkgcHJvYyBjYXJzKSAo +YXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKQpFdmFsOiAoYXBwbHkgdW56aXAxLXdpdGgtY2Ry +IGxpc3RzKQpFdmFsOiBhcHBseQpFdmFsOiB1bnppcDEtd2l0aC1jZHIKRXZhbDogbGlzdHMKQXBw +bHkgdG86ICgjPENMT1NVUkU+ICgoNDYuOTM2NTc3IDk1My4wMTY1OSkpKQpBcHBseSB0bzogKCg0 +Ni45MzY1NzcgOTUzLjAxNjU5KSkKRXZhbDogKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgbGlz +dHMgJygpICcoKSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiBsaXN0cwpF +dmFsOiAnKCkKRXZhbDogJygpCkFwcGx5IHRvOiAoKCg0Ni45MzY1NzcgOTUzLjAxNjU5KSkgKCkg +KCkpCkV2YWw6IChpZiAobnVsbD8gbGlzdHMpIChjb25zIGNhcnMgY2RycykgKGxldCAoKGNhcjEg +KGNhYXIgbGlzdHMpKSAoY2RyMSAoY2RhciBsaXN0cykpKSAodW56aXAxLXdpdGgtY2RyLWl0ZXJh +dGl2ZSAoY2RyIGxpc3RzKSAoYXBwZW5kIGNhcnMgKGxpc3QgY2FyMSkpIChhcHBlbmQgY2RycyAo +bGlzdCBjZHIxKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBsaXN0 +cwpBcHBseSB0bzogKCgoNDYuOTM2NTc3IDk1My4wMTY1OSkpKQpFdmFsOiAobGV0ICgoY2FyMSAo +Y2FhciBsaXN0cykpIChjZHIxIChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0 +aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChs +aXN0IGNkcjEpKSkpCkV2YWw6IChjYWFyIGxpc3RzKQpFdmFsOiBjYWFyCkV2YWw6IGxpc3RzCkFw +cGx5IHRvOiAoKCg0Ni45MzY1NzcgOTUzLjAxNjU5KSkpCkV2YWw6IChjYXIgKGNhciB4KSkKRXZh +bDogY2FyCkV2YWw6IChjYXIgeCkKRXZhbDogY2FyCkV2YWw6IHgKQXBwbHkgdG86ICgoKDQ2Ljkz +NjU3NyA5NTMuMDE2NTkpKSkKQXBwbHkgdG86ICgoNDYuOTM2NTc3IDk1My4wMTY1OSkpCkV2YWw6 +IChjZGFyIGxpc3RzKQpFdmFsOiBjZGFyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCg0Ni45MzY1 +NzcgOTUzLjAxNjU5KSkpCkV2YWw6IChjZHIgKGNhciB4KSkKRXZhbDogY2RyCkV2YWw6IChjYXIg +eCkKRXZhbDogY2FyCkV2YWw6IHgKQXBwbHkgdG86ICgoKDQ2LjkzNjU3NyA5NTMuMDE2NTkpKSkK +QXBwbHkgdG86ICgoNDYuOTM2NTc3IDk1My4wMTY1OSkpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHIt +aXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBj +ZHJzIChsaXN0IGNkcjEpKSkKRXZhbDogdW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiAo +Y2RyIGxpc3RzKQpFdmFsOiBjZHIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDQ2LjkzNjU3NyA5 +NTMuMDE2NTkpKSkKRXZhbDogKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKQpFdmFsOiBhcHBlbmQK +RXZhbDogY2FycwpFdmFsOiAobGlzdCBjYXIxKQpFdmFsOiBsaXN0CkV2YWw6IGNhcjEKQXBwbHkg +dG86ICg0Ni45MzY1NzcpCkV2YWw6IHgKQXBwbHkgdG86ICgoKSAoNDYuOTM2NTc3KSkKRXZhbDog +KGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKQpFdmFsOiBhcHBlbmQKRXZhbDogY2RycwpFdmFsOiAo +bGlzdCBjZHIxKQpFdmFsOiBsaXN0CkV2YWw6IGNkcjEKQXBwbHkgdG86ICgoOTUzLjAxNjU5KSkK +RXZhbDogeApBcHBseSB0bzogKCgpICgoOTUzLjAxNjU5KSkpCkFwcGx5IHRvOiAoKCkgKDQ2Ljkz +NjU3NykgKCg5NTMuMDE2NTkpKSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGNvbnMgY2FycyBj +ZHJzKSAobGV0ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIxIChjZGFyIGxpc3RzKSkpICh1bnpp +cDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChhcHBlbmQgY2FycyAobGlzdCBjYXIx +KSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkpKQpFdmFsOiAobnVsbD8gbGlzdHMpCkV2YWw6 +IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCkpCkV2YWw6IChjb25zIGNhcnMgY2RycykK +RXZhbDogY29ucwpFdmFsOiBjYXJzCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgoNDYuOTM2NTc3KSAo +KDk1My4wMTY1OSkpKQpFdmFsOiAoY2FyIHVueikKRXZhbDogY2FyCkV2YWw6IHVuegpBcHBseSB0 +bzogKCgoNDYuOTM2NTc3KSAoOTUzLjAxNjU5KSkpCkV2YWw6IChjZHIgdW56KQpFdmFsOiBjZHIK +RXZhbDogdW56CkFwcGx5IHRvOiAoKCg0Ni45MzY1NzcpICg5NTMuMDE2NTkpKSkKRXZhbDogKGFw +cGx5IHByb2MgY2FycykKRXZhbDogYXBwbHkKRXZhbDogcHJvYwpFdmFsOiBjYXJzCkFwcGx5IHRv +OiAoIzxDTE9TVVJFPiAoNDYuOTM2NTc3KSkKQXBwbHkgdG86ICg0Ni45MzY1NzcpCkV2YWw6IChn +aW1wLWltYWdlLWFkZC12Z3VpZGUgaW1nIHZHdWlkZSkKRXZhbDogZ2ltcC1pbWFnZS1hZGQtdmd1 +aWRlCkV2YWw6IGltZwpFdmFsOiB2R3VpZGUKQXBwbHkgdG86ICgxIDQ2LjkzNjU3NykKRXZhbDog +KGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWltYWdlLWFkZC12Z3VpZGUiIHgp +KQpFdmFsOiBhcHBseQpFdmFsOiBnaW1wLXByb2MtZGItY2FsbApFdmFsOiAoY29ucyAiZ2ltcC1p +bWFnZS1hZGQtdmd1aWRlIiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLWFkZC12Z3Vp +ZGUiCkV2YWw6IHgKQXBwbHkgdG86ICgiZ2ltcC1pbWFnZS1hZGQtdmd1aWRlIiAoMSA0Ni45MzY1 +NzcpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2lt +cC1pbWFnZS1hZGQtdmd1aWRlIiAxIDQ2LjkzNjU3NykpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2Ut +YWRkLXZndWlkZSIgMSA0Ni45MzY1NzcpCkV2YWw6IChhcHBseSBtYXAgKGNvbnMgcHJvYyBjZHJz +KSkKRXZhbDogYXBwbHkKRXZhbDogbWFwCkV2YWw6IChjb25zIHByb2MgY2RycykKRXZhbDogY29u +cwpFdmFsOiBwcm9jCkV2YWw6IGNkcnMKQXBwbHkgdG86ICgjPENMT1NVUkU+ICgoOTUzLjAxNjU5 +KSkpCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoIzxDTE9TVVJFPiAoOTUzLjAxNjU5KSkpCkFwcGx5 +IHRvOiAoIzxDTE9TVVJFPiAoOTUzLjAxNjU5KSkKRXZhbDogKGlmIChudWxsPyBsaXN0cykgKGFw +cGx5IHByb2MpIChpZiAobnVsbD8gKGNhciBsaXN0cykpICcoKSAobGV0KiAoKHVueiAoYXBwbHkg +dW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikp +KSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkp +KQpFdmFsOiAobnVsbD8gbGlzdHMpCkV2YWw6IG51bGw/CkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAo +KCg5NTMuMDE2NTkpKSkKRXZhbDogKGlmIChudWxsPyAoY2FyIGxpc3RzKSkgJygpIChsZXQqICgo +dW56IChhcHBseSB1bnppcDEtd2l0aC1jZHIgbGlzdHMpKSAoY2FycyAoY2FyIHVueikpIChjZHJz +IChjZHIgdW56KSkpIChjb25zIChhcHBseSBwcm9jIGNhcnMpIChhcHBseSBtYXAgKGNvbnMgcHJv +YyBjZHJzKSkpKSkKRXZhbDogKG51bGw/IChjYXIgbGlzdHMpKQpFdmFsOiBudWxsPwpFdmFsOiAo +Y2FyIGxpc3RzKQpFdmFsOiBjYXIKRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDk1My4wMTY1OSkp +KQpBcHBseSB0bzogKCg5NTMuMDE2NTkpKQpFdmFsOiAobGV0KiAoKHVueiAoYXBwbHkgdW56aXAx +LXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnopKSAoY2RycyAoY2RyIHVueikpKSAoY29u +cyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpKSkKRXZhbDog +KGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykKRXZhbDogYXBwbHkKRXZhbDogdW56aXAxLXdp +dGgtY2RyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKDk1My4wMTY1OSkpKQpB +cHBseSB0bzogKCg5NTMuMDE2NTkpKQpFdmFsOiAodW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZSBs +aXN0cyAnKCkgJygpKQpFdmFsOiB1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlCkV2YWw6IGxpc3Rz +CkV2YWw6ICcoKQpFdmFsOiAnKCkKQXBwbHkgdG86ICgoKDk1My4wMTY1OSkpICgpICgpKQpFdmFs +OiAoaWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNkcnMpIChsZXQgKChjYXIxIChjYWFyIGxp +c3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlwMS13aXRoLWNkci1pdGVyYXRpdmUgKGNk +ciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEpKSAoYXBwZW5kIGNkcnMgKGxpc3QgY2Ry +MSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDogbnVsbD8KRXZhbDogbGlzdHMKQXBwbHkg +dG86ICgoKDk1My4wMTY1OSkpKQpFdmFsOiAobGV0ICgoY2FyMSAoY2FhciBsaXN0cykpIChjZHIx +IChjZGFyIGxpc3RzKSkpICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMpIChh +cHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkpCkV2YWw6 +IChjYWFyIGxpc3RzKQpFdmFsOiBjYWFyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCg5NTMuMDE2 +NTkpKSkKRXZhbDogKGNhciAoY2FyIHgpKQpFdmFsOiBjYXIKRXZhbDogKGNhciB4KQpFdmFsOiBj +YXIKRXZhbDogeApBcHBseSB0bzogKCgoOTUzLjAxNjU5KSkpCkFwcGx5IHRvOiAoKDk1My4wMTY1 +OSkpCkV2YWw6IChjZGFyIGxpc3RzKQpFdmFsOiBjZGFyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAo +KCg5NTMuMDE2NTkpKSkKRXZhbDogKGNkciAoY2FyIHgpKQpFdmFsOiBjZHIKRXZhbDogKGNhciB4 +KQpFdmFsOiBjYXIKRXZhbDogeApBcHBseSB0bzogKCgoOTUzLjAxNjU5KSkpCkFwcGx5IHRvOiAo +KDk1My4wMTY1OSkpCkV2YWw6ICh1bnppcDEtd2l0aC1jZHItaXRlcmF0aXZlIChjZHIgbGlzdHMp +IChhcHBlbmQgY2FycyAobGlzdCBjYXIxKSkgKGFwcGVuZCBjZHJzIChsaXN0IGNkcjEpKSkKRXZh +bDogdW56aXAxLXdpdGgtY2RyLWl0ZXJhdGl2ZQpFdmFsOiAoY2RyIGxpc3RzKQpFdmFsOiBjZHIK +RXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKDk1My4wMTY1OSkpKQpFdmFsOiAoYXBwZW5kIGNhcnMg +KGxpc3QgY2FyMSkpCkV2YWw6IGFwcGVuZApFdmFsOiBjYXJzCkV2YWw6IChsaXN0IGNhcjEpCkV2 +YWw6IGxpc3QKRXZhbDogY2FyMQpBcHBseSB0bzogKDk1My4wMTY1OSkKRXZhbDogeApBcHBseSB0 +bzogKCgpICg5NTMuMDE2NTkpKQpFdmFsOiAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpCkV2YWw6 +IGFwcGVuZApFdmFsOiBjZHJzCkV2YWw6IChsaXN0IGNkcjEpCkV2YWw6IGxpc3QKRXZhbDogY2Ry +MQpBcHBseSB0bzogKCgpKQpFdmFsOiB4CkFwcGx5IHRvOiAoKCkgKCgpKSkKQXBwbHkgdG86ICgo +KSAoOTUzLjAxNjU5KSAoKCkpKQpFdmFsOiAoaWYgKG51bGw/IGxpc3RzKSAoY29ucyBjYXJzIGNk +cnMpIChsZXQgKChjYXIxIChjYWFyIGxpc3RzKSkgKGNkcjEgKGNkYXIgbGlzdHMpKSkgKHVuemlw +MS13aXRoLWNkci1pdGVyYXRpdmUgKGNkciBsaXN0cykgKGFwcGVuZCBjYXJzIChsaXN0IGNhcjEp +KSAoYXBwZW5kIGNkcnMgKGxpc3QgY2RyMSkpKSkpCkV2YWw6IChudWxsPyBsaXN0cykKRXZhbDog +bnVsbD8KRXZhbDogbGlzdHMKQXBwbHkgdG86ICgoKSkKRXZhbDogKGNvbnMgY2FycyBjZHJzKQpF +dmFsOiBjb25zCkV2YWw6IGNhcnMKRXZhbDogY2RycwpBcHBseSB0bzogKCg5NTMuMDE2NTkpICgo +KSkpCkV2YWw6IChjYXIgdW56KQpFdmFsOiBjYXIKRXZhbDogdW56CkFwcGx5IHRvOiAoKCg5NTMu +MDE2NTkpICgpKSkKRXZhbDogKGNkciB1bnopCkV2YWw6IGNkcgpFdmFsOiB1bnoKQXBwbHkgdG86 +ICgoKDk1My4wMTY1OSkgKCkpKQpFdmFsOiAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkg +bWFwIChjb25zIHByb2MgY2RycykpKQpFdmFsOiBjb25zCkV2YWw6IChhcHBseSBwcm9jIGNhcnMp +CkV2YWw6IGFwcGx5CkV2YWw6IHByb2MKRXZhbDogY2FycwpBcHBseSB0bzogKCM8Q0xPU1VSRT4g +KDk1My4wMTY1OSkpCkFwcGx5IHRvOiAoOTUzLjAxNjU5KQpFdmFsOiAoZ2ltcC1pbWFnZS1hZGQt +dmd1aWRlIGltZyB2R3VpZGUpCkV2YWw6IGdpbXAtaW1hZ2UtYWRkLXZndWlkZQpFdmFsOiBpbWcK +RXZhbDogdkd1aWRlCkFwcGx5IHRvOiAoMSA5NTMuMDE2NTkpCkV2YWw6IChhcHBseSBnaW1wLXBy +b2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS1hZGQtdmd1aWRlIiB4KSkKRXZhbDogYXBwbHkK +RXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtYWRkLXZndWlk +ZSIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1pbWFnZS1hZGQtdmd1aWRlIgpFdmFsOiB4CkFw +cGx5IHRvOiAoImdpbXAtaW1hZ2UtYWRkLXZndWlkZSIgKDEgOTUzLjAxNjU5KSkKQXBwbHkgdG86 +ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAtaW1hZ2UtYWRkLXZn +dWlkZSIgMSA5NTMuMDE2NTkpKQpBcHBseSB0bzogKCJnaW1wLWltYWdlLWFkZC12Z3VpZGUiIDEg +OTUzLjAxNjU5KQpFdmFsOiAoYXBwbHkgbWFwIChjb25zIHByb2MgY2RycykpCkV2YWw6IGFwcGx5 +CkV2YWw6IG1hcApFdmFsOiAoY29ucyBwcm9jIGNkcnMpCkV2YWw6IGNvbnMKRXZhbDogcHJvYwpF +dmFsOiBjZHJzCkFwcGx5IHRvOiAoIzxDTE9TVVJFPiAoKCkpKQpBcHBseSB0bzogKCM8Q0xPU1VS +RT4gKCM8Q0xPU1VSRT4gKCkpKQpBcHBseSB0bzogKCM8Q0xPU1VSRT4gKCkpCkV2YWw6IChpZiAo +bnVsbD8gbGlzdHMpIChhcHBseSBwcm9jKSAoaWYgKG51bGw/IChjYXIgbGlzdHMpKSAnKCkgKGxl +dCogKCh1bnogKGFwcGx5IHVuemlwMS13aXRoLWNkciBsaXN0cykpIChjYXJzIChjYXIgdW56KSkg +KGNkcnMgKGNkciB1bnopKSkgKGNvbnMgKGFwcGx5IHByb2MgY2FycykgKGFwcGx5IG1hcCAoY29u +cyBwcm9jIGNkcnMpKSkpKSkKRXZhbDogKG51bGw/IGxpc3RzKQpFdmFsOiBudWxsPwpFdmFsOiBs +aXN0cwpBcHBseSB0bzogKCgoKSkpCkV2YWw6IChpZiAobnVsbD8gKGNhciBsaXN0cykpICcoKSAo +bGV0KiAoKHVueiAoYXBwbHkgdW56aXAxLXdpdGgtY2RyIGxpc3RzKSkgKGNhcnMgKGNhciB1bnop +KSAoY2RycyAoY2RyIHVueikpKSAoY29ucyAoYXBwbHkgcHJvYyBjYXJzKSAoYXBwbHkgbWFwIChj +b25zIHByb2MgY2RycykpKSkpCkV2YWw6IChudWxsPyAoY2FyIGxpc3RzKSkKRXZhbDogbnVsbD8K +RXZhbDogKGNhciBsaXN0cykKRXZhbDogY2FyCkV2YWw6IGxpc3RzCkFwcGx5IHRvOiAoKCgpKSkK +QXBwbHkgdG86ICgoKSkKRXZhbDogJygpCkFwcGx5IHRvOiAoKDQpICgpKQpFdmFsOiAoZ2ltcC1p +bWFnZS1ncmlkLXNldC1zcGFjaW5nIGltZyAxMDAgMTAwKQpFdmFsOiBnaW1wLWltYWdlLWdyaWQt +c2V0LXNwYWNpbmcKRXZhbDogaW1nCkV2YWw6IDEwMApFdmFsOiAxMDAKQXBwbHkgdG86ICgxIDEw +MCAxMDApCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS1n +cmlkLXNldC1zcGFjaW5nIiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwK +RXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtZ3JpZC1zZXQtc3BhY2luZyIgeCkKRXZhbDogY29ucwpF +dmFsOiAiZ2ltcC1pbWFnZS1ncmlkLXNldC1zcGFjaW5nIgpFdmFsOiB4CkFwcGx5IHRvOiAoImdp +bXAtaW1hZ2UtZ3JpZC1zZXQtc3BhY2luZyIgKDEgMTAwIDEwMCkpCkFwcGx5IHRvOiAoIzxGT1JF +SUdOIFBST0NFRFVSRSA5Mzk2MTEzMTU1MjQ5Nj4gKCJnaW1wLWltYWdlLWdyaWQtc2V0LXNwYWNp +bmciIDEgMTAwIDEwMCkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtZ3JpZC1zZXQtc3BhY2luZyIg +MSAxMDAgMTAwKQpFdmFsOiAoZ2ltcC1pbWFnZS1ncmlkLXNldC1vZmZzZXQgaW1nIDAgMCkKRXZh +bDogZ2ltcC1pbWFnZS1ncmlkLXNldC1vZmZzZXQKRXZhbDogaW1nCkV2YWw6IDAKRXZhbDogMApB +cHBseSB0bzogKDEgMCAwKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwgKGNvbnMgImdp +bXAtaW1hZ2UtZ3JpZC1zZXQtb2Zmc2V0IiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9j +LWRiLWNhbGwKRXZhbDogKGNvbnMgImdpbXAtaW1hZ2UtZ3JpZC1zZXQtb2Zmc2V0IiB4KQpFdmFs +OiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLWdyaWQtc2V0LW9mZnNldCIKRXZhbDogeApBcHBseSB0 +bzogKCJnaW1wLWltYWdlLWdyaWQtc2V0LW9mZnNldCIgKDEgMCAwKSkKQXBwbHkgdG86ICgjPEZP +UkVJR04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAtaW1hZ2UtZ3JpZC1zZXQtb2Zm +c2V0IiAxIDAgMCkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtZ3JpZC1zZXQtb2Zmc2V0IiAxIDAg +MCkKRXZhbDogKGdpbXAtaW1hZ2UtdW5kby1lbmFibGUgaW1nKQpFdmFsOiBnaW1wLWltYWdlLXVu +ZG8tZW5hYmxlCkV2YWw6IGltZwpBcHBseSB0bzogKDEpCkV2YWw6IChhcHBseSBnaW1wLXByb2Mt +ZGItY2FsbCAoY29ucyAiZ2ltcC1pbWFnZS11bmRvLWVuYWJsZSIgeCkpCkV2YWw6IGFwcGx5CkV2 +YWw6IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWltYWdlLXVuZG8tZW5hYmxl +IiB4KQpFdmFsOiBjb25zCkV2YWw6ICJnaW1wLWltYWdlLXVuZG8tZW5hYmxlIgpFdmFsOiB4CkFw +cGx5IHRvOiAoImdpbXAtaW1hZ2UtdW5kby1lbmFibGUiICgxKSkKQXBwbHkgdG86ICgjPEZPUkVJ +R04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAtaW1hZ2UtdW5kby1lbmFibGUiIDEp +KQpBcHBseSB0bzogKCJnaW1wLWltYWdlLXVuZG8tZW5hYmxlIiAxKQpFdmFsOiAoZ2ltcC1maWxl +LXNhdmUgUlVOLU5PTklOVEVSQUNUSVZFIGltZyAoY2FyIChnaW1wLWltYWdlLWdldC1hY3RpdmUt +bGF5ZXIgaW1nKSkgIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovcmVmX2d1aWRlcy5zdmcueGNmIiAi +L3RtcC9naW1wLW91dC0zc2gyNXhuai9yZWZfZ3VpZGVzLnN2Zy54Y2YiKQpFdmFsOiBnaW1wLWZp +bGUtc2F2ZQpFdmFsOiBSVU4tTk9OSU5URVJBQ1RJVkUKRXZhbDogaW1nCkV2YWw6IChjYXIgKGdp +bXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciBpbWcpKQpFdmFsOiBjYXIKRXZhbDogKGdpbXAtaW1h +Z2UtZ2V0LWFjdGl2ZS1sYXllciBpbWcpCkV2YWw6IGdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXll +cgpFdmFsOiBpbWcKQXBwbHkgdG86ICgxKQpFdmFsOiAoYXBwbHkgZ2ltcC1wcm9jLWRiLWNhbGwg +KGNvbnMgImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciIgeCkpCkV2YWw6IGFwcGx5CkV2YWw6 +IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5 +ZXIiIHgpCkV2YWw6IGNvbnMKRXZhbDogImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXllciIKRXZh +bDogeApBcHBseSB0bzogKCJnaW1wLWltYWdlLWdldC1hY3RpdmUtbGF5ZXIiICgxKSkKQXBwbHkg +dG86ICgjPEZPUkVJR04gUFJPQ0VEVVJFIDkzOTYxMTMxNTUyNDk2PiAoImdpbXAtaW1hZ2UtZ2V0 +LWFjdGl2ZS1sYXllciIgMSkpCkFwcGx5IHRvOiAoImdpbXAtaW1hZ2UtZ2V0LWFjdGl2ZS1sYXll +ciIgMSkKQXBwbHkgdG86ICgoNCkpCkV2YWw6ICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL3JlZl9n +dWlkZXMuc3ZnLnhjZiIKRXZhbDogIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovcmVmX2d1aWRlcy5z +dmcueGNmIgpBcHBseSB0bzogKDEgMSA0ICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL3JlZl9ndWlk +ZXMuc3ZnLnhjZiIgIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovcmVmX2d1aWRlcy5zdmcueGNmIikK +RXZhbDogKGFwcGx5IGdpbXAtcHJvYy1kYi1jYWxsIChjb25zICJnaW1wLWZpbGUtc2F2ZSIgeCkp +CkV2YWw6IGFwcGx5CkV2YWw6IGdpbXAtcHJvYy1kYi1jYWxsCkV2YWw6IChjb25zICJnaW1wLWZp +bGUtc2F2ZSIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1maWxlLXNhdmUiCkV2YWw6IHgKQXBw +bHkgdG86ICgiZ2ltcC1maWxlLXNhdmUiICgxIDEgNCAiL3RtcC9naW1wLW91dC0zc2gyNXhuai9y +ZWZfZ3VpZGVzLnN2Zy54Y2YiICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL3JlZl9ndWlkZXMuc3Zn +LnhjZiIpKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQUk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgi +Z2ltcC1maWxlLXNhdmUiIDEgMSA0ICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL3JlZl9ndWlkZXMu +c3ZnLnhjZiIgIi90bXAvZ2ltcC1vdXQtM3NoMjV4bmovcmVmX2d1aWRlcy5zdmcueGNmIikpCkFw +cGx5IHRvOiAoImdpbXAtZmlsZS1zYXZlIiAxIDEgNCAiL3RtcC9naW1wLW91dC0zc2gyNXhuai9y +ZWZfZ3VpZGVzLnN2Zy54Y2YiICIvdG1wL2dpbXAtb3V0LTNzaDI1eG5qL3JlZl9ndWlkZXMuc3Zn +LnhjZiIpCkdpdmVzOiAoI3QpCnRzPiAKRXZhbDogKGdpbXAtcXVpdCAwKQpFdmFsOiBnaW1wLXF1 +aXQKRXZhbDogMApBcHBseSB0bzogKDApCkV2YWw6IChhcHBseSBnaW1wLXByb2MtZGItY2FsbCAo +Y29ucyAiZ2ltcC1xdWl0IiB4KSkKRXZhbDogYXBwbHkKRXZhbDogZ2ltcC1wcm9jLWRiLWNhbGwK +RXZhbDogKGNvbnMgImdpbXAtcXVpdCIgeCkKRXZhbDogY29ucwpFdmFsOiAiZ2ltcC1xdWl0IgpF +dmFsOiB4CkFwcGx5IHRvOiAoImdpbXAtcXVpdCIgKDApKQpBcHBseSB0bzogKCM8Rk9SRUlHTiBQ +Uk9DRURVUkUgOTM5NjExMzE1NTI0OTY+ICgiZ2ltcC1xdWl0IiAwKSkKQXBwbHkgdG86ICgiZ2lt +cC1xdWl0IiAwKQ== + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="ref_guides.svg.xcf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: ref_guides.svg.xcf + +Z2ltcCB4Y2YgZmlsZQAAAAPoAAAD6AAAAAAAAAARAAAAAQEAAAASAAAAFAAAA7kCAAAALgIAAAAx +AQAAA7cBAAAAEwAAAAhCwAAAQsAAAAAAABQAAAAEAAAAAgAAABYAAAAEAAAAAQAAABUAAAEeAAAA +EGdpbXAtaW1hZ2UtZ3JpZAAAAAABAAABAihzdHlsZSBzb2xpZCkKKGZnY29sb3IgKGNvbG9yLXJn +YmEgMC4wMDAwMDAgMC4wMDAwMDAgMC4wMDAwMDAgMS4wMDAwMDApKQooYmdjb2xvciAoY29sb3It +cmdiYSAxLjAwMDAwMCAxLjAwMDAwMCAxLjAwMDAwMCAxLjAwMDAwMCkpCih4c3BhY2luZyAxMDAu +MDAwMDAwKQooeXNwYWNpbmcgMTAwLjAwMDAwMCkKKHNwYWNpbmctdW5pdCBpbmNoZXMpCih4b2Zm +c2V0IDAuMDAwMDAwKQooeW9mZnNldCAwLjAwMDAwMCkKKG9mZnNldC11bml0IGluY2hlcykKAAAA +AAAAAAAAAAABoQAAAAAAAAAAAAAD6AAAA+gAAAABAAAAB1NsaWRlMgAAAAACAAAAAAAAAAYAAAAE +AAAA/wAAAAgAAAAEAAAAAQAAAAkAAAAEAAAAAAAAABwAAAAEAAAAAAAAAAoAAAAEAAAAAAAAAAsA +AAAEAAAAAAAAAAwAAAAEAAAAAAAAAA0AAAAEAAAAAAAAAA8AAAAIAAAAAAAAAAAAAAAHAAAABAAA +AAAAAAAUAAAABAAAAAIAAAAAAAAAAAAAAlgAAAAAAAAD6AAAA+gAAAAEAAACfAAB7AUAAewRAAHs +HQAB7CkAAAAAAAAD6AAAA+gAAAaIAAAGmAAABqgAAAa4AAAGyAAABtgAAAboAAAG+AAABwgAAAcY +AAAHKAAABzgAAAdIAAAHWAAAB2gAAAd4AAAHiAAAB5gAAAeoAAAHuAAAB8gAAAssAAALWAAADsQA +ABH6AAASJgAAFWQAABn4AAAaLAAAHsgAAB7YAAAe6AAAHvgAAB8IAAAfGAAAHygAAB84AAAmuAAA +JsgAAC5IAAA1SAAANVgAADxYAABGmAAARqgAAFDoAABQ+AAAUQgAAFEYAABRKAAAUTgAAFFIAABR +WAAAUnEAAFKdAABTrgAAVLsAAFTnAABV7AAAV1UAAFeJAABY6QAAWPkAAFkJAABZGQAAWSkAAFtT +AABfbgAAX34AAF+OAABfngAAX64AAF++AABfzgAAX94AAF/uAABf/gAAYrIAAGXQAABl4AAAZfAA +AGYAAABuDAAAb14AAHX2AAB2BgAAdhYAAHYmAAB4YAAAeHAAAHiAAAB4kAAAeKAAAIWWAACQywAA +k/AAAJQAAACUEAAAlbEAAJk9AACZTQAAmV0AAJltAACa5wAAprUAAKnfAACtkQAAraEAAK2xAACy +uAAAuA4AALi5AAC4yQAAuNkAALooAAC95wAAvfcAAL4HAAC//wAAx7sAANLuAADfdAAA5GEAAORx +AADkgQAA5X0AAOgVAADoJQAA6DUAAOhFAADxJwAA8yMAAPoYAAD6KAAA+nYAAP9LAAEOYgABGBsA +AR43AAEeRwABHlcAASs8AAEzzgABOqcAATq3AAE6xwABPbwAAULyAAFDEgABQyIAAUMyAAFD/gAB +S2oAAUx0AAFNvAABTcwAAU3cAAFSxQABWZUAAVrgAAFa8AABWwAAAVtcAAFd2AABXegAAV34AAFe +CAABXhgAAV5uAAFefgABXo4AAV6eAAFergABXuMAAWALAAFgGwABYCsAAWA7AAFrNgABcE8AAXZf +AAF2bwABdn8AAXaPAAF2nwABdq8AAXa/AAF2zwABdt8AAYPDAAGLIQABkhAAAZIgAAGSMAABl2oA +AZ52AAGe9gABosQAAaL4AAGmQAABqWcAAambAAGtogABsEAAAbB0AAG6YgABwmwAAcPIAAHD2AAB +w+gAAcP4AAHECAABxBgAAco4AAHKWAABztgAAdN2AAHTlgAB2fcAAd53AAHehwAB5QcAAeUXAAHl +JwAB5TcAAeVHAAHlVwAB5WcAAeV3AAHm0wAB5vcAAehNAAHozAAB6OQAAelbAAHqCwAB6i8AAerV +AAHq5QAB6vUAAesFAAHrFQAB6yUAAes1AAHrRQAB61UAAetlAAHrdQAB64UAAeuVAAHrpQAB67UA +AevFAAHr1QAB6+UAAev1AAAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8Q +AAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfwjs +AP2fpKUQpSoA/JKx0dwQ3CoA/aTR+xH7KgD9pd/7EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977Efsq +AP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA +/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9 +o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j +3vsR+38JLAD9F1lxEHErAP5YrRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0r +AP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA +/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+ +dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa1/CSwA/QkgKBAoKwD+Hz4RPisA/ik+ET4r +AP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA +/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+ +KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4p +PhE+fwjsAP0IXHcQdyoA/AfS0sQQxCoA/VzTgBGAKgD9f7+AEYAqAP2AwIARgCoA/YDAgBGAKgD9 +gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2A +wIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDA +gBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCA +EYAqAP2AwIARgH8IwAA/pT/cfwbA+38JAAA/cX8GwK1/CQAAPyh/BsA+fwjAAD93P8R/BsCAfwjA +AA2l/aSSAC4ADdz80LGSAC0ADvv90aQALQAO+/3fpQAtAA77/d6jAC0ADvv93qMALQAO+/3eowAt +AA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0A +Dvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO ++/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77 +/d6jAC0AfwkAAA1x/VkXAC4ADq3+VwAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50 +AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQA +LgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAu +AA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4AfwkAAA0o/SAJAC4ADj7+HwAuAA4+ +/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+ +KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4p +AC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikA +LgAOPv4pAC4AfwjAAA13/VwHAC4ADcT80tEHAC0ADoD901oALQAOgP2/fwAtAA6A/cCAAC0ADoD9 +wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3A +gAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCA +AC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAA +LQAOgP3AgAAtAA6A/cCAAC0AfwjzAPyApKOkCKQyAPylrsnQCNAyAPyjyef7CPsyAP2k0PsJ+zIA +/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9 +pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k +0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ ++wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7fwk0AP0TSVcIVzMA/UmErQitMwD+V60JrTMA/let +Ca0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60J +rTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmt +MwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa1/ +CTQA/QcaHwgfMwD9Gi8+CD4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+ +CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4J +PjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+ +MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPn8I8wD8AnPc/wj/MgD+dP8K/zIA/Nz/qIAIgDIA +/f7/gAmAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB +/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqA +MgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAMgAB/wqAfwjAAD+kP9B/BsD7fwkA +AD9XfwbArX8JAAA/H38GwD5/CMAAfwCA/38GwIB/CMAAFaQBo/6AACUAFdD8yK6kACUAFfv85cmk +ACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQA +JQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAl +ABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUA +Fvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlAH8JAAAVV/1JEwAmABWt/YNI +ACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcA +JgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAm +ABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYA +Fq3+VwAmABat/lcAJgB/CQAAFR/9GgcAJgAVPv0vGgAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+ +/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+ +HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4f +ACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAfwjAABX//NxyAgAl +ABf//nMAJQAVgPyp/9sAJQAWgP3//gAlABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaA +Af8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8m +ABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaA +Af8mAH8IuQD+n6QEpDcA/aejpASkNwD7paSwy9AC0DYA+/+kpM3QA9A2APqqpKfQ0fsC+zYA+qKk +qNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ +0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7 +Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7 +NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA ++qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7fwk6AP0YTFcCVzgA/QFQ +VwNXOAD8B1dbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8 +CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdb +rQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtfwk6AP0JGx8CHzkA/hwfAx84APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwD +HyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+ +Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44 +APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwD +HyA+Aj44APwDHyA+Aj44APwDHyA+Aj44APwDHyA+Aj5/CLkA/Big4f8C/zcA/R3q/wT/NwD+rP8F +/zYA/QHw/wX/NgD+Ff8B//71gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70 +gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B +//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+ +Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKAfwiAAH8AgKR/AIDQfwaA+38JAAB/ +AIBXfwaArX8JAAB/AIAffwaAPn8IgAB/AQD/fwaAgH8IgAAcpP2jmQAfAB6k/qoAHgAa0PrPyKuk +pQAeABzQ/MSkpAAeABr7+vLQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4A +Gvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7 ++vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r0 +0MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDM +pKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSk +AB4AGvv69NDMpKQAHgB/CQAAGlf8VkYPACAAHFf+QQAgABqt/J5XTwAgABqt/KBXTwAgABqt/KBX +TwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAg +ABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt +/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBX +TwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgABqt/KBXTwAgAH8JAAAbH/0ZBQAgABwf/hcA +IAAaPvw4HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAa +Pvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5 +HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwA +IAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAaPvw5HxwAIAAa +Pvw5HxwAIAB/CIAAGv/7/diLCgAfAB3//dIJAB4AHv/+fwAeAB7//sUAHgAagP6M/wH//ugAHgAa +gP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukA +HgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH/ +/ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L +/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAa +gP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukAHgAagP6L/wH//ukA +HgAagP6L/wH//ukAHgB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoA +AH8KAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAKgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe ++xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977 +EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR ++yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7 +KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977Efsq +AP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA +/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9 +o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j +3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe+xH7KgD9o977EfsqAP2j3vsR+yoA/aPe ++xH7KgD9o977EfsrAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50 +rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nSt +Ea0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0R +rSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGt +KwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0r +AP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA +/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+ +dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50rRGtKwD+dK0RrSsA/nStEa0rAP50 +rRGtKwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ +ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4R +PisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+ +KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4r +AP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA +/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+ +KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4p +PhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPisA/ik+ET4rAP4pPhE+KwD+KT4RPioA/YDA +gBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCA +EYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIAR +gCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGA +KgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAq +AP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA +/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9 +gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2A +wIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDA +gBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAKgD9gMCAEYAqAP2AwIARgCoA/YDAgBGAfxAA+38Q +AK1/EAA+fxAAgA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAt +AA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0A +Dvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO ++/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77 +/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv9 +3qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3e +owAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6j +AC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMA +LQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAtAA77/d6jAC0ADvv93qMALQAO+/3eowAt +AA77/d6jAC0ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAu +AA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4A +Dq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAO +rf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t +/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+ +dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50 +AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQA +LgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAuAA6t/nQALgAOrf50AC4ADq3+dAAu +AA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4A +Dj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAO +Pv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+ +/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+ +KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4p +AC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikA +LgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAu +AA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOPv4pAC4ADj7+KQAuAA4+/ikALgAOgP3AgAAt +AA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0A +DoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAO +gP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A +/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9 +wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3A +gAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCA +AC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAA +LQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAt +AA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtAA6A/cCAAC0ADoD9wIAALQAOgP3AgAAtADIA/aTQ+wn7 +MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7Cfsy +AP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA +/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9 +pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k +0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ ++wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7 +CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ ++zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7 +MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MgD9pND7CfsyAP2k0PsJ+zIA/aTQ+wn7MwD+V60JrTMA +/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+ +V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5X +rQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/let +Ca0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60J +rTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmt +MwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0z +AP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA +/letCa0zAP5XrQmtMwD+V60JrTMA/letCa0zAP5XrQmtMwD+V60JrTMA/h8+CT4zAP4fPgk+MwD+ +Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4f +Pgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+ +CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4J +PjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+ +MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4z +AP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA +/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4zAP4fPgk+MwD+ +Hz4JPjMA/h8+CT4zAP4fPgk+MwD+Hz4JPjMA/h8+CT4yAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAy +AAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/ +CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAy +AAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/ +CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAy +AAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/ +CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAyAAH/CoAy +AAH/CoAyAAH/CoAyAAH/CoB/EAD7fxAArX8QAD5/EACAFvv90KQAJQAW+/3QpAAlABb7/dCkACUA +Fvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW ++/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7 +/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv9 +0KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3Q +pAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCk +ACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQA +JQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAl +ABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAW+/3QpAAlABb7/dCkACUA +Fvv90KQAJQAW+/3QpAAlABb7/dCkACUAFvv90KQAJQAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5X +ACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcA +JgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAm +ABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYA +Fq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAW +rf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat +/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+ +VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5XACYAFq3+VwAmABat/lcAJgAWrf5X +ACYAFq3+VwAmABat/lcAJgAWrf5XACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8A +JgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAm +ABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYA +Fj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAW +Pv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+ +/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+ +HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4f +ACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8AJgAWPv4fACYAFj7+HwAmABY+/h8A +JgAWPv4fACYAFj7+HwAmABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8m +ABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaA +Af8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8m +ABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaA +Af8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8m +ABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaA +Af8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8mABaAAf8m +ADYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2 +APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6 +oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKk +qNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ +0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7 +Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7 +NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA ++qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqi +pKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo +0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS ++wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC ++zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2APqipKjQ0vsC+zYA+qKkqNDS+wL7NgD6oqSo0NL7Avs2 +APqipKjQ0vsC+zYA+qKkqNDS+wL7OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8 +CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdb +rQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8 +CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdb +rQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8 +CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdb +rQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKt +OAD8CFdbrQKtOAD8CFdbrQKtOAD8CFdbrQKtOAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8 +Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8g +PgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+ +OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8 +Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8g +PgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+ +OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8 +Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8g +PgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+ +OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8 +Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+OAD8Ax8gPgI+NgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70 +gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B +//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+ +Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70 +gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B +//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+ +Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70 +gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B +//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+ +Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKA +NgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70gAKANgD+Fv8B//70 +gAKAfxAA+38QAK1/EAA+fxAAgBr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQ +zKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00Myk +pAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQA +HgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4A +Gvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7 ++vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r0 +0MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDM +pKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSk +AB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAe +ABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa ++/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv6 +9NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQ +zKSkAB4AGvv69NDMpKQAHgAa+/r00MykpAAeABr7+vTQzKSkAB4AGq38oFdPACAAGq38oFdPACAA +Gq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38 +oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdP +ACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAA +Gq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38 +oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdP +ACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAA +Gq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38 +oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdP +ACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAA +Gq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGq38oFdPACAAGj78OR8cACAAGj78 +OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8c +ACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAA +Gj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78 +OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8c +ACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAA +Gj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78 +OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8c +ACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAA +Gj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78 +OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGj78OR8cACAAGoD+i/8B +//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+ +i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4AGoD+i/8B//7pAB4A +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 +EQAfAPoUMFx8l60WrfqXe1wvFAAZAPoMKFJ/pq0crfqmf1InDAAUAPsPNHGcrSKt+5xyNw8AEgD9 +dKatJq37pnU7EgAQACut+6h4NAkADgAtrfyiZCMADQAvrfyMSBAACwAwrfyrbSAACgAyrfyFNAQA +CAAzrfyaTgwABwA0rfynWxIABgA1rfysZBUABQA3rf1sGQAEADit/WwVAAMAOa39ZBIAAgA5rfyr +WgwAAQA6rfqnTQUAAK06rf2bMwAAAH8LDADrAwkNERgdICImJycmIiAdGBENCQMAJgD4BQsVIisw +Nz4LPvc9NzArIxcNBgAfAPoHESEsNj4WPvo2LCARBwAZAPoDDh4tOz4cPvo7LRwOAwAUAPsGEyg4 +PiI++zgoFAYAEgD9Kjs+Jj77OykVBwAQACs++zwrEwQADgAtPvw6JAwADQAvPvwyGgYACwAwPvw9 +JwsACgAyPvwvEwIACAAzPvw3GwUABwA0Pvw7IAYABgA1Pvw9JAcABQA3Pv0mCAAEADg+/SYHAAMA +OT79IwcAAgA5Pvw9IAUAAQA6Pvo7GwIAAD46Pv03EgAAAH8KzwDxCzFEVWBsd3dsYFVEMQoAKwDn +I2SZw+f44NXNyMXCwsXIzdXg+OfDmGMjACIA9hRepObryrajj4ALgPWBkKO2zO3mpV0TABsA+AdT +t/POs5OAFoD4k7TO87ZSBwAWAPklmvDXr4aAHID5hq/X75kkABMA+6vwvY6AIoD6jr7wqSsAEQD9 +uIaAJoD6hrrvtCoADwArgPqEt/CMCwANAC2A+4nH6V8ADAAvgPuf47EQAAoAMID7gsDlOQAJADKA ++6fveQEABwAzgPuQ36QEAAYANID7hdW5CgAFADWA+4HJzhQABAA3gPzC1xIAAwA4gPzCzQsAAgA5 +gPzLugQAAQA5gPmC1aQBAACAOYD6heBxAACAOoD8j+45AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8JPwD+ogA4APyfo6OkAaQ1APydpaOkBaQyAP2fpqQJpDAA/qWkDKQtAP6qpA+kKwD9 +qqOkEKQpAP2kpaQSpCcA/f+jpBSkJgD+p6QWpCQA/p+kGKQjABukIQD9v6OkGqQgAP6npBykHwD+ +pqQdpB4A/qWkHqQcAP7/pCCkGwD+v6QdpPuosr7LABkA/qKkG6T8qrvK0ALQGQD+oqQZpPyot8bQ +BdAYAP6ZpBik/Km9ztAH0BcA/v+kF6T8qb3O0AnQFwD+paQVpPylu8/QC9AWABek/bHL0A3QFQD+ +o6QUpP2pxdAP0BQA/qekFKT9sc3QENATAP6/pBSk/rvQEtATAP6jpBKk/ajG0BPQfw18APsIHTRM +ADcA/A4uSlcCVzUA/AcmRVcFVzMA/AoxVFcHVzEA/AsxVFcJVy8A/AQuVlcLVy4A/RpNVw1XLAD9 +C0FXD1crAP0bUVcQVykA/QIuVxJXKAD9CUVXE1d/DXwA+wMKExsANwD8BRAbHwIfNQD8Ag0ZHwUf +MwD8BBIeHwcfMQD8BBIeHwkfLwD9AREfDB8uAP0JHB8NHywA/QQXHw8fKwD9Ch0fEB8pAP0BER8S +HygA/QMZHxMffwk/AP4WADgA+RhZmcjv/wA0APoNRIjM/v8D/zIA+whNqvr/B/8wAPwzkez/Cv8t +APwJbd7/Df8rAPwMb+X/D/8pAPwOd+3/Ef8nAPwBXuv/E/8mAP0xx/8V/yQA/BCR/P8W/yMA/Uzp +/xj/IQD8BID9/xn/IAD9HcT/G/8fAP1N7f8c/x4A/Xf+/x3/HAD9AYr/H/8bAP0Enf8g/xoA/Qu2 +/yH/GQD9C8X/Iv8YAP0Ftv8j/xcA/QGg/yT/FwD+jf8l/xYA/nn/Jv8VAP1L/v8m/xQA/R3s/yf/ +EwD9BMT/KP8TAP6L/yn/fwkAAPylpKOkDKT7o6SlogApABakAaP+nwAkABqk/KOloQAgAB6k/aOi +AB0AIaT9pf8AGgAkpP6fABgAJKQBo/6qABYAJ6T9o6oAFAAppP2jqgASACuk/qUAEQAtpP6hAA8A +L6QPADCk/pkADAAxpP6iAAsAMqT+owAKADOk/qUACQDrp660u8HGyMrNz8/NysjGwru0rqekIKT+ +gAAHABPQ+8zBtamkHaT+mQAGABfQ/Mm7q6QbpP6dAAUAGtD8xreopBmk/qIABAAc0PzPvqikGKT+ +qgADAB/Q/cCqpBek/oAAAgAg0PzPvaakFaT+pQACACLQ/My0o6QUpP6lAAEAJND9xamkFKT8owAA +0CTQ/c6ypBSk/aUA0CbQ/b2lpBOk/pnQJ9D9x6ekE6R/DQAA6wYUIS48REhLUVVVUUtIRDsuIRQG +ACoAE1f7TjojCwAmABdX/EotDgAjABpX/EUlBwAgABxX/FU0CgAeAB5X/FU3DQAcACBX/FYxBQAa +ACJX/U4gABkAJFf9QAsAFwAlV/1SHQAWACdX/TECABQAKFf9RAgAEwB/DQAA6wIHDBEVGBobHR4e +HRsaGBURDAcCACoAEx/7HBUMBAAmABcf/BoQBQAjABof/BgNAgAgABwf/B4TBAAeAB4f/B4UBQAc +ACEf/RICABoAIh/9HAsAGQAkH/0XBAAXACUf/R0KABYAJx/9EgEAFAAoH/0YAwATAH8JAADqPmWL +qrvH0t3u+fnu3dLGu6mLZT4WACkAFP/67siZWRgAJAAZ//vdmVUTACAAHP/7/LteCwAdAB//+/Gi +RAEAGgAi//zdawgAGAAk//zqgA8AFgAm//zxiBIAFAAo//zubwMAEgAq//3NNgARACv//P2iEwAP +AC3//ehJAA4ALv/8/pEFAAwAMP/9ySEACwAx//3sSwAKADL//f50AAkANP/9kQIABwA1//2jBQAG +ADb//bsNAAUAN//9xAsABAA4//27BgADADn//aUCAAIAOv/+kwACADv//nQAAQA7//v+TgAA/zv/ +/O0fAP88//3HBf89/wCHfxAAAH8QAAB/EAAAfxAAAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8Q +AAB/EAAAKwD8n7Tn+w/7KwD9q9n7EPsqAPyjyfn7EPspAPydter7EfspAP2p1fsS+ygA/KK/9vsS ++ygA/azi+xP7JwD8pMH5+xP7JwD9qt77FPsmAPyov/f7FPsmAP2o3fsV+yUA/Kq48vsV+yUA/aTN ++xb7JQD9ruP7FvskAPyhvPf7FvskAP2j0vsX+yQA/arj+xf7JAD9tfH7F/sjAP2jwvsY+yMA/aPU ++xj7IwD9quD7GPsjAP2x6fsY+yMA/bbx+xj7IgD8orz5+xj7IgD9pcb7GfsiAP2lzPsZ+yIA/aPQ ++xn7IgD9pdX7GfsiAP2k2PsZ+yIA/aPd+xn7IgD9o937GfsiAP2k2PsZ+yIA/aXV+xn7IgD9o9D7 +GfsiAP2kzPsZ+yIA/aXF+xn7IgD8orz5+xj7IwD9tfP7GPsjAP2x6PsY+yMA/ani+xj7IwD9o9T7 +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 +/alIrT2t/oytfw0+rf6MrTyt/alGrTyt/WgQrTut/IMfAK06rfuZMgAArTmt+qZMBQAArTit/KtZ +DQABADmt/WIPAAIAPD78MAsAPjw+/SYGPjw+/TwaPj0+/jI+fw0+Pv4yPjw+/TwYPjw+/SUGPjs+ +/C8LAD46Pvs3EgAAPjk++jsbAgAAPjg+/D0gBQABADk+/SMGAAIAPID8puUSgDyA/cWygDyA/YPk +gD2A/p6Afw0+gP6fgDyA/YPlgDyA/caugDuA/KnhD4A6gPuR7zMAgDmA+obhbgAAgDiA/ILWoQAB +ADmA/Mq4BAABAH8AgAD+pQA9AP21qgA8AP3WpgA8APz0vaQAOwD8++CrADsA+/v3waIAOgAB+/3f +qwA6AAH7/Pa+pQA5AAL7/d2oADkAAvv88biSADgAA/v9zaMAOAAD+/3irAA4AAP7/Pa8oQA3AAT7 +/dGkADcABPv94awANwAE+/3vtQA3AAX7/cGiADYABfv906QANgAF+/3gqgA2AAX7/eixADYABfv9 +8bYANgAF+/z5u5kANQAG+/3FpgA1AAb7/c2lADUABvv90KQANQAG+/3VowA1AAb7/dekADUABvv9 +3aQANQAG+/3dpAA1AAb7/dekADUABvv91aMANQAG+/3QpAA1AAb7/c2lADUABvv9xaYANQAF+/z5 +u5kANQAF+/3xtgA2AAX7/eivADYABfv94akANgAF+/3VowA2AAX7/cGnADYABPv97rUANwAE+/3j +qgA3AAT7/dCjADcAA/v89ryhADcAA/v95KwAOAAD+/3MpQA4AAL7/PO4kgA4AAL7/dupADkAAfv8 +9r2lADkAAfv93qsAOgD7+/fApgA6APz74asAOwD89L2mADsA/dWrADwA/bWiADwA/qUAfwG+AH8A +wAD+IQA9AP1jCQA8AP2gMwA8APyteBEAOwD8rag5ADsAAa39dREAOgABrf2kNAA6AAKt/XEKADkA +Aq39mycAOQADrf5QADkAA639fRMAOAADrf2kLgA4AASt/loAOAAErf17DgA3AASt/ZYjADcABa3+ +OQA3AAWt/l8ANwAFrf15CgA2AAWt/YcZADYABa39miMANgAFrf2sLwA2AAat/kMANgAGrf5QADYA +Bq3+VwA2AAat/mAANgAGrf5nADYABq3+cAA2AAat/nAANgAGrf5nADYABq3+YAA2AAat/lcANgAG +rf5QADYABq3+QwA2AAWt/awuADYABa39mSQANgAFrf2HGQA2AAWt/XkKADYABa3+XwA3AAWt/jkA +NwAErf2VIwA3AASt/XsOADcABK3+WQA4AAOt/aQuADgAA639fRMAOAADrf5QADkAAq39myYAOQAC +rf1wCgA5AAGt/aQ0ADoAAa39dA4AOgD8rac3ADsA/K12EAA7AP2eMgA8AP1hCQA8AP4gAH8B/gB/ +AMAA/gwAPQD9IwQAPAD9ORIAPAD8PisGADsA/D48FAA7AAE+/SkGADoAAT79OxMAOgACPv0oAwA5 +AAI+/TcOADkAAz7+HAA5AAM+/S0HADgAAz79OxEAOAAEPv4gADgABD79LAUANwAEPv01DAA3AAU+ +/hUANwAFPv4iADcABT79KwMANgAFPv0wCQA2AAU+/TcNADYABT79PRAANgAGPv4YADYABj7+HQA2 +AAY+/h8ANgAGPv4iADYABj7+JQA2AAY+/igANgAGPv4oADYABj7+JQA2AAY+/iIANgAGPv4fADYA +Bj7+HQA2AAY+/hgANgAFPv09EAA2AAU+/TcMADYABT79MAkANgAFPv0rAwA2AAU+/iIANwAFPv4U +ADcABD79NQwANwAEPv0sBQA3AAQ+/iAAOAADPv07EQA4AAM+/S0HADgAAz7+HAA5AAI+/TcOADkA +Aj79KAMAOQABPv07EgA6AAE+/SkFADoA/D47EwA7APw+KgYAOwD9OBIAPAD9IwQAPAD+CwB/Af4A +fwCAAP5SAD0A/eYMADwA/cyMADwA/IvwKgA7APyAt7MAOwD7gITtLAA6AAGA/bqpADoAAYD8h/El +ADkAAoD9vpgAOQACgPyP7wcAOAADgP3YUAA4AAOA/bGzADgAA4D8h/MTADcABID9z1oANwAEgP21 +oAA3AASA/ZTjADcABYD97CEANgAFgP3MYgA2AAWA/beWADYABYD9pMEANgAFgP2Q5gA2AAWA/IH4 +CgA1AAaA/eEuADUABoD91UQANQAGgP3PUQA1AAaA/cpeADUABoD9xmsANQAGgP3BeQA1AAaA/cF5 +ADUABoD9xmsANQAGgP3KXgA1AAaA/c9RADUABoD91UQANQAGgP3iLgA1AAWA/IH4CgA1AAWA/ZHl +ADYABYD9pMAANgAFgP24lQA2AAWA/cxhADYABYD97SAANgAEgP2V4wA3AASA/bWfADcABID90FkA +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 +Ex8QH/4oPg0+GwD9BB4fDx/+JT4OPhsA/hIfDx/9ITs+Dj4aAP0DHh8PH/40Pg8+GgD+DR8PH/4q +PhA+GgD+GR8OH/0hPD4QPhkA/gUfDx/+MT4RPhkA/hAfDh/+Iz4SPhkA/hsfDh/+MT4SPhgA/gMf +Dh/+Iz4TPhgA/gsfDh/+LT4TPhgA/hMfDh/+Oj4TPhgA/hsfDR/+JT4UPhcA/gIfDh/+Lj4UPhcA +/gcfDh/+OD4UPhcA/gwfDR/+Ij4VPhcA/hEfDR/+Jj4VPhcA/hUfDR/+Kj4VPhcA/hgfDR/+Lz4V +PhcA/hofDR/+ND4VPhcA/hsfDR/+Nz4VPhcA/h0fDR/+Oj4VPhcA/h4fDR/+PD4VPhcA/h4fDR/+ +PD4VPhcA/h0fDR/+Oj4VPhcA/hsfDR/+Nz4VPhcA/hofDR/+ND4VPhcA/hgfDR/+Lz4VPhcA/hUf +DR/+Kj4VPhcA/hEfDR/+Jj4VPhcA/gwfDR/+IT4VPhcA/gcfDh/+OD4UPhcA/gIfDh/+LT4UPhgA +/hsfDR/+JT4UPhgA/hMfDh/+Oj4TPhgA/gsfDh/+LD4TPhgA/gMfDh/+Iz4TPhkA/hofDh/+MD4S +PhkA/hAfDh/+Iz4SPhkA/gUfDx/+MD4RPhoA/hkfDh/9ITw+ED4aAP4NHw8f/ik+ED4aAP0CHh8P +H/40Pg8+GwD+Eh8PH/0hOz4OPhsA/QMeHw8f/iU+Dj4cAP4THxAf/ic+DT4cAP4EHxEf/io+DD4d +AP4RHxEf/io+Cz4dAP0CHB8RH/4oPgo+EgD9Sv7/Kf8RAP0R6f8q/xEA/pb/K/8QAP0z/P8r/w8A +/QLK/yz/DwD+aP8r//371AANAP0S7v8p//vlsYeAAA0A/oD/KP/94qaAAoANAP0N7f8m//3sooAE +gA0A/nb/Jf/8+76DgAWADAD9COb/JP/975uAB4AMAP5s/yT//dSGgAiACwD9At7/I//+xYAKgAsA +/kD/I//+uYALgAsA/p3/Iv/+uoAMgAoA/Qnw/yH//sWADYAKAP5Z/yH//tSADoAKAP63/yD//e2H +gA6ACQD9E/v/H//9+5iAD4AJAP5T/yD//r6AEIAJAP6U/x///e2EgBCACQD+1f8f//6igBGACAD9 +F/7/Hv/+34ASgAgA/lr/H//+ooASgAgA/pr/Hv/+5YATgAgA/sj/Hv/+sYATgAgA/u//Hf/9+4iA +E4AHAP4X/x7//tSAFIAHAP4+/x7//q2AFIAHAP5l/x7//o2AFIAHAP6M/x3//uuAFYAHAP6s/x3/ +/tCAFYAHAP66/x3//ryAFYAHAP7H/x3//qmAFYAHAP7T/x3//peAFYAHAP7g/x3//o+AFYAHAP7t +/x3//omAFYAHAP75/x3//oOAFYAHAP75/x3//oOAFYAHAP7t/x3//omAFYAHAP7g/x3//o+AFYAH +AP7T/x3//piAFYAHAP7H/x3//qmAFYAHAP66/x3//ryAFYAHAP6s/x3//tCAFYAHAP6M/x3//uyA +FYAHAP5l/x7//o2AFIAHAP49/x7//q6AFIAHAP4W/x7//tSAFIAIAP7u/x3//fuIgBOACAD+yP8e +//6ygBOACAD+mf8e//7lgBOACAD+Wf8f//6jgBKACAD9Fv7/Hv/+4oASgAkA/tX/H//+pIARgAkA +/pP/H//97YSAEIAJAP5S/yD//r+AEIAJAP0S+/8f//38mYAPgAoA/rX/IP/97oeADoAKAP5Y/yH/ +/tWADoAKAP0I7/8h//7KgA2ACwD+nP8i//67gAyACwD+Pv8j//67gAuACwD9Ad3/I//+x4AKgCnQ +/cuqpBKkKtD9zKykEaQr0P3NrqQQpCzQ/c2tpA+kAdDv1Nrg5e7x9vn59vHu5t/Z09Aa0P3Nq6QO +pP3j8vsO+/zy5dnQGND9yqikDaQU+/z24tXQFtD9x6WkDKQX+/3q19AV0P68pAykGfv96NPQFND+ +sqQLpBr7/Pfez9AS0P3NqaQKpBz7/e3T0BLQ/sSkCqQd+/322dAS0P6zpAmkH/v+29AR0P3LpqQI +pCD7/eDP0BDQ/rykCKQh+/7g0BDQ/c+ppAekIvv+3NAQ0P6+pAekI/v+2NAQ0P6ppAakI/v999TQ +D9D+vaQGpCT7/e3P0A7Q/c+npAWkJfv+39AP0P62pAWkJfv9+dPQDtD+x6QFpCb7/ujQD9D+qqQE +pCf7/tXQDtD+uqQEpCf7/ujQDtD+yaQEpCj7/tXQDtD+qKQDpCj7/uPQDtD+s6QDpCj7/vfQDtD+ +v6QDpCn7/tjQDdD+y6QDpCn7/uPQDtD+p6QCpCn7/vLQDtD+rqQCpCr7/tPQDdD+tKQCpCr7/tnQ +DdD+u6QCpCr7/t/QDdD+waQCpCr7/ubQDdD+xqQCpCr7/u7QDdD+x6QCpCr7/vHQDdD+y6QCpCr7 +/vTQDdD+zKQCpCr7/vnQDdD+z6QCpCr7/vnQDdD+z6QCpCr7/vTQDdD+zKQCpCr7/vHQDdD+y6QC +pCr7/u3QDdD+x6QCpCr7/uTQDdD+xqQCpCr7/t/QDdD+waQCpCr7/tnQDdD+u6QCpCr7/tLQDdD+ +tKQCpCn7/vHQDtD+raQCpCn7/uPQDtD+p6QCpCn7/tjQDdD+y6QDpCj7/fbP0A3Q/r+kA6Qo+/7h +0A7Q/rOkA6Qo+/7V0A7Q/qikA6Qn+/7o0A7Q/sikBKQn+/7V0A7Q/rqkBKQm+/7o0A/Q/qqkBKQl ++/3509AO0P7GpAWkJfv+3tAP0P62pAWkJPv+7dAP0P3Op6QFpCP7/fbS0A/Q/r2kBqQi+/352NAP +0P3PqKQGpCL7/tvQEND+vqQHpCH7/uDQEdD+qaQHpCD7/eDP0BDQ/rykCKQe+/3529AR0P3MpqQI +pClX/UwNABIAKlf9TxEAEQArV/1SFQAQACxX/VIRAA8AAVfvXmt2g5OZo6mpo5mTg3VqXlcaV/1Q +DQAOAP2Ana0OrfudgGlYVxdX/UsIAA0AFK38o31hVxZX/UQCAAwAF639jGRXFVf+MAAMABmt/Yde +VxRX/hsACwAarfyodFhXElf9UQsACgAcrf2RXlcSV/5AAAoAHa39pGhXElf+HgAJAB+t/m9XEVf9 +TwUACAAgrf53VxFX/jAACAAhrf53VxBX/VYMAAcAIq3+cFcQV/41AAcAI63+aFcPV/1VCwAGACOt +/aZeVw9X/jEABgAkrf2RWFcOV/1UBgAFACWt/nRXD1f+JQAFACWt/aleVw5X/kQABQAmrf6HVw9X +/g0ABAAnrf5jVw5X/iwABAAnrf6HVw5X/kkABAAorf5hVw5X/gkAAwAorf58Vw5X/h8AAwAorf2k +WFcNV/41AAMAKa3+aFcNV/5MAAMAKa3+flcOV/4GAAIAKa3+nFcOV/4TAAIAKq3+XlcNV/4gAAIA +Kq3+alcNV/4uAAIAKq3+dVcNV/47AAIAKq3+g1cNV/5DAAIAKq3+klcNV/5HAAIAKq3+mlcNV/5M +AAIAKq3+oVcNV/5QAAIAKq3+qVcNV/5VAAIAKq3+qVcNV/5VAAIAKq3+oVcNV/5QAAIAKq3+mlcN +V/5MAAIAKq3+kVcNV/5HAAIAKq3+glcNV/5DAAIAKq3+dVcNV/47AAIAKq3+alcNV/4tAAIAKq3+ +XVcNV/4gAAIAKa3+m1cOV/4TAAIAKa3+flcOV/4GAAIAKa3+aFcNV/5MAAMAKK39o1hXDVf+NQAD +ACit/ntXDlf+HwADACit/mBXDlf+CQADACet/oZXDlf+SQAEACet/mNXDlf+LAAEACat/oZXD1f+ +DQAEACWt/ahdVw5X/kQABQAlrf5zVw9X/iQABQAkrf2QWFcOV/1UBgAFACOt/aNdVw9X/jEABgAi +rf2sZ1cPV/1VCQAGACKt/m9XEFf+NAAHACGt/nZXEFf9VQsABwAgrf52VxFX/i8ACAAerf2sb1cR +V/1OBQAIACkf/RsEABIAKh/9HAYAEQArH/0dBwAQACwf/R0GAA8AAR/vIiYqLzQ3Ojw8Ojc0Lyom +IR8aH/0cBQAOAP0tOD4OPvw4LSUfGB/9GwMADQAUPvw6LCMfFh/9GAEADAAXPv0yJB8VH/4RAAwA +GT79MCEfFB/+CgALABo+/TwpHxMf/R0EAAoAHD79NCEfEh/+FwAKAB0+/TslHxIf/gsACQAfPv4o +HxEf/RwCAAgAID7+Kh8RH/4RAAgAIT7+Kh8RH/4EAAcAIj7+KB8QH/4TAAcAIz7+JR8PH/0eBAAG +ACM+/TshHw8f/hIABgAkPv40Hw8f/R4CAAUAJT7+KR8PH/4NAAUAJT79PCEfDh/+GAAFACY+/jAf +Dx/+BQAEACc+/iMfDh/+EAAEACc+/jAfDh/+GgAEACg+/iMfDh/+AwADACg+/iwfDh/+CwADACg+ +/jsfDh/+EwADACk+/iUfDR/+GwADACk+/i0fDh/+AgACACk+/jgfDh/+BwACACo+/iEfDR/+DAAC +ACo+/iYfDR/+EAACACo+/iofDR/+FQACACo+/i8fDR/+GAACACo+/jQfDR/+GQACACo+/jcfDR/+ +GwACACo+/jkfDR/+HQACACo+/jwfDR/+HgACACo+/jwfDR/+HgACACo+/jkfDR/+HQACACo+/jcf +DR/+GwACACo+/jQfDR/+GQACACo+/i4fDR/+GAACACo+/iofDR/+FQACACo+/iYfDR/+EAACACo+ +/iEfDR/+CwACACk+/jcfDh/+BwACACk+/i0fDh/+AgACACk+/iUfDR/+GwADACg+/jofDh/+EwAD +ACg+/iwfDh/+CwADACg+/iIfDh/+AwADACc+/jAfDh/+GgAEACc+/iMfDh/+EAAEACY+/jAfDx/+ +BQAEACU+/TwhHw4f/hgABQAlPv4pHw8f/g0ABQAkPv4zHw8f/R4CAAUAIz79OiEfDx/+EQAGACI+ +/T0lHw8f/R4DAAYAIj7+KB8QH/4SAAcAIT7+Kh8QH/0eBAAHACA+/iofER/+EQAIAB4+/T0oHxEf +/RwCAAgAPv/+/v9/AMH/7+vQvKmXkYiDg4iRl6q90ez/LP/9ro2ADoD7ja7U+/8o/xSA/Iiy5f8m +/xeA/Z7d/yT/GYD9pO3/Iv8agPyEv/z/IP8cgP2Z7f8f/x2A/YfV/x7/H4D+x/8d/yCA/rv/HP8h +gP67/xv/IoD+xv8a/yOA/tb/Gf8jgP2G7P8Y/ySA/Zn8/xf/JYD+v/8X/yWA/YPs/xb/JoD+pP8W +/yeA/uH/Ff8ngP6k/xX/KID+5f8U/yiA/rP/FP8ogP2H+/8T/ymA/tb/E/8pgP6w/xP/KYD+jv8T +/yqA/u3/Ev8qgP7R/xL/KoD+vv8S/yqA/qr/Ev8qgP6Y/xL/KoD+kP8S/yqA/or/Ev8qgP6D/xL/ +KoD+g/8S/yqA/or/Ev8qgP6Q/xL/KoD+mf8S/yqA/qv/Ev8qgP6+/xL/KoD+0f8S/yqA/u7/Ev8p +gP6P/xP/KYD+sP8T/ymA/tb/E/8ogP2I/P8T/yiA/rT/FP8ogP7m/xT/J4D+pf8V/yeA/uH/Ff8m +gP6l/xb/JYD9hO7/Fv8lgP7B/xf/JID9mvz/F/8jgP2I7/8Y/yKA/YHX/xn/IoD+x/8a/yGA/rz/ +G/8ggP68/xz/HoD9gcj/Hf/+owA9AP2kqgA8AAGkPQABpP6lADsAAqT+gAA6AAOkOwADpP6fADkA +A6T+owA5AASk/qoAOAAEpP6lADgABaT+qgA3AAakOAAGpP7/ADYABqT+owA2AAekNwAHpP6qADUA +B6T+pQA1AAek/qMANQAIpP6fADQACKT+pQA0AAik/qUANAAJpDUACaT+pgAzAAqkNAAKpDQACqQ0 +AAqkNAAKpP6qADIAC6QzAAukMwALpDMAC6QzAAukMwALpDMAC6QzAAukMwALpDMACqT+owAyAAqk +/qMAMgALpDMAC6QzAAqk/qMAMgALpDMAC6QzAAukMwALpDMAC6QzAAukMwAKpP6mADIACqQ0AAqk +NAAKpDQACqQ0AAmk/qYAMwAJpDUACaQ1AAik/qMANAAIpP6fADQACKQ2AAikNgAHpP6qADUAB6Q3 +AAak/qYANgAFpP2j/wA2AH8QAAB/EAAA/k4APQD95w8APAD9/5IAPAD8//02ADsAAf/9yAIAOgAC +//5lADoAAv/97BAAOQAD//59ADkAA//97AwAOAAE//50ADgABP/95wkANwAF//5qADcABf/93QEA +NgAG//49ADYABv/+mgA2AAb//fAJADUAB//+VQA1AAf//rIANQAH//36EAA0AAj//k8ANAAI//6Q +ADQACP/+0gA0AAj//f4XADMACf/+VwAzAAn//pgAMwAJ//7FADMACf/+7QAzAAr//hUAMgAK//47 +ADIACv/+YgAyAAr//okAMgAK//6qADIACv/+twAyAAr//sQAMgAK//7SADIACv/+3gAyAAr//usA +MgAK//74ADIACv/++AAyAAr//usAMgAK//7eADIACv/+0QAyAAr//sQAMgAK//63ADIACv/+qQAy +AAr//okAMgAK//5iADIACv/+OwAyAAr//hQAMgAJ//7tADMACf/+xQAzAAn//pcAMwAJ//5XADMA +CP/9/hcAMwAI//7SADQACP/+jwA0AAj//k4ANAAH//36EAA0AAf//rAANQAH//5UADUABv/98AkA +NQAG//6YADYABv/+PAA2AAX//dwBADYAfwoAAH8KAAB/CgAAfwoAAH8QAAB/EAAAfxAAAH8QAAAv +APyqrdj7C/swAPyqstr7CvsxAPulrdb5+wj7MgD7kqzQ9/sH+zMA+7+ozfH7Bvs1APymu+T7Bfs2 +APulstb5+wP7NwD7n6vH6vsC+zkA+aay1PT7+wA5APqiqb3g9wA7APykrL8APQD+pgB/DP8AMAD9 +E2qtC60xAP0ZbK0KrTIA/BNiq60IrTMA/BBXpq0HrTQA/AxOmq0GrTUA/AIvgK0FrTcA/B1nqa0D +rTgA/BBIjK0CrToA+h1eoK2tADoA+wkzeKcAPAD9EDUAfw0/ADAA/QYlPgs+MQD9CSY+Cj4yAPwG +Iz0+CD4zAPwGHzs+Bz40APwFGzc+Bj42AP0RLj4FPjcA/AolPD4DPjgA/AYaMj4CPjoA+gohOT4+ +ADoA+wQSKzsAPAD9BhMAfw0/AC8A/AnIxoALgDAA/BLXwoAKgDEA+xHIzIKACIAyAPsHstiGgAeA +MwD7BKTfkIAGgDUA/Gfwq4AFgDYA+zPhyYOAA4A3APsQseSfgAKAOQD5TeXQi4CAADkA+guM8LeF +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 +Pv00IR8SH/4WAAoAGj79PCkfEx/9HQQACgAZPv0wIR8UH/4KAAsAFz79MiQfFR/+EQAMABQ+/Dos +Ih8WH/0YAQAMAP0tNz4OPvw3LSUfGB/9GwMADQABH+8hJiovNDc6PDw6NzQvKiYhHxof/RwEAA4A +LB/9HQYADwArH/0dBwAQACof/RwGABEAKR/9GwQAEgAoH/0YAwATACcf/RIBABQAJR/9HQoAFgAk +H/0WBAAXACIf/RwLABkAIB/8HhEBABoAHh/8HhQEABwAHB/8HhMDAB4AGh/8GA0CACAAFx/8GhAE +ACMAEx/7HBUMBAAmAOsCBwwQFRgZGx0eHh0bGRgVEAwHAgB/CisAHYD9iNf/Hv8cgP2Z7v8f/xqA +/ITA/P8g/xmA/abu/yL/F4D9nt7/JP8UgPyIs+b/Jv/9sI+ADoD7j7DW/P8q/+/t0b2qmZGJg4OJ +kZmqvtHt/38BLP/+/f89//6E/zz//cEE/zv//OobAP86//v9RwAA/zr//nIAAQA6//6HAAIAOf/9 +owEAAgA4//20BAADADf//cMKAAQANv/9ugwABQA1//2iBQAGADT//ZECAAcAMv/9/XEACQAx//3r +SQAKADD//cEbAAsALv/8/pEFAAwALf/95kYADgAr//z9mQ8ADwAq//3MNQARACj//O5vAgASACb/ +/OuAEQAUACT//OmADgAWACL//NxpBwAYAB//+/CiRAEAGgAc//v8u14KAB0AGf/73ZlVEQAgABT/ ++uzGllYWACQA6jxjiqi5xdHd7fn57d3RxbmoiWM7FAB/BioABaT+pQA3AAWk/qoANwAEpP6jADgA +BKT+ogA4AAOk/qMAOQADpP6qADkAA6Q7AAKk/v8AOgABpP6lADsA/aSlADwAAaQ9AP6lAH8NPgB/ +EAAAfxAAAAX//mkANwAE//3nCQA3AAT//nIAOAAD//3rCwA4AAP//noAOQAC//3rDwA5AAL//mIA +OgAB//3FAQA6APz//DAAOwD9/5AAPAD95g4APAD+RwB/DT4AfwoAAH8KAAB/CgAAfwoAAH8QAAB/ +EAAAfxAAAH8QAAB/Df4A/aqjADoA+6qjpLEAOQD6pqO0ytUANwD4o6SqxNXq+wA1APb/o6a6z+P5 ++/sANAD5paSuytr2+wL7NAD6oqO30Ob7BPszAPqlp8LV8/sF+zIA+qSpyNz5+wb7fw4+AP0BGgA7 +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 +paQWpCMA/aqjpBikIQD9oqOkGqQfAP2do6QcpB0A/aGlpB6kGwD9oqOkIKQZAP6ipCOkFwD8oqSj +pCOkFQD+oqQnpBMA/qWkKKT+pgAQAP6mpCik/KjK8gAOAP6mpCik+qnK8/z8AAsA/f+mpCik/KvQ +9vwC/AoA/YCmpCik/KzQ9/wE/AgA/ZmjpCik/K/V+fwG/AYA/aqjpCik/LDZ+vwI/AQA/aKjpCik +/LPb+/wK/AIA/Z2jpCik/bTf/A38/ACmo6QopP244vwP/P6jpCik/bjl/BH8KKT9vur8E/wlpPyl +we38FfwjpPymxO78F/whpPymx/L8GPz+6KQepPyoyvP8GPz96LukHaT8qc32/Bj8/eK2pB2k/KvQ +9vwX/Pz74rWkHaT8rtb5/Bf8/PrbsqQdpPyw1fn8F/z8+tuxpB2k/LLb+/wX/Pz41a6kHaT8tNv7 +/Bf8/PjVraQdpP244vwY/Pz10KqkHaT9uOL8GPz89dCppB2k/b7p/Bj8/PTNqKQcpPylvur8GPz8 +8MempBKk/rKkB6T8psXu/Bj8/PDHpaQSpPyz2/ukB6T9s+X8Gfz92q+kEqT7ruj8/KQJpP245fwY +/Pz62K+kEqT9vemkC6T9uOL8GPz8+tuwpCGk/bji/Bj8/PnXrqQhpP244vwY/Pz51q6kIaT9ueb8 +GPz8+tmupCGk/bji/Bj8/PrZrqQhpP245fwY/Pz62a2kIaT9uuf8GPz8+dmtpCGk/bjl/Bj8/PnZ +raQhpP245fwY/Pz41a2kIaT9uOX8GPz8+NWtpCGk/bjl/Bj8/fjVrH8GPwD+BAA7APwIS5wAOQD6 +CUufr68ANwD8DlejrwKvNgD8D1elrwSvNAD8FWOprwavMgD8F2msrwivMAD8H26trwqvLgD8InWu +rwyvLAD9KHqvD68qAP0ogq8RrycA/AE0i68TryUA/AE6kq8VryMA/ANAla8XryEA/AVGm68Yr/6G +AB4A/AhLna8Yr/2GLQAdAPwKUqOvF6/8rnolAB0A/A5XpK8Xr/yueiIAHQD8FGSprxev/KxuGwAd +APwXY6qvF6/8q24ZAB0A/B5urK8Xr/ynYxMAHQD8IG6trxev/KdjEQAdAPwoeq6vF6/8olYLAB0A +/Sh6rxiv/KFXCgAcAPwBNYmvGK/8n1IHABwA/AE0i68Yr/yYRQQAEgD+GwAHAPwDQpSvGK/8l0YD +ABIA/B5urQAHAP0fgK8Zr/1rFQASAPsTh6+vAAkA/SmBrxiv/KtoFQASAP0xiQALAP0oeq8Yr/ys +bhcAIQD9KHqvGK/8qmYTACEA/Sh6rxiv/KplEwAhAP0rg68Yr/yraRMAIQD9KHqvGK/8q2kTACEA +/SiBrxiv/KtpEgAhAP0shK8Yr/yqaRIAIQD9KIGvGK/8qmkRACEA/SiBrxiv/KhjEQAhAP0ogq8Y +r/ynYxAAIQD9KIKvGK/9p2MQfwY/AP4BADsA/AMbNwA5APoDGzg+PgA3APwFHzo+Aj42APwFHzs+ +BD40APwIIzw+Bj4yAPwIJT0+CD4wAPwLJz0+Cj4uAP0MKT4NPiwA/Q4rPg8+KgD9Di4+ET4oAP0S +MT4TPiYA/RU0PhU+IwD8ARc1Phc+IQD8Ahk3Phg+/i8AHgD8Axs4Phg+/S8QAB0A/AMdOj4YPv0r +DQAdAPwFHzo+GD79KwwAHQD8ByM8Phc+/D0nCQAdAPwIIzw+Fz78PScJAB0A/AonPT4XPvw7IwcA +HQD8Cyc9Phc+/DsjBgAdAP0OKz4YPvw5HgQAHQD9Dis+GD78OR8EAB0A/RMxPhg+/DgdAgAdAP0S +MT4YPvw2GQEAEgD+CgAHAPwBFzU+GD78NRkBABIA/AsnPQAHAP0LLT4ZPv0mCAASAPsHMD4+AAkA +/Q8uPhg+/D0lBwASAP0SMQALAP0OKz4YPvw9JwgAIQD9Dis+GD78PCQHACEA/Q4rPhg+/DwkBwAh +AP0PLj4YPvw9JQcAIQD9Dis+GD78PSUHACEA/Q4uPhg+/D0lBgAhAP0QLz4YPvw8JQYAIQD9Di4+ +GD78PCUGACEA/Q4uPhg+/DwjBgAhAP0OLj4YPvw7IwYAIQD9Di4+GD79OyMGOQD9Df7/Av85AP41 +/wP/OQD+XP8D/zkA/oP/A/85AP6q/wP/OQD+0v8D/zgA/Rb2/wP/NgD8F4j1/wT/NAD8IJH3/wb/ +MgD8I5n7/wj/MAD8LqL8/wr/LgD8OrX+/wz/LAD9PLP/D/8pAPwBTMf/Ef8nAPwCTcv/E/8lAPwC +Vdb/Ff8jAPwGXtr/F/8hAPwLb+P/Gf8fAPwNb+b/G/8dAPwTgu//Hf8bAPwWgPD/H/8ZAPwekfb/ +If8XAPwhkfj/I/8VAPwsovv/Jf8TAPwwov3/J/8RAPw8s/7/Kf8PAP08vP8s/wwA/AFNyP8u/woA +/AJNzf8w/wgA/AVe2P8y/wYA/AZe2/80/wQA/Atv5P82/wIA/A1v6P84//sAFIDv/zr//Yj1/38H +ff8NpP7v/An8/sGkB6T+1PwB/P30sqQKpP2z9fwG/Ayk/ab7/An8/rOkB6T+4/wC/P3ysKQKpP20 +9vwF/Ayk/rP8Cfz9+6ekB6T+8PwD/P3wraQKpP239/wE/Ayk/sD8Cfz+8KQHpP2m+/wE/P3uraQK +pP24+PwD/Ayk/s38Cfz+46QHpP6z/Ab8/eyqpAqk/b36/AL8DKT+2/wJ/P7VpAek/sD8B/z97Kqk +CqT9wPr8AfwMpP7o/An8/sikB6T+zvwI/P3oqKQKpPvB+/z8pAuk/vX8Cfz+u6QHpP7b/An8/eWn +pAqk/MX7/KQKpP6r/Ar8/q2kB6T+6fwK/P3kpqQKpP3J/KQKpP64/An8/vikCKT+9vwL/P3fpaQK +pP7NpAqk/sf8Cfz+66QHpP6s/A38/dylpBak/tP8Cfz+3aQHpP64/A78/tmkFqT+4vwJ/P7QpAek +/sf8D/z+1qQVpP7u/An8/sKkB6T+1PwQ/P7RpBOk/ab6/An8/rSkB6T+4vwR/P7PpBKk/rL8Cvz+ +qKQHpP7u/BL8/sukEaT+wPwJ/P7xpAek/ab6/BP8/sikEKT+zfwJ/P7kpAek/rL8FPz9+8WkD6T+ +2vwJ/P7WpAek/r/8Ffz9+8GkDaT9uPH8Cfz+yaQHpP7N/Bb8/fq/pAqk/bji/Av8/rukB6T+2vwX +/P36vaQHpP2+6fwN/P6upAek/uj8GPz9+LqkA6T8pb7r/A78/vikCKT+9fwZ/Pj4uKSkpsTu/BD8 +/uykB6T+qvwb/Pv3tcTv/BL8/t6kB6T+uPwc/P73/BT8/tCkB6T+xvwz/P7DpAek/tP8Mvz9+rOk +B6T+4Pww/Pz627CkCKT+7vwu/Pz41a6kCaT9pfr8LPz899GrpAuk/rH8K/z89c+ppA2k/r78Kfz8 +9NCppA+k/sz8J/z88cqnpBGk/tn8Jfz878ampBKk/bPu/CP8/O3EpaQSpPyz2/v8Ivz87cSlpBKk +/bTf/CP8/ezBpBOk/bji/CT8/r6kE6T9uOX8JvwTpP2+6fwo/BCk/KW+6/wq/A6k/KbE7vws/Ayk +/KbE7/wu/Aqk/KbH8vww/Aik/KjK8/wy/Aak/KnN9vw0/ASk/KzT9/w2/AKk/KzT+Pw4/Pukr9X5 +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 +pP6mACoAEqQsABGk/qIAKwARpC0AEaQtABCkLgAPpP6lAC0ADqT+owAuAA6k/pIALgANpP6jAC8A +DaT+qgAvAAyk/qMAMAAMpDIAC6T+owAxAAukMwALpDMACaT+pQAzAAmk/qcAMwAJpDUACKT+qgA0 +AAek/qMANQAHpP6ZADUABqT+owA2AAak/r8ANgAFpP6lADcABaT+/wA3AASk/qYAOAADpP6jADkA +A6T+pgA5AASkOgAEpP6iADgABaQ5AAWk/qEANwAGpDgABqT+owA2AAekNwAHpP6iADUACKQ2AAik +/qMANAAJpDUACa/+ZgAzAAiv/acQADMACK/+WQA0AAev/aEKADQAB6/+TAA1AAav/ZkFADUABq/+ +PwA2AAWv/Y8BADYABa/+MQA3AASv/oQAOAADr/2uJwA4AAOv/nYAOQACr/2tHAA5AAKv/mkAOgAB +r/2pEwA6AAGv/lsAOwD8r6MMADsA/a9OADwA/ZoFADwA/kEAPQD+AgB/Cv4ACT7+JAAzAAg+/TsG +ADMACD7+HwA0AAc+/TkDADQABz7+GwA1AAY+/TYCADUABj7+FgA2AAU+/jMANwAFPv4SADcABD7+ +LwA4AAQ+/g4AOAADPv4qADkAAj79PQoAOQACPv4lADoAAT79PAcAOgABPv4gADsA/D46BAA7AP0+ +HAA8AP02AgA8AP4XAD0A/gEAfwr+AB7//fojAB0AHv/+kQAeAB3//fMXAB4AHf/+fwAfABz//ekN +AB8AHP/+awAgABv//dwGACAAG//+WAAhABr//dACACEAGv/+RQAiABn//r8AIwAY//3+NAAjABj/ +/qgAJAAX//36JQAkABf//pQAJQAW//30GAAlABb//oEAJgAV//3rDgAmABX//m4AJwAU//3fBwAn +ABT//lsAKAAT//3RAgAoABP//kgAKQAS//7BACoAEf/9/jkAKgAR//6rACsAEP/9/CkAKwAQ//6X +ACwAD//99hwALAAP//6EAC0ADv/97hEALQAO//5yAC4ADf/94AcALgAN//5eAC8ADP/90gMALwAM +//5LADAAC//+wgAxAAv//joAMQAK//6uADIACf/9/CoAMgAJ//6bADMACP/99x0AMwAI//6JADQA +B//97xIANAAH//51ADUABv/95AoANQAG//5hADYABf/91wQANgAF//5PADcABP/9yAEANwAE//48 +ADgAA//+sgA5AAP//j8AOQAD//6UADkAA//9+iEAOAAE//6dADgABP/9+yYANwAF//6mADcABf/9 +/S8ANgAG//6wADYAB//+NwA1AAf//rgANQAI//5AADQACP/+xAA0AH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfw0+AP2qpAA6APumo6SkADgA/aajpAKkNwD9maOkBKQ2AP6lpAakNAD+ +oaQIpDMA/qakCaQxAP2/o6QKpDAA/qKkDKQvAP6mpAuk/am9AC0A/qWkCqT7pbvP0AAsAP6lpAqk +/bHL0AHQfw9+AP0LMQA6APsELlZXADkA/RpNVwFXfw9+AP0EEgA6APsBER8fADkA/QkcHwEffw0+ +AP0PdgA6APsUgO7/ADgA/BeA8f8B/zcA/AVv8/8D/zYA/UHW/wX/NAD9G6r/B/8zAP1N7f8I/zEA +/ASA/f8J/zAA/R7F/wv/LwD9P+7/DP8uAP1P9v8N/y0A/WD7/w7/fwwLAPmqpqOlpKWkCKT5paOk +o6aqACQA+6ekpaWkFKT7paSlowAcAPyZpqOkH6T9o5kAFgD9pqOkJKT9o6YAEwArpP2jqgAQAC6k +/p8ADgAwpP6hAAwAMaT9o5IACgALpOunrrS7wcbIys3Pz83KyMbCu7Sup6QSpP6lAAkAB6T7qLK+ +y9AS0PvMwbWppA+k/aOnAAcABKT8qrvK0BrQ/Mm7q6QPpAcAAaT8qLfG0CDQ/Ma3qKQNpP6qAAQA +/Km9ztAk0PzPvqikDKT+pQADAP7O0CnQ/cCqpAuk/qMAAgAs0PzPvaakCaT9o6QAAQAu0PzMtKOk +CaT+pQAAAH8ODADrBhQhLjxESEtRVVVRS0hEOy4hFAYAJgD7CB00TFcSV/tOOiMLAB8A/A4uSlca +V/xKLQ4AGQD8ByZFVyBX/EUlBwAUAPwKMVRXJFf8VTQKABIA/lRXKFf8VTcNABAALFf8VjEFAA4A +Llf9TiAADQB/DgwA6wIHDBEVGBobHR4eHRsaGBURDAcCACYA+wMKExsfEh/7HBUMBAAfAPwFEBsf +Gh/8GhAFABkA/AINGR8gH/wYDQIAFAD8BBIeHyQf/B4TBAASAP4eHygf/B4UBQAQAC0f/RICAA4A +Lh/9HAsADQB/DAsA6QYoUHedusfS3e75+e7d0sa6nHZQKAYAJAD6Glye2fv/Ev/6+9mdWxkAHAD7 +BU2W1/8c//vXlUsFABYA/CuI6P8i//ztmTwAEwD+1v8o//zVdQ8AEAAs//zykRgADgAu//z0kRsA +DAAw//z2gAcACgAy//3bRwAJADT//acaAAcANf/97EwABgA2//z+kQYABAA4//3KIgADADn//e09 +AAIAOv/9+FQAAQA7//38ZgAAAH8QAAB/EAAAfxAAAH8QAAB/CgAAfwoAAH8KAAB/CgAAfxAAAH8Q +AAB/EAAAfxAAADAA+v+jqszf+wj7LwD6/6WuzOT7CfsvAPukrs/o+wr7LgD7o6vN6PsL+y0A+6Sp +y+P7DPssAPuip8ng+w37KwD7paLB2/sO+yoA+v+kt9X5+w77KgD7pK3R8fsP+ykA+6Omyuf7EPsp +APykvNr7EfsoAPukq9D2+xH7JwD7maPE4/sS+ycA+6O01fn7EvsmAPudpMrq+xP7JgD8pbPV+xT7 +JQD7n6PI6fsU+yUA/KSz1fsV+yUA/KTE5vsV+yQA+6ap0Pn7FfskAPykudr7FvsjAPuApMnr+xb7 +IwD8o63T+xf7IwD8pLnc+xf7IwD8pMTo+xf7IgD7qqTP9vsX+yIA/KSv1PsY+yIA/KW53fsY+yIA +/KTB5PsY+yIA/KPI6/sY+yEA+4Cjzvb7GPshAPylqNL7GfshAPymr9X7GfshAPyjsdf7GfshAPyk +s9n7GfshAPyjttv7GfshAPyluNz7GfshAPylud77GfshAPykuNz7GfshAPyjttv7GfshAPyks9n7 +GfshAPymsdf7GfshAPymr9X7GfshAPylqdL7GfshAPuAo872+xj7IgD8o8jr+xj7IgD8pMHk+xj7 +IgD8pLnc+xj7IgD8o6/V+xj7IgD7maTP9vsX+yMA/KTF6PsX+yMA/KW53PsX+yMA/KWs0/sX+yMA ++4Ckyev7FvskAPykudz7FvskAPukqNH5+xX7JQD8o8Tm+xX7JQD8pLLV+xX7JQD7n6PI6fsU+yYA +/KOz1PsU+yYA+6qkyer7E/snAPujs9X5+xL7JwD7maTF4/sS+ygA+6Sr0fT7EfsyAPwOTXetCK0x +APwSUYGtCa0wAPwUVoitCq0vAPwPUoetC60uAPwKTX+tDK0tAPwGSXmtDa0tAP08b60OrSwA/Cdh +qa0OrSsA/BJYmq0PrSoA/ARMhK0QrSoA/TBsrRGtKQD8D1ihrRGtKQD9QXytEq0oAPwgYaytEq0n +APwBSoytE60nAP0fY60UrScA/UiJrRStJgD9HGGtFa0mAP1Bg60VrSUA/ApZqa0VrSUA/SpurRat +JQD9SY+tFq0kAP0SXq0XrSQA/SpxrRetJAD9QIatF60jAPwCVaStF60jAP0WYq0YrSMA/StyrRit +IwD9OYCtGK0jAP1GkK0YrSMA/VOkrRitIgD9ClytGa0iAP0VY60ZrSIA/RpmrRmtIgD9H2qtGa0i +AP0jba0ZrSIA/SdwrRmtIgD9KnOtGa0iAP0ncK0ZrSIA/SNtrRmtIgD9H2qtGa0iAP0aZq0ZrSIA +/RVjrRmtIgD9ClutGa0jAP1TpK0YrSMA/UaQrRitIwD9OYCtGK0jAP0rca0YrSMA/RZirRitIwD8 +AlWkrRetJAD9QIatF60kAP0qcK0XrSQA/RFerRetJQD9SI6tFq0lAP0qbq0WrSUA/AlZqa0VrSYA +/UCDrRWtJgD9G2GtFa0nAP1IiK0UrScA/R5irRStJwD8AUqMrROtKAD8H2GsrRKtKQD9QXutEq0p +APwOWKCtEa0yAPwFGys+CD4xAPwHHS4+CT4wAPwHHzA+Cj4vAPwFHTA+Cz4uAPwDGy0+DD4tAPwC +Gis+DT4tAP0VKD4OPiwA/A4jPD4OPisA/AYfNz4PPioA/AIbLz4QPioA/REmPhE+KQD8BR85PhE+ +KQD9Fyw+Ej4oAPwLIz0+Ej4oAP0bMj4TPicA/QsjPhQ+JwD9GjE+FD4mAP0KIz4VPiYA/RcvPhU+ +JQD8BCA8PhU+JQD9Dyc+Fj4lAP0aMz4WPiQA/QYhPhc+JAD9Dyg+Fz4kAP0XMD4XPiMA/AEeOz4X +PiMA/QgjPhg+IwD9Dyk+GD4jAP0ULj4YPiMA/RkzPhg+IwD9Hjs+GD4iAP0EIT4ZPiIA/QgjPhk+ +IgD9CSQ+GT4iAP0LJj4ZPiIA/Q0nPhk+IgD9Dig+GT4iAP0PKT4ZPiIA/Q4oPhk+IgD9DSc+GT4i +AP0LJj4ZPiIA/QkkPhk+IgD9CCM+GT4iAP0DIT4ZPiMA/R47Phg+IwD9GTM+GD4jAP0ULj4YPiMA +/Q8oPhg+IwD9CCM+GD4jAPwBHjs+Fz4kAP0XMD4XPiQA/Q8oPhc+JAD9BiE+Fz4lAP0aMz4WPiUA +/Q8nPhY+JQD8AyA8PhU+JgD9Fy8+FT4mAP0KIz4VPicA/RowPhQ+JwD9CyM+FD4oAP0aMj4TPigA +/AsjPT4SPikA/RcsPhI+KQD8BR85PhE+MAD6AYD//rqACIAvAPoBm//8rIAJgC8A+4n/+aOACoAu +APts//ykgAuALQD7Wv3+r4AMgCwA+zf6/7eADYArAPsR3//HgA6AKgD6Aa7/5IOADoAqAPtw//eQ +gA+AKQD7JPf+qIAQgCkA/Lf/zoARgCgA+1T/9oqAEYAnAPsK4P+zgBKAJwD7gP/kgYASgCYA+w3t +/56AE4AmAPx3/+CAFIAlAPsI5v+igBSAJQD8a//kgBWAJQD8z/+qgBWAJAD7K//2g4AVgCQA/Ir/ +yoAWgCMA+wLj/5uAFoAjAPxA/+yAF4AjAPyD/8WAF4AjAPzF/6WAF4AiAPsM+v2HgBeAIgD8Sf/j +gBiAIgD8gv/DgBiAIgD8qv+tgBiAIgD80f+agBiAIQD7AvX/h4AYgCEA/B//8oAZgCEA/D//4YAZ +gCEA/E7/2YAZgCEA/Fr/0oAZgCEA/Gf/zIAZgCEA/HT/xoAZgCEA/Hz/wYAZgCEA/HP/xoAZgCEA +/Gf/zIAZgCEA/Fr/0oAZgCEA/E3/2YAZgCEA/D//4YAZgCEA/B//84AZgCEA+wL1/4eAGIAiAPzR +/5qAGIAiAPyq/62AGIAiAPyB/8SAGIAiAPxI/+OAGIAiAPsK+f2HgBeAIwD8xP+lgBeAIwD8gv/G +gBeAIwD8Pv/tgBeAIwD7AuP/nIAWgCQA/In/yoAWgCQA+yr/9oOAFYAlAPzO/6qAFYAlAPxq/+WA +FYAlAPsI5f+jgBSAJgD8df/jgBSAJgD7DOz/n4ATgCcA+33/5YGAEoAnAPsK3/+0gBKAKAD7Uf/2 +i4ARgDT7+uLLq6T/AAQANfv65M6upP8AAwA2+/vo0K6kAAMAN/v76c2qowACADj7++TMqaQAAQA5 ++/nhyaeiAAD7Ofv628OjnwD7Ofv6+dS3o//7Ovv78dCuo/s7+/zoyqb7PPv92bz7PPv99ND7Pfv+ +4ft/DH77/uL7PPv+9NE0rfx6Tg8ABgA1rfyAUhQABQA2rfyHVRMABAA3rfyKUg4AAwA4rfyBTgsA +AgA5rfx5SAUAAQA6rf1uPQABADqt+qtiJQAArTqt+5tYEwCtO638hksErTyt/WsvrTyt/aBZrT2t +/nutPa3+rK1/C/6t/qytPa3+eq08rf6gWDQ+/CscBQAGADU+/C4dBwAFADY+/DAfBwAEADc+/DEd +BQADADg+/C4cBAACADk+/CsaAgABADo+/ScWAAEAOj76PSMNAAA+Oj77Nx8HAD47PvwwGwE+PD79 +JhE+PD79OSA+PT7+LD49Pv49Pn8L/j7+PT49Pv4rPjw+/jkfNID6tv7/kQEABAA1gPqt/P+YAQAD +ADaA+6T5/4YAAwA3gPuh+/9yAAIAOID7rP7+XwABADmA+bj/+DQAAIA5gPrJ/90QAIA5gPqC4/+y +AYA6gPuP9v9sgDuA/Kb+9oA8gP3Q/4A8gP2L9oA9gP61gD2A/oGAfwv+gP6BgD2A/raAPID+i/d/ +AkAA/qUAPQD+pAA9AP2sowA8APzGoqoAOwD81bOjADsA++rKpKoAOgD7+9WzpQA6APr76MikqgA5 +AAH7/NWxpQA5AAH7/OTFpAA5AAH7+/nRqKIAOAAC+/zbuKQAOAAC+/vsyKSqADcAA/v80q2mADcA +A/v83LilADcAA/v858OkADcAA/v798+kogA2AAT7/NWvpAA2AAT7/N25owA2AAT7/OPAowA2AAT7 +/OvGowA2AAT7+/fOo/8ANQAF+/zRqacANQAF+/zVr6UANQAF+/zXsaMANQAF+/zYs6UANQAF+/za +taQANQAF+/zct6MANQAF+/zeuaUANQAF+/zct6MANQAF+/zataQANQAF+/zYs6UANQAF+/zXsaMA +NQAF+/zVr6MANQAF+/zSqKQANQAE+/v2zqP/ADUABPv868ajADYABPv848CjADYABPv83LmjADYA +BPv81a6jADYAA/v79s+kogA2AAP7/OXEowA3AAP7/Nu4pQA3AAP7/NKspgA3AAL7++rJpIAANwAC ++/zauKQAOAAB+/v30amiADgAAfv85sSlADkAAfv81bGkADkA+vvoyKOqADkA+/vVsqMAOgD76smk +ogA6APzVs6MAOwD8xaOiADsA/aqmADwAfwLAAP4QAD0A/kIAPQD9YR8APAD8jEsBADsA/K1jHgA7 +APuth0kBADoAAa39YRsAOgABrf2CQAA6AAGt/KlaCgA5AAKt/W0pADkAAq39jUkAOQADrf1dEAA4 +AAOt/W8pADgAA639hT8AOAADrfykVQIANwAErf1hFQA3AASt/XEqADcABK39fzgANwAErf2PRQA3 +AASt/aRTADcABa39WwkANgAFrf1iFAA2AAWt/WYaADYABa39aR4ANgAFrf1sIgA2AAWt/XAnADYA +Ba39cyoANgAFrf1wJwA2AAWt/WwiADYABa39aR4ANgAFrf1mGgA2AAWt/WIUADYABa39WwkANgAE +rf2jUwA3AASt/Y9FADcABK39fzgANwAErf1xKgA3AASt/WEVADcAA638o1UCADcAA639hD8AOAAD +rf1vKAA4AAOt/V0QADgAAq39jEgAOQACrf1sKAA5AAGt/KhZCgA5AAGt/YJAADoAAa39YBoAOgD8 +rYZHADsA/K1jHQA7APyLSwEAOwD9YB4APAD+QgA9AP4OAD0AfwLAAP4GAD0A/hgAPQD9IwsAPAD9 +MhsAPAD8PiMLADsA/D4wGgA7AAE+/SMKADoAAT79LhcAOgABPvw8IAQAOQACPv0nDgA5AAI+/TIa +ADkAAz79IQYAOAADPv0oDgA4AAM+/S8WADgAAz78Ox4BADcABD79IwgANwAEPv0oDwA3AAQ+/S0U +ADcABD79MxkANwAEPv07HQA3AAU+/SADADYABT79IwcANgAFPv0kCQA2AAU+/SULADYABT79JwwA +NgAFPv0oDgA2AAU+/SkPADYABT79KA4ANgAFPv0nDAA2AAU+/SULADYABT79JAkANgAFPv0jBwA2 +AAU+/SADADYABD79Oh0ANwAEPv0zGQA3AAQ+/S0UADcABD79KA8ANwAEPv0jBwA3AAM+/DoeAQA3 +AAM+/S8WADgAAz79KA4AOAADPv0hBgA4AAI+/TIaADkAAj79Jw4AOQABPvw8IAMAOQABPv0uFwA6 +AAE+/SIJADoA/D4wGQA7APw+IwoAOwD9MRsAPAD9IgsAPAD+FwA9AP4FAD0AfwJAAP4iAD0A/rQA +PQD9/1AAPAD8/+IMADsA/OX/fQA7APuf/+wMADoA+4Dh/3QAOgD6gKT/6AkAOQABgPzl/2kAOQAB +gPyr/8wAOQABgPuD9f8sADgAAoD8zP+GADgAAoD7nf/kAwA3AAOA/O7/PAA3AAOA/Mf/fwA3AAOA +/Kf/wQA3AAOA+4f9+QsANgAEgPzk/0YANgAEgPzE/4AANgAEgPyv/6cANgAEgPyb/84ANgAEgPuH +//QBADUABYD89P8dADUABYD84v8+ADUABYD82v9LADUABYD80/9YADUABYD8zf9lADUABYD8xv9y +ADUABYD8wf98ADUABYD8xv9yADUABYD8zf9lADUABYD80/9YADUABYD82v9LADUABYD84v89ADUA +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 +Ffz9+8KkDaT+qPwK/P62pAek/uL8FPz9+8SkD6T+8/wJ/P7CpAek/tX8E/z9+8SkEKT+6PwJ/P7P +pAek/sr8Evz9+8WkEaT+2/wJ/P7apAek/r38Efz9+8WkEqT+0PwJ/P7npAek/rL8EPz9+8akE6T+ +w/wJ/P7ypAek/ab7/A/8/sekFKT+tvwK/P6opAek/vH8Dvz+yaQVpP6r/Ar8/rOkB6T+5fwN/P7I +pBek/vb8Cfz+v6QHpP7Z/Az8/sqkC6T+0KQKpP7r/An8/sukB6T+zfwL/P7NpAuk/dD8pAqk/t78 +Cfz+16QHpP7B/Ar8/sukC6T80Pz8pAqk/tH8Cfz+46QHpP60/An8/s6kC6T+zPwB/Auk/sb8Cfz+ +76QHpP6o/Aj8/s+kC6T+zPwC/Auk/rn8Cfz9+6WkB6T+9PwG/P7PpAuk/sz8A/wLpP6u/Ar8/rCk +B6T+6PwF/P7PpAuk/sz8BPwMpP75/An8/rukB6T+3PwE/P7QpAuk/sv8BfwMpP7u/An8/sikB6T+ +0PwD/P7QpAuk/sr8BvwMpP7h/An8/tSkB6T+xPwC/P7TpAuk/sf8B/wMpP7V/An8/uCkB6T+t/wB +/P7UpAuk/sf8CPwMpP7J/An8/u2kB6T7rPz81KQLpP3G+/wI/Ayk/rz8Cfz++KQIpP331aQLpP3G ++/wJ/Ayk/rH8Cvz+raQHpP7GpAuk/cb7/Ar8DKT9pfr8Cfz+uKQUpP3F+/wL/A2k/vD8Cfz+xaQT +pP3C+/wM/A2k/uT8Cfz+0KQSpP3C+/wN/A2k/tj8Cfz+3aQRpP3B+/wO/A2k/sz8Cfz+6aQQpP3B ++/wP/A2k/sD8Cfz+9aQPpP3B+/wP/P72pAyk/rP8Cvz+qaQNpP3A+vwP/P32taQMpP6o/Ar8/rSk +DKT9wPr8D/z99bSkDqT+8/wJ/P7BpAuk/b35/A/8/fa2pA+k/uj8Cfz+zqQKpP2++vwP/P32tqQQ +pP7b/An8/tmkCaT9vvn8D/z99rWkEaT+z/wJ/P7mpAik/bz5/A/8/fe2pBKk/sP8Cfz+8aQHpP28 ++fwP/P33tqQTpP62/An8/fumpAWk/bz5/A/8/fe2pBSk/qr8Cvz+sqQEpP25+PwP/P33t6QWpP72 +/An8/r6kA6T9ufj8D/z997ekF6T+6vwJ/P7KpAKk/bj4/A/8/fe3pBik/t78Cfz+1qQBpP249/wP +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 +BVf+oq0RrSMA/lVXBVf+qa0RrSMA/lVXBVf+qa0RrSMA/lFXBVf+oq0RrSMA/kxXBVf+m60RrSMA +/khXBVf+lK0RrSMA/kRXBVf+jK0RrSMA/jxXBVf+fa0RrSMA/i5XBVf+cK0RrSMA/iFXBVf+Zq0R +rSMA/hRXBVf+Xa0RrSMA/gZXBlf+m60QrSQA/kxXBVf+f60QrSQA/jZXBVf+a60QrSQA/iBXBVf9 +XKytD60kAP4JVwZX/outD60lAP5KVwVX/mytD60lAP4uVwVX/VmnrQ6tJQD+DVcGV/5+rQ6tJgD+ +RVcFV/1erK0NrSYA/iVXBlf+g60NrSYA/QdUVwVX/mCtDa0nAP4yVwZX/oCtDK0nAP0KVVcFV/1b +o60LrTgA/QQXHwMfNwD9Ch0fBB81AP0BER8GHzQA/QMZHwcfMwD9BBsfCB8yAP0FHB8JHzEA/Qgd +Hwkf/icALwD9Bh0fCB/8ITM+AC4A/QQcHwgf+yU6Pj4ALQD9AxsfCB/+LD4CPi0A/QEZHwgf/i8+ +Az4tAP4SHwcf/SAyPgQ+LAD+CR8HH/0gND4FPisA/QQdHwcf/jI+Bj4rAP4XHwcf/i8+Bz4qAP4L +Hwcf/iw+CD4pAP0CHB8GH/4lPgk+KQD+Eh8GH/0hOz4JPigA/gQfBx/+Mz4KPigA/hMfBh/+KD4L +PicA/QQeHwUf/SE7Pgs+JwD+Eh8GH/4uPgw+JgD9Ax4fBR/+Ij4NPiYA/g0fBh/+Lz4NPiYA/hkf +BR/9Ij0+DT4lAP4FHwYf/i0+Dj4lAP4QHwUf/SA7Pg4+JQD+Gx8FH/4mPg8+JAD+Ax8GH/4yPg8+ +JAD+Cx8FH/4hPhA+JAD+Ex8FH/4mPhA+JAD+Gx8FH/4tPhA+IwD+Ah8GH/43PhA+IwD+Bx8FH/4h +PhE+IwD+DB8FH/4kPhE+IwD+ER8FH/4oPhE+IwD+FR8FH/4sPhE+IwD+GB8FH/4yPhE+IwD+Gh8F +H/41PhE+IwD+Gx8FH/43PhE+IwD+HR8FH/46PhE+IwD+Hh8FH/48PhE+IwD+Hh8FH/48PhE+IwD+ +HR8FH/46PhE+IwD+Gx8FH/43PhE+IwD+Gh8FH/41PhE+IwD+GB8FH/4yPhE+IwD+FR8FH/4sPhE+ +IwD+ER8FH/4oPhE+IwD+DB8FH/4kPhE+IwD+Bx8FH/4hPhE+IwD+Ah8GH/43PhA+JAD+Gx8FH/4t +PhA+JAD+Ex8FH/4mPhA+JAD+Cx8FH/0hPT4PPiQA/gMfBh/+MT4PPiUA/hofBR/+Jj4PPiUA/hAf +BR/9IDs+Dj4lAP4FHwYf/i0+Dj4mAP4ZHwUf/SI9Pg0+JgD+DR8GH/4vPg0+JgD9Ah4fBR/+Ij4N +PicA/hIfBh/+LT4MPicA/QMeHwUf/SA6Pgs+LAD+fP8Q/ysA/n3/Ef8qAP5m/xL/KQD9Ufz/Ev8o +AP0/9/8T/ycA/SDu/xT/JgD9Bcb/E//9/swAJQD+jv8T//zumoAAJAD9S/7/Ev/714iAgAAjAP0b +7f8R//39tYACgCQA/qr/Ef/9/KmAA4AjAP5F/xH//feegASAIgD9B9r/EP/995iABYAiAP5+/xD/ +/fuegAaAIQD9G/b/D//9/aeAB4AhAP6O/xD//rWACIAgAP0T8/8P//7VgAmAIAD+hf8P//3uh4AJ +gB8A/Q/w/w7//f2agAqAHwD+dv8P//7IgAuAHwD+0/8O//3zh4ALgB4A/jX/D//+rIAMgB4A/pL/ +Dv/+54ANgB0A/QTo/w7//qmADYAdAP5N/w7//euBgA2AHQD+lv8O//6vgA6AHQD+2P8N//34hYAO +gBwA/hr/Dv/+zoAPgBwA/l3/Dv/+n4APgBwA/p3/Df/+8YAQgBwA/tn/Df/+z4AQgBsA/Qb7/w3/ +/q6AEIAbAP4p/w7//o+AEIAbAP5P/w3//u6AEYAbAP53/w3//tmAEYAbAP6e/w3//sWAEYAbAP65 +/w3//rKAEYAbAP7F/w3//p+AEYAbAP7T/w3//pWAEYAbAP7g/w3//o+AEYAbAP7t/w3//omAEYAb +AP75/w3//oOAEYAbAP75/w3//oOAEYAbAP7t/w3//omAEYAbAP7g/w3//o+AEYAbAP7T/w3//paA +EYAbAP7G/w3//p+AEYAbAP65/w3//rKAEYAbAP6e/w3//saAEYAbAP53/w3//tmAEYAbAP5P/w3/ +/u+AEYAbAP4p/w7//o+AEIAbAP0G+/8N//6vgBCAHAD+2P8N//7QgBCAHAD+nf8N//3ygYAPgBwA +/lz/Dv/+oIAPgBwA/hn/Dv/+zoAPgB0A/tf/Df/9+IWADoAdAP6V/w7//rCADoAdAP5L/w7//euB +gA2AHQD9BOj/Dv/+qoANgB4A/pH/Dv/+6IANgB4A/jT/D//+roAMgB8A/tP/Dv/99IiAC4AM0O3T +19zi6u7x9vn59vHu6uLc19LQEND9xamkCaT9owDQB9D709rj8vsQ+/vy49nS0A3Q/c6ypAqkBdD8 +0dnp+xf7+/nq29HQDND9vaWkCKQD0PzU4/n7HPv8+ePU0AvQ/cenpAekAdD91OP7Ifv8+ejV0ArQ +/cuqpAak/dLk+yb7/ePS0AnQ/cyspAWk/vb7KPv999vQCdD9za6kBKQs+/3r0tAI0P3NraQDpC37 +/fbZ0AjQ/c2rpAKkL/v+4NAI0P3KqKQBpDD7/ufQCND7x6WkpPsw+/3r0dAH0Py8pKT7Mfv97dLQ +B9D9sqT7Mvv969HQBtD9zan7M/v+5dAH0P7E+zT7/uDQB9A2+/7Y0AbQNvv99tLQBdA3+/7r0AXQ +OPv+29AE0Dj7/fbS0APQOfv+5dAD0Dr7/tXQAtA6+/7m0ALQOvv9+dPQAdA7+/7j0AHQO/v799HQ +0Ps7+/zZ0ND7O/v86dDQ+zv7/PnS0Ps8+/3Z0Ps8+/3i0Ps8+/3x0Ps9+/7S+z37/tf7Pfv+2/s9 ++/7j+z37/ur7Pfv+7vs9+/7x+z37/vT7Pfv++fs9+/75+z37/vT7Pfv+8fs9+/7u+z37/ur7Pfv+ +4/s9+/7b+z37/tb7Pfv+0vs8+/3z0Ps8+/3k0Ps8+/3Y0Ps8+/3S0Ps7+/zp0ND7O/v82dDQ+zr7 ++/fR0ND7Ovv+4tAB0Dv7/tTQAdA6+/7k0ALQOvv+09AC0Dn7/uPQA9A4+/330tAD0AxX7V1mcX2M +lJmjqaujmpSMfXBmXVcQV/1ACwALAAhX+1xrf5ytEK37nH9rXFcNV/1SHQAKAAVX/Flqia0Xrfus +jG1ZVwxX/TECAAgAA1f8Xn+orRyt/Kh+XlcLV/1ECAAHAAFX/GB/rK0grfyshmFXClf9TA0ABgD9 +W4GtJq39gFtXCVf9TxEABQD+pK0orf2kb1cJV/1SFQAEACyt/Y9dVwhX/VIRAAMALa39pGlXCFf9 +UA0AAgAvrf55VwhX/UsIAAEAMK39hVhXB1f7RAIAAK0wrf2OWlcHV/wwAACtMa39klpXB1f9GwCt +Mq39jllXBlf9UQutM63+hFcHV/5ArTSt/nlXB1c2rf5oVwZXNq39o11XBVc3rf6PVwVXOK3+blcE +Vzit/aRbVwNXOa3+gFcDVzqt/mBXAlc6rf6CVwJXOq39rF5XAVc7rf5+VwFXO637p1lXV607rfxr +V1etO638ildXrTut/KxbV608rf1qV608rf19V608rf2bV609rf5drT2t/matPa3+b609rf58rT2t +/outPa3+k609rf6arT2t/qGtPa3+qa09rf6prT2t/qGtPa3+mq09rf6TrT2t/outPa3+fK09rf5v +rT2t/mWtPa3+XK08rf2bV608rf19V608rf1qV607rfysW1etO638iVdXrTut/GpXV606rfunWVdX +rTqt/n1XAVc6rf2sXlcBVzqt/oFXAlc6rf5fVwJXOa3+flcDVzit/aRbVwNXDB/tISQoLDI1Nzo8 +PTo3NTIsKCQhHxAf/RcEAAsACB/7ISYtOD4QPvs4LSYhHw0f/R0KAAoABR/8ICYxPhc++z0yJyAf +DB/9EgEACAADH/wiLTw+HD78PC0iHwsf/RgDAAcAAR/8Ii09PiA+/D0wIx8KH/0bBAAGAP0hLj4m +Pv0tIR8JH/0cBgAFAP47Pig+/TsoHwkf/R0HAAQALD79MyEfCB/9HQYAAwAtPv07JR8IH/0cBQAC +AC8+/isfCB/9GwMAAQAwPv4vHwgf+xgBAAA+MD79MyAfBx/8EQAAPjE+/TQgHwcf/QoAPjI+/TMg +HwYf/R0EPjM+/i8fBx/+Fz40Pv4rHwcfNj7+JR8GHzY+/TohHwUfNz7+Mx8FHzg+/icfBB84Pv07 +IR8DHzk+/i0fAx86Pv4iHwIfOj7+Lh8CHzo+/T0hHwEfOz7+LR8BHzs++zsgHx8+Oz78Jh8fPjs+ +/DEfHz47Pvw9IR8+PD79Jh8+PD79LR8+PD79Nx8+PT7+IT49Pv4kPj0+/ig+PT7+LD49Pv4xPj0+ +/jQ+PT7+Nz49Pv45Pj0+/jw+PT7+PD49Pv45Pj0+/jc+PT7+ND49Pv4xPj0+/iw+PT7+KD49Pv4k +Pj0+/iE+PD79Nx8+PD79LR8+PD79Jh8+Oz78PSEfPjs+/DEfHz47PvwmHx8+Oj77OyAfHz46Pv4t +HwEfOj79PSEfAR86Pv4uHwIfOj7+Ih8CHzk+/i0fAx84Pv07IR8DHwz/7e7ZxbKflpGIg4KIkJaf +ssbZ7/8c//z+egD/B//78c+vjoAQgPuOr9Dy/xr//nn/BP/8+NGigBeA+4GezPj/F//+/v8C//zr +r4SAHID8hLDr/xj//OivgYAggPyBpuX/FP/986yAJoD9rvP/Ev/+h4AogPyHyP7/EP8sgP2b7/8P +/y2A/YfU/w7/L4D9t/7/DP8wgP2n+/8L/zGA/Zz2/wr/MoD9mPf/Cf8zgP2c+v8I/zSA/aj+/wf/ +NYD+t/8H/zaA/tb/Bv82gP2I7/8F/zeA/Zv+/wT/OID+yf8E/ziA/Yfz/wP/OYD+rv8D/zqA/ub/ +Av86gP6r/wL/OoD9gez/Af87gP6w/wH/O4D7hfn//4A7gPzQ//+AO4D8of//gDuA/IHz/4A8gP3R +/4A8gP2x/4A8gP2P/4A9gP7vgD2A/tqAPYD+x4A9gP6zgD2A/qCAPYD+l4A9gP6QgD2A/oqAPYD+ +g4A9gP6DgD2A/oqAPYD+kIA9gP6XgD2A/qCAPYD+s4A9gP7HgD2A/tuAPYD+8IA8gP2P/4A8gP2x +/4A8gP3S/4A7gPyB8/+AO4D8ov//gDuA/NH//4A6gPuF+f//gDqA/rH/Af86gP2B7P8B/zqA/qz/ +Av86gP7p/wL/OYD+sP8D/ziA/Yfz/wP/fwCAAP6jAD0A/aSjADwAAaT+owA7AAKk/qIAOgADpP6q +ADkAA6T+owA5AASk/qUAOAAFpP6nADcABqQ4AAekNwAHpP6qADUAB6T+owA1AAik/qMANAD+s6QH +pDUA/cumpAak/qoAMwD90LykBqT+pQAzAPzQz6mkB6QzAAHQ/r6kBqT+pQAyAALQ/qmkBqQzAALQ +/r2kBqT+pwAxAALQ/c+npAWk/qMAMQAD0P62pAak/r8AMAAD0P7HpAekMQAE0P6qpAakMQAE0P66 +pAakMQAE0P7JpAak/p8ALwAF0P6opAWk/qMALwAF0P6zpAWk/qUALwAF0P6/pAakMAAF0P7LpAak +/pkALgAG0P6npAWk/qEALgAG0P6upAWk/qYALgAG0P60pAWk/qUALgAG0P67pAWk/qUALgAG0P7B +pAakLwAG0P7GpAakLwAG0P7HpAWk/qMALgAG0P7LpAakLwAG0P7MpAakLwAG0P7PpAWk/qMALgAG +0P7PpAWk/qMALgAG0P7MpAakLwAG0P7LpAakLwAG0P7HpAWk/qMALgAG0P7GpAakLwAG0P7BpAak +LwAG0P67pAakLwAG0P60pAakLwAG0P6tpAWk/qYALgAG0P6npAWk/qUALgAF0P7LpAak/pkALgAF +0P6/pAakMAAF0P6zpAWk/qUALwAF0P6opAWk/qMALwAE0P7IpAak/p8ALwAE0P66pAakMQAE0P6q +pAakMQAD0P7GpAak/qMAMAAD0P62pAak/r8AMAAC0P3Op6QFpP6lADEAAtD+vaQGpP6lADEAAdD9 +z6ikBqQzAH8DwAD+HgA9AP1PBQA8AP1XMAA8APxXVgwAOwABV/41ADsAAVf9VQsAOgACV/4xADoA +Alf9VAYAOQADV/4lADkAA1f+RAA5AARX/g0AOAAEV/4sADgABFf+SQA4AAVX/gkANwAFV/4fADcA +BVf+NQA3AAVX/kwANwAGV/4GADYABlf+EwA2AAZX/iAANgAGV/4uADYABlf+OwA2AAZX/kMANgAG +V/5HADYABlf+TAA2AAZX/lAANgAGV/5VADYABlf+VQA2AAZX/lAANgAGV/5MADYABlf+RwA2AAZX +/kMANgAGV/47ADYABlf+LQA2AAZX/iAANgAGV/4TADYABlf+BgA2AAVX/kwANwAFV/41ADcABVf+ +HwA3AAVX/gkANwAEV/5JADgABFf+LAA4AARX/g0AOAADV/5EADkAA1f+JAA5AAJX/VQGADkAAlf+ +MQA6AAFX/VUJADoAfwPAAP4LAD0A/RwCADwA/R8RADwAAR/+BAA7AAEf/hMAOwABH/0eBAA6AAIf +/hIAOgACH/0eAgA5AAMf/g0AOQADH/4YADkABB/+BQA4AAQf/hAAOAAEH/4aADgABR/+AwA3AAUf +/gsANwAFH/4TADcABR/+GwA3AAYf/gIANgAGH/4HADYABh/+DAA2AAYf/hAANgAGH/4VADYABh/+ +GAA2AAYf/hkANgAGH/4bADYABh/+HQA2AAYf/h4ANgAGH/4eADYABh/+HQA2AAYf/hsANgAGH/4Z +ADYABh/+GAA2AAYf/hUANgAGH/4QADYABh/+CwA2AAYf/gcANgAGH/4CADYABR/+GwA3AAUf/hMA +NwAFH/4LADcABR/+AwA3AAQf/hoAOAAEH/4QADgABB/+BQA4AAMf/hgAOQADH/4NADkAAh/9HgIA +OQACH/4RADoAAR/9HgMAOgB/AIAA/mQAPQD9+04APAD8//c9ADsAAf/97R4AOgAC//3JBgA5AAP/ +/osAOQAD//3+TwA4AAT//ewaADcABf/+pgA3AAb//kMANgAG//3YBgA1AAf//noANQAH//31GQA0 +AAj//owANAAI//30FQAzAAn//oIAMwAJ//3vDgAyAAr//nQAMgAK//7VADIAC//+MQAxAAv//o4A +MQAL//3pBAAwAAz//kkAMAAM//6SADAADP/+1AAwAAz//f4YAC8ADf/+WQAvAA3//psALwAN//7X +AC8ADf/9+gUALgAO//4mAC4ADv/+TQAuAA7//nQALgAO//6bAC4ADv/+twAuAA7//sQALgAO//7R +AC4ADv/+3gAuAA7//usALgAO//74AC4ADv/++AAuAA7//usALgAO//7eAC4ADv/+0QAuAA7//sQA +LgAO//63AC4ADv/+mgAuAA7//nMALgAO//5NAC4ADv/+JQAuAA3//foFAC4ADf/+1gAvAA3//psA +LwAN//5ZAC8ADP/9/hgALwAM//7UADAADP/+kgAwAAz//kgAMAAL//3oBAAwAAv//o0AMQAL//4w +ADEACv/+1AAyAH8KAAB/CgAAfwoAAH8KAAB/EAAAfxAAAH8QAAB/EAAAKQD8o7zZ+xH7KQD7qKbK +5fsQ+yoA+6St0fH7D/srAPukt9X5+w77KwD7n6PB2/sO+ywA+6WnyN/7DfstAPujqMvj+wz7LgD7 +pKrM6PsL+y8A+6Su0Oj7CvsvAPr/o63N4/sJ+zAA+v+jqsvg+wj7MgD6o6jH2/n7BvszAPqjp8LV +8fsF+zQAAaP8tdHm+wT7NQD5qqWtytn0+wL7NwD3o6a60eH5+/sANwD4paSrxNXq+wA5APqmorPJ +1QA6APuio6SxADwA/aKjAH8K/wAqAP0va60RrSoA/ARLg60QrSsA/BJYma0PrSwA/CZhqa0OrS0A +/TturQ6tLQD8BUl4rQ2tLgD8CUx+rQytLwD8DVCHrQutMAD8E1WHrQqtMQD8ElGArQmtMgD8Dk13 +rQitMwD7CUduqa0GrTQA+wU7YZqtBa02APwjV4KtBK03APsSS2ugrQKtOAD4AyxYe6ytrQA5APoN +P2GMrQA7APwfSmIAPAD9ARoAfws/ACoA/REmPhE+KgD8ARsvPhA+KwD8Bh83Pg8+LAD8DSM8Pg4+ +LQD9FSc+Dj4tAPwCGis+DT4uAPwDGy0+DD4vAPwEHDA+Cz4wAPwHHzA+Cj4xAPwGHC0+CT4yAPwF +Gyo+CD4zAPsDGSc8PgY+NAD7AhUjNz4FPjYA/AwfLj4EPjcA+wYbJjk+Aj44APgBEB8sPT4+ADkA ++gUXIzI+ADsA/AsaIwA9AP4JAH8LPwApAPy1/9CAEYApAPsj9/+pgBCAKgD7bf/3kYAPgCsA+63/ +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 +J/v17tjP0MqxpKSlogAMACn7+evV0NDBqKQBpAwAKvv5+eDR0MywpAGk/oAACQAs+/by1tDPu6Sk +o6oACAAt+/n54NDQxKakAaQIAC/79+nS0MiopKWqAAYAMPv38dTQyqukpKoABQAx+/f21dDMrKSl +qgAEADL79/fX0M2rpKWSAAMAM/v3+dbQyqikpIAAAgA0+/j31dDIp6SlAAIANfv49NTQw6SkpgAB +ADb79vPR0LikpKYAAPs2+/fo0M+vpKP/APs3+/jd0MuopKUA+zf7+PnV0MGkpKb7OPv589HQsKSk ++zn7+uDQyaSk+zn7+vnU0Lik+zr7++rPz6j7O/v819C7+zv7/OvQzfs8+/3X0Ps8+/3q0Ps9+/7U ++z37/uD7Pfv+9vt/CD77/vT7Pfv+4Ps9+wDV/GiGq60erfemf2NXV1U0CgATACWt+JBnV1dVMQQA +EQAnrfmUaVdXSxoAEAAprfmQYVdXPAgADgAqrfmreVlXTxgADQAsrfmdY1dWLgEACwAtrfmsd1dX +PwUACgAvrfqKW1dICQAJADCt+pteV0wNAAgAMa36o2JXTxAABwAyrfqnZldQDQAGADOt+qllV0sI +AAUANK36p2JXSAUABAA1rfqhXlc+AQADADat+5tbVykAAwA3rfuHV1YUAAIAOK37cldNBwABADit ++6tjVzkAAQA5rfmbWVcXAACtOa36dldKAgCtOa36qV5XKQCtOq37jFdTB607rfxmVy2tO638j1dS +rTyt/WRXrTyt/YtXrT2t/mCtPa3+ea09rf6hrX8IPq3+oK09rf55rT2tAGD8JTA9Ph4+9zstIx8f +HhMEABMAJT74MyUfHx4SAQARACc++TUlHx8bCQAQACk++TMjHx8VAwAOACo++T0rIB8cCQANACw+ ++jgjHx8RAAwALT75PSofHxcCAAoALz76MSEfGgMACQAwPvo3Ih8bBQAIADE++jojHxwGAAcAMj76 +OyQfHAUABgAzPvo8JB8bAwAFADQ++jsjHxoCAAQANT77OSIfFgAEADY++zcgHw8AAwA3PvswHx8H +AAIAOD77KR8cAgABADg++z0jHxQAAQA5Pvk3IB8IAAA+OT76Kh8aAQA+OT76PCIfDwA+Oj77Mh8e +Aj47PvwkHxA+Oz78Mx8dPjw+/SQfPjw+/TEfPj0+/iI+PT7+Kz49Pv45Pn8IPj7+OT49Pv4rPj0+ +ACL81aaCgB6A/Iav3/8E//z+oBYADwAlgP2a2P8E//zuagIADQAngP2W0/8E//26FgAMACmA/Zrl +/wP//elGAAsAKoD8grf4/wL//Px+AgAJACyA/Y3f/wP//acGAAgALYD8gbv+/wL//b4OAAcAL4D9 +ofP/Av/9yxUABgAwgP2P6/8C//3XFQAFADGA/Yji/wL//csMAAQAMoD9hdr/Av/9vQcAAwAzgP2D +3P8C//2lAgACADSA/YXi/wL//ncAAgA1gP2K6/8B//37PAABADaA/Y/1/wH/++MUAACANoD9pP7/ +Af/8tQEAgDeA/sP/Av/9YACAN4D9guH/Af/97BSAOID9j/r/Af/+mIA5gP68/wH//v2AOYD9g+v/ +Af87gP6f/wH/PID82f//gDuA/Jv//4A8gP3d/4A8gP2g/4A9gP7mgD2A/reAPYD+ioB/CD6A/ouA +PYD+t4A9gADmfwTAAP6kAD0A/qQAPQD9pKMAPAABpD0A/KekowA7APy5pKMAOwD7zKWkpAA6APvQ +sqSkADoA+9DDpKQAOgD60M+npKUAOQD619C3pKMAOQD65NDFpKQAOQD59tDPpaSqADgA+fvV0K+k +pQA4APn73dC7pKMAOAD5++nQx6SkADgA+Pv3z8+kpJkANwAB+/rS0KqkowA3AAH7+tfQsKSjADcA +Afv62tC3pKMANwAB+/ri0L6kpQA3AAH7+uXQwqSkADcAAfv66dDEpKQANwAB+/rr0MekpAA3AAH7 ++u7QyKSkADcAAfv68tDLpKQANwAB+/ry0MukpAA3AAH7+u7QyKSkADcAAfv669DHpKQANwAB+/rp +0MSkpAA3AAH7+ufQwqSkADcAAfv64tC+pKUANwAB+/ra0LekpQA3AAH7+tfQsaSmADcAAfv60tCp +pKEANwD4+/fPz6SkmQA3APn76dDHpKQAOAD5+93Qu6SkADgA+fvV0LCkpAA4APn20M+lpKYAOAD6 +5tDEpKQAOQD619C2pKQAOQAB0PyopKYAOQD70MKkpAA6APvQsqSlADoAfwXAAP4FAD0A/ioAPQD9 +UAMAPAD9Vx0APAD9Vz0APAD8WFYIADsA/GZXJQA7APyCV0IAOwD7o1dVBAA6APutYVcYADoA+61x +Vy4AOgD7rYhXRAA6APqtpldVAQA5AAGt/FxXDAA5AAGt/GRXGQA5AAGt/G5XJgA5AAGt/HpXNAA5 +AAGt/IRXOwA5AAGt/IlXQAA5AAGt/I9XRAA5AAGt/JVXSQA5AAGt/JxXTQA5AAGt/JxXTQA5AAGt +/JVXSQA5AAGt/I9XRAA5AAGt/IlXQAA5AAGt/IRXOwA5AAGt/HpXNAA5AAGt/G5XJgA5AAGt/GRX +GQA5AAGt/FxXCwA5APqtpldVAQA5APutiFdEADoA+61xVy0AOgD7rWFXFwA6APujV1UDADoA/IJX +QQA7APxmVyUAOwD8WFUHADsA/Vc8ADwA/VccADwAfwXAAP4CAD0A/g8APQD9HQEAPAD9HwoAPAD9 +HxYAPAABH/4DADsA/CQfDQA7APwuHxcAOwD7Oh8eAQA6APs+Ix8IADoA+z4oHxAAOgD7PjAfGAA6 +APs+Ox8eADoAAT78IR8EADkAAT78JB8JADkAAT78Jx8OADkAAT78Kx8SADkAAT78Lx8VADkAAT78 +MR8XADkAAT78Mx8YADkAAT78NR8aADkAAT78OB8bADkAAT78OB8bADkAAT78NR8aADkAAT78Mx8Y +ADkAAT78MR8XADkAAT78Lx8VADkAAT78Kx8SADkAAT78Jx8OADkAAT78JB8JADkAAT78IR8EADkA ++z47Hx4AOgD7PjAfGAA6APs+KB8QADoA+z4jHwgAOgD7Oh8eAQA6APwuHxcAOwD8JB8NADsA/B8e +AgA7AP0fFQA8AP0fCgA8AH8EwAD+OAA9AP7EAD0A/f9AADwA/f+8ADwAAf/+OgA7AAH//rIAOwAB +//39HAA6AAL//nYAOgAC//7UADoA/v3/Af/+MAA5AP7Z/wH//osAOQD+q/8B//7QADkA+Yj+///+ +FQA4AP2A5f8B//5VADgA/YDE/wH//pYAOAD9gKP/Af/+1gA4AP2Ahv8B//37BQA3AAGA/vH/Af/+ +JwA3AAGA/t3/Af/+TgA3AAGA/sr/Af/+dQA3AAGA/rb/Af/+mwA3AAGA/qj/Af/+rgA3AAGA/qL/ +Af/+uwA3AAGA/pv/Af/+yAA3AAGA/pX/Af/+1QA3AAGA/o7/Af/+4gA3AAGA/o7/Af/+4gA3AAGA +/pX/Af/+1QA3AAGA/pv/Af/+yAA3AAGA/qL/Af/+uwA3AAGA/qj/Af/+rgA3AAGA/rb/Af/+mwA3 +AAGA/sr/Af/+dAA3AAGA/t3/Af/+TQA3AAGA/vH/Af/+JgA3AP2Ahv8B//36BQA3AP2Ao/8B//7V +ADgA/YDE/wH//pUAOAD9gOX/Af/+VAA4APmI/v///RQAOAD+q/8B//7PADkA/tn/Af/+iQA5AP79 +/wH//i4AOQAC//7UADoAAv/+dAA6AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAA +AH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAOAD9pqOkA6Q2AP2Ao6QFpDUA/qKk +BaT9qb0AMgD9qqOkBKT7qb3O0AAxAP6ipASk/KW7z9AB0DEA/qWkBKT9scvQA9AvAP7/pASk/anF +0ATQ/tMALQD9maWkA6T9sc3QA9D80+T5ACwA/pmkBKT+u9AE0Pvc9/v7ACsA/qWkA6T9qMbQA9D9 +1vH7AvsrAP2qo6QCpP2pytAD0P7g+wT7KgD9maOkAqT9q8vQAtD90uv7BfspAP3/paQCpP2uzdAC +0P3X9/sG+ykABKT9rM3QAtD92vn7B/soAASk/anL0ALQ/tv7CfsnAP6ipAKk/ajK0ALQ/uD7Cvsm +AP6ZpAOk/sbQAtD+3fsL+yYA/qOkAqT+vdAC0P7a+wz7JQD+oqQCpP6y0ALQ/df5+wz7JAD+gKQC +pP2pzNAB0P3S9/sN+yQA/qOkAaT9o8XQAtD+6/sO+yMA/qakAqT+s9AC0P7i+w/7IwD+o6QBpP2m +y9AB0P7W+xD7IgAEpP690AHQ/c/v+xD7IgADpP6q0ALQ/t77EfshAP6ipAKk/r/QAdD90/f7Efsh +AAOk/ajP0AHQ/uT7EvsgAP6qpAKk/r3QAdD90/n7EvsgAP6lpAGk/afP0AHQ/uP7E/sgAP6lpAGk +/rfQAdD90vn7E/sfAP6hpAKk/sbQAdD+3/sU+x8AA6T+qtAC0P7y+xT7HwADpP670AHQ/tb7Ffse +AP6qpAKk/srQAdD+4/sV+x4A/qakAaT+qNAC0P73+xX7HgADpP600AHQ/tb7FvseAAOk/sDQAdD+ +3vsW+x0A/v+kAqT+ytAB0P7q+xb7HQD+oqQBpP6o0ALQ/vn7FvsdAP6jpAGk/q7QAdD+1PsX+x0A +A6T+tNAB0P7Z+xf7HQADpP680AHQ/t77F/sdAAOk/sHQAdD+5PsX+x0AA6T+xtAB0P7q+xf7HQAD +pP7I0AHQ/u77F/sdAAOk/svQAdD+8/sX+x0AA6T+zNAB0P72+xf7HQADpP7P0AHQ/vn7F/sdAAOk +/s/QAdD++fsX+x0AA6T+zNAB0P72+xf7HQADpP7L0AHQ/vP7F/sdAAOk/sjQAdD+7vsX+x0AA6T+ +xtAB0P7q+xf7HQADpP7B0AHQ/uT7F/sdAP6lpAGk/rvQAdD+3vsX+x0A/qOkAaT+tNAB0P7Z+xf7 +HQD+o6QBpP6u0AHQ/tT7F/sdAP6npAGk/qfQAtD++fsW+x0A/v+kAqT+y9AB0P7q+xb7HgADpP7A +0AHQ/t77FvseAP6jpAGk/rTQAdD+1fsW+x4AA6T+qdAC0P73+xX7HgD+maQCpP7K0AHQ/uX7Ffsf +AAOk/rvQAdD+1/sV+38AvgD9CjEAOgD7CzFUVwA4APwELlZXAVc4AP0aTVcDVzYA/QtBVwRX/l4A +NAD9G1FXA1f8XoKsADIA/QIuVwNX+lhxqK2tADEA/QlFVwNX/WWZrQKtMQD9C0pXAlf9WHetBK0w +AP0PTlcCV/1cjq0FrS8A/RVSVwJX/WakrQatLgD9EFJXAlf9bKutB60tAP0MT1cCV/5vrQmtLAD9 +CEpXAlf+d60KrSsA/QJFVwJX/nKtC60rAP4yVwJX/mytDK0qAP4aVwJX/WarrQytKQD9ClFXAVf9 +XaStDa0pAP5BVwFX/ViOrQ6tKAD+H1cCV/56rQ+tJwD9BU5XAVf+Za0QrScA/jJXAVf9WJetEK0m +AP0NVlcBV/50rRGtJgD+NlcBV/1eqK0RrSUA/QpVVwFX/oKtEq0lAP4yVwFX/V6srRKtJAD9B1RX +AVf+f60TrSQA/iZXAVf9XKmtE60kAP5FVwFX/netFK0jAP4OVwJX/p2tFK0jAP4uVwFX/mWtFa0j +AP5KVwFX/oCtFa0iAP4JVwFX/VimrRWtIgD+IFcBV/5jrRatIgD+NlcBV/50rRatIgD+TVcBV/6M +rRatIQD+B1cBV/1Yqa0WrSEA/hRXAVf+YK0XrSEA/iFXAVf+aa0XrSEA/i9XAVf+dK0XrSEA/jxX +AVf+gK0XrSEA/kRXAVf+ja0XrSEA/khXAVf+lK0XrSEA/kxXAVf+m60XrSEA/lFXAVf+oq0XrSEA +/lVXAVf+qa0XrSEA/lVXAVf+qa0XrSEA/lFXAVf+oq0XrSEA/kxXAVf+m60XrSEA/khXAVf+lK0X +rSEA/kRXAVf+ja0XrSEA/jxXAVf+gK0XrSEA/i5XAVf+dK0XrSEA/iFXAVf+aa0XrSEA/hRXAVf+ +YK0XrSEA/gZXAVf9WKmtFq0iAP5MVwFX/oytFq0iAP42VwFX/nStFq0iAP4gVwFX/mOtFq0iAP4J +VwFX/VimrRWtIwD+SlcBV/6ArRWtIwD+LlcBV/5krRWtfwC+AP0EEgA6APsEEh4fADgA/QERHwIf +OAD9CRwfAx82AP0EFx8EH/4hADQA/QodHwMf/CEuPQAyAP0BER8EH/soPD4+ADEA/QMZHwMf/SQ3 +PgI+MQD9BBsfAx/+Kj4EPjAA/QUcHwIf/SEzPgU+LwD9CB0fAh/9JDs+Bj4uAP0GHR8CH/0mPT4H +Pi0A/QQcHwIf/ig+CT4sAP0DGx8CH/4qPgo+KwD9ARkfAh/+KT4LPisA/hIfAh/+Jj4MPioA/gkf +Ah/9JD0+DD4pAP0EHR8BH/0hOz4NPikA/hcfAh/+Mz4OPigA/gsfAh/+Kz4PPicA/QIcHwEf/iQ+ +ED4nAP4SHwIf/jY+ED4mAP4EHwIf/ik+ET4mAP4THwEf/SE8PhE+JQD9BB4fAR/+Lj4SPiUA/hIf +AR/9IT0+Ej4kAP0DHh8BH/4tPhM+JAD+DR8BH/0hPD4TPiQA/hkfAR/+Kz4UPiMA/gUfAh/+OD4U +PiMA/hAfAR/+JD4VPiMA/hsfAR/+LT4VPiIA/gMfAh/+Oz4VPiIA/gsfAR/+Iz4WPiIA/hMfAR/+ +KT4WPiIA/hsfAR/+Mj4WPiEA/gIfAh/+PD4WPiEA/gcfAR/+Ij4XPiEA/gwfAR/+JT4XPiEA/hEf +AR/+KT4XPiEA/hUfAR/+Lj4XPiEA/hgfAR/+Mj4XPiEA/hofAR/+NT4XPiEA/hsfAR/+Nz4XPiEA +/h0fAR/+Oj4XPiEA/h4fAR/+PD4XPiEA/h4fAR/+PD4XPiEA/h0fAR/+Oj4XPiEA/hsfAR/+Nz4X +PiEA/hofAR/+NT4XPiEA/hgfAR/+Mj4XPiEA/hUfAR/+Lj4XPiEA/hEfAR/+KT4XPiEA/gwfAR/+ +JT4XPiEA/gcfAR/+Ij4XPiEA/gIfAh/+PD4WPiIA/hsfAR/+Mj4WPiIA/hMfAR/+KT4WPiIA/gsf +AR/+Iz4WPiIA/gMfAh/+Oz4VPiMA/hofAR/+LT4VPiMA/hAfAR/+JD4VPjgA/BeZ+f8C/zYA/AJe +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 +uwYAAwAxgP2J4/8C//3KDAAEADCA/ZDs/wL//dYUAAUAL4D9ofP/Av/9yxUABgAtgPyBwP7/Av/9 +vA0ABwAsgP2O4P8D//2kBQAIACqA/IK5+f8C//z7egEACQApgP2e6f8D//3oRAALACeA/ZfV/wT/ +/bYVAAwAJYD9m9n/BP/87WYBAA0A/Nang4AegPyGsOD/BP/8/p0VAA8AAf/79sqcgYAYgPuDpNL6 +/wX//cw7ABEABP/7+d27mYARgPqBmbvZ+f8G//zFTQEAEgAI/+v35NC9qZyWkIiCg4mRmJ6twdTn ++/8I//28QgAVAP2I6f8g//ziiCYAGAD7BU6n6v8a//vgmD0BAB0A+gEucLLv/xL/++emZCMAJgDr +GkFnjrTG0t7u+vjs3c/DrohiOhMAfwfiAPvNpaSkADoA/LmkpAA7APynpKMAOwD9pKUAPAD9pKUA +PAD+pAA9AP6lAH8OfgD9UAMAPAD+KQA9AP4FAH8PfgD9HAEAPAD+DwA9AP4CAH8PfgAB//39HAA6 +AAH//rEAOwAB//46ADsA/f+6ADwA/f8+ADwA/sIAPQD+NgB/Dn4AfwQoAPyko6WkE6QlAP2mo6QW +pCMA/qOkGaQhAPyAo6OkGaQgAP2qpaQbpB8A/Z+jpBykHwAfpB4AIKQdAP2ko6QepB0AIaQcAP6m +pCCkHAAipBsA/p+kIaQbAP6jpCGkGwD+paQhpBsAI6QbAA+k/a7J0BDQGwAPpP7J0BHQGwAPpBPQ +GwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAP +pBPQGwAPpBPQGwAPpBPQGwAPpBPQGwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+k +D9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP +0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/t/CCwA/RNJVxBXKwD+SVcRVysAE1cr +ABNXKwATVysAE1crABNXKwATVysAE1crABNXKwATVysAE1crABNXKwATVysAE1crABNXKwAPVwOt +KwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAP +VwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtKwAPVwOtfwgsAP0HGh8QHysA/hofER8rABMfKwAT +HysAEx8rABMfKwATHysAEx8rABMfKwATHysAEx8rABMfKwATHysAEx8rABMfKwATHysADx8DPisA +Dx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8D +PisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPn8EKAD5DlmQs9Dr/xD/JQD8PKfv/xX/IwD9 +JLH/GP8hAPwCevj/Gf8gAP0Dr/8b/x8A/QjA/xz/HwD+ov8d/x4A/nD/Hv8dAP0t+P8e/x0A/rf/ +H/8cAP0u/f8f/xwA/rD/IP8bAP0I9P8g/xsA/kj/If8bAP6N/yH/GwD+v/8h/xsA/uD/If8bAP7h +/yH/GwD+/v8h/xsAI/8bACP/GwAj/xsAI/8bACP/GwAj/xsAI/8bACP/GwAj/xsAI/8bACP/GwAj +/xsAI/8bAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB// +A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4AbAB//A4B/BAAAfwQApH8EANB/ +BAD7fwgAAH8EAFd/BACtfwgAAH8EAB9/BAA+fwQAAH8IAP9/BACAfwQAAA+k+6Oko6oAKgATpP2l +pwAoABekJwAYpCYAGKT9pZIAIwAapP6ZACIAG6T+qgAhABykIgAbpAGjIQAdpCEAHaT+pQAfAB6k +IAAepP6hAB4AH6QfAB+kHwAepP6jAB4ADdD9yK6kDqQfAA7Q/smkDqQfAA/QD6QfAA/QD6QfAA/Q +D6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6Qf +AA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/Q +D6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAA/QD6QfAH8IAAAN +V/1JEwAuAA5X/kgALgAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cv +AA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8A +D1cvAA9XLwAPVy8AD1cvAA9XLwB/CAAADR/9GgcALgAOH/4aAC4ADx8vAA8fLwAPHy8ADx8vAA8f +LwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8v +AA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8AfwQAAA3/+enjwIxL +CQAqABL//PWvMQAoABX//cItACYAFv/9+W0AJQAY//2hBwAjABn//cEFACIAGv/9nwMAIQAb//54 +ACEAG//9+CcAIAAc//6wACAAHf/+PgAfAB3//p8AHwAd//35EwAeAB7//lcAHgAe//6MAB4AHv/+ +tQAeAB7//tIAHgAe//7tAB4AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8f +AB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8A +H/8fAB//HwAf/x8AH/8fAB//HwAf/x8AfwU1AP3/oqQHpDMA/aWjpAikMgD+o6QKpDEA/qOkC6Qw +AP6ipAykMAD+paQMpC8A/qOkDaQvAA+kLwD+paQFpP2uydAE0C8AB6T+ydAF0C8AB6QH0C8AB6QH +0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8A +B6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH +0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8AB6QH0C8A +B6QH0C8AB6QH0C8AB6QH0C8AB6QH0H8HOAD9E0lXBFc3AP5JVwVXNwAHVzcAB1c3AAdXNwAHVzcA +B1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAH +VzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdX +NwAHV38HOAD9BxofBB83AP4aHwUfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcf +NwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83 +AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHH38FNQD6AUKXyOn/BP8z +AP0ww/8I/zIA/Wf8/wn/MQD+bP8L/zAA/TT5/wv/MAD+vf8M/y8A/kX/Df8vAP6M/w3/LwD+y/8N +/y8A/uL/Df8vAP7+/w3/LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//fwUAAH8CAKR/AgDQfwcA+38HAAB/AgBX +fwcArX8HAAB/AgAffwcAPn8FAAB/BAD/fwcAgH8FAAAcpP6jACAAHqT+ogAeACCkHgAhpB0AIaT+ +owAbACKk/v8AGgAipP6jABoAIqT+owAaABnQ/ciupAakGwAa0P7JpAakGwAb0AekGwAb0AekGwAb +0AekGwAb0AekGwAb0AekGwAb0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7 +B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH +0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQ +B6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AH +pBsAE/sH0AekGwAT+wfQB6QbAH8HAAAZV/1JEwAiABpX/kgAIgAbVyMAG1cjABtXIwAbVyMAG1cj +ABtXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdX +IwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwAT +rQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdXIwATrQdX +IwB/BwAAGR/9GgcAIgAaH/4aACIAGx8jABsfIwAbHyMAGx8jABsfIwAbHyMAEz4HHyMAEz4HHyMA +Ez4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4H +HyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMA +Ez4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAEz4HHyMAfwUAABn/++LKjEUAIAAd +//28NAAeAB7//flqAB0AIP/+aAAcACD//fwvABsAIf/9xAEAGgAi//49ABoAIv/+lgAaACL//scA +GgAi//7oABoAIv/+/gAaACP/GwAj/xsAI/8bACP/GwAj/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP +/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsA +E4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP +/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAE4AP/xsAfwc7AAGk/KOkpAA3AP2fo6QDpDgABqQ3 +AAekNwADpPuuydDQADYAA6T+ydAB0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD +0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcA +A6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD +0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0DcAA6QD0H8IPAD7E0lXVwA6AP5JVwFXOwADVzsAA1c7 +AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsA +A1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXfwg8 +APsHGh8fADoA/hofAR87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwAD +HzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMf +OwADHzsAAx87AAMfOwADHzsAAx9/BzsA+lGq3P//ADcA/RCn/wP/OAD+qP8E/zcA/lH/Bf83AP6r +/wX/NwD+3f8F/zcA/v7/Bf83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/ +NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83 +AAf/NwAH/zcAB/83AAf/NwAH/38HAAB/AQCkfwEA0H8HAPt/CAAAfwEAV38HAK1/CAAAfwEAH38H +AD5/BwAAfwIA/38HAIAfAP6lpAGk/qvQAtD+8vsU+x8A/aqjpAGk/sfQAdD+4PsU+yAAA6T+t9AB +0P3S+fsT+yAAA6T9qM/QAdD+4/sT+yAA/qqkAqT+vdAB0P7S+xP7IQADpP2pz9AB0P7k+xL7IQD+ +oaQCpP6/0AHQ/dL3+xH7IgADpP2pz9AB0P7e+xH7IgD+o6QCpP690AHQ/c/v+xD7IwD+o6QBpP2l +zNAB0P7W+xD7IwD+oaQCpP6z0ALQ/uH7D/skAP6lpAKk/sXQAtD+6/sO+yQA/oCkAqT9qM3QAdD9 +0vb7DfslAASk/rLQAtD91/n7DPsmAP6jpAKk/r3QAtD+2fsM+yYA/r+kAqT9pcfQAtD+3fsL+ycA +/qWkAqT9p8rQAtD+3vsK+ygABKT9qszQAtD92/n7CPspAASk/avN0ALQ/dn5+wf7KQD9/6WkAqT9 +r87QAtD91vb7BvsqAP6qpAOk/azM0ALQ/dLr+wX7KwD+qqQDpP2pydAD0P7e+wT7LAD+n6QDpP2n +x9AD0P3W8fsC+y0A/ZKlpAKk/KW6z9AD0Pvb9/v7AC0A/b+lpAOk/bHM0APQ/NPk+wAuAP3/paQD +pP2pxNAE0P7TADAA/qOkBKT9scvQA9AyAP6lpASk/Ka8z9AB0B2k/KOkowARAP2Zo6QEpPuqvc7Q +pCCk/qoAEQD+oqQFpP2nu6QhpBMA/f+jpCmkFAD8oqOjpAKkHdD9yK6kAqQWAP2io6QBpB7Q/smk +AqQYAPyqpaTQHtADpBoA/qrQHtADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb ++wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7 +A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD +0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQ +A6QbABv7A9ADpBsAG/sD0AOkGwAjAP4NVwJX/p2tFK0kAP5FVwFX/netFK0kAP4lVwFX/VyprROt +JAD9B1RXAVf+fq0TrSUA/jJXAVf9XaytEq0lAP0KVVcBV/6BrRKtJgD+NVcBV/1cp60RrSYA/QxW +VwFX/nStEa0nAP4xVwFX/ViXrRCtJwD9BE5XAVf+Za0QrSgA/h5XAlf+ea0PrSkA/kBXAVf9WI6t +Dq0pAP0KUVcBV/1coq0NrSoA/hpXAlf9ZqutDK0rAP4xVwJX/mutDK0rAP0CRFcCV/5xrQutLAD9 +B0pXAlf+dq0KrS0A/QxOVwJX/W+srQitLgD9D1JXAlf9a6utB60vAP0VUlcCV/1lo60GrTAA/Q9O +VwJX/VyOrQWtMQD9C0pXAlf9WHStBK0yAP0IRFcDV/1lmK0CrTMA/AEsVlcCV/pYb6etrQA0AP0a +UVcDV/xdgawANQD9C0BXBFf+XgA3AP0aTVcDVzkA/AUwVlcBVzsA+wsxVFcAPAD9CC4AfgAdV/1J +EwAeAB5X/kgAHgAfVx8AH1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfABut +A1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cf +AButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfAButA1cfABut +A1cfAButA1cfAButA1cfACMA/gUfAh/+OD4UPiQA/hkfAR/+Kj4UPiQA/g0fAR/9ITw+Ez4kAP0C +Hh8BH/4tPhM+JQD+Eh8BH/0hPT4SPiUA/QMeHwEf/i4+Ej4mAP4THwEf/SE7PhE+JgD+BB8CH/4p +PhE+JwD+ER8CH/42PhA+JwD9AhwfAR/+JD4QPigA/gsfAh/+Kz4PPikA/hcfAh/+Mz4OPikA/QQd +HwEf/SE6Pg0+KgD+CR8CH/0kPT4MPisA/hEfAh/+Jj4MPisA/QEYHwIf/ig+Cz4sAP0DGh8CH/4q +Pgo+LQD9BBwfAh/9KD0+CD4uAP0FHR8CH/0mPT4HPi8A/QgdHwIf/SQ6PgY+MAD9BRwfAh/9ITM+ +BT4xAP0EGh8DH/4pPgQ+MgD9AxgfAx/9JDY+Aj40AP4QHwQf+yg7Pj4ANAD9CR0fAx/8IS49ADUA +/QQXHwQf/iEANwD9CRsfAx85AP0CER8CHzsA+wQSHh8APAD9AxEAfgAdH/0aBwAeAB4f/hoAHgAf +Hx8AHx8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+ +Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8f +ABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+Ax8fABs+ +Ax8fAB8A/mn/Bf/9/o2AFIAfAP0S+P8F//67gBSAIAD+rv8F//3xg4ATgCAA/lH/Bv/+sIATgCAA +/Qbr/wX//e6BgBKAIQD+hv8G//6sgBKAIQD9E/P/Bf/98IWAEYAiAP6P/wb//sCAEYAiAP0Z9/8F +//38k4AQgCMA/pb/Bv/+3IAQgCMA/RPs/wb//riAD4AkAP5p/wb//f2cgA6AJAD9Asj/Bv/98ImA +DYAlAP01/f8G//3agoAMgCYA/ov/B//+0IAMgCYA/QTF/wf//sSAC4AnAP0f7v8H//68gAqAKAD9 +TP7/B//9yIGACIApAP6G/wj//dCCgAeAKQD9AZ7/CP/924iABoAqAP0Drf8I//3wnIAFgCsA/QnC +/wj//f3AgASALAD9EMT/Cf/93JKAAoAtAP0HrP8J//r9yIWAgAAtAP0Env8K//zurIEALgD8AYX+ +/wr//u0AMAD9Tu3/Cv8yAP0fx/8n//zcqVAAEQD8BYv9/yj//aUPABEA/TTK/yj//qgAEgD8AV7r +/yf//lEAEwD8Fpb4/yX//qYAFQD8FoDx/yP//tsAFwD8FYXr/yH//v4AGQD+A/8i/xsAG4AH/xsA +G4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH +/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsA +G4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAPfv98tD7PPv9 +3tD7O/v8+dLQ+zv7/OLQ0Ps7+/zT0ND7Ovv+5NAB0Dr7/fnS0AHQOvv+3tAC0Dn7/fHP0AHQ/rz7 +OPv+1tAB0P3Mpvs3+/7f0ALQ/bOk+zb7/uvQAtD8w6Sk+zX7/fbS0AHQ+82qpKT7NPv9+dbQAtD+ +saQBpDX7/tnQAtD+vKQCpDT7/tzQAtD+xaQDpDP7/t/QAtD9yqekAqT+p/sx+/7c0ALQ/cyppAKk +/aUA+y/7/fnZ0ALQ/c2spAKk/KUAAPsu+/321tAC0P3Or6QCpPul/wAA+y37/e3S0ALQ/cutpAKk +/aO/AAEALfv+4NAD0P3KqqQDpP6ZAAIAK/v979bQA9D9xaekA6T+nwADACn7/Pnez9AD0P29paQC +pP2jqgAEACj7/eTS0APQ/c6ypAOk/aWqAAUA/eL5+yL7/Pnk09AE0P3DqKQDpP2l/wAGAPvQ0uDy ++x77/PLg0tAE0P3LtKQEpP6jAAgAA9D81uP2+xj7/Pfj1tAG0P28pqQEpP6nAAkABtD71d7q9/sQ ++/v36t7V0AbQ/M/AqqQEpP2jvwAKAP7O0AfQ68/U193j7O7x9vn59vHu7OXd19TP0AfQ/M++qaQF +pP6jAAwA/Ke2x9Ag0PzGtqekBaT9o6oADQACpPyru8nQGtD8yLqqpAak/aWmAA8ABaT7qLK+ytAS +0PvMwbWopAik/qEAEQAJpOunrrS7wcXIyszPz8zKyMbBu7SupqQIpPyjpKYAEwD+paQipPujpKWq +ABcAAaUfpP2lnwAdAPu/pqSlpBWk/KOkvwAlAP6npAGk/KOko6QEpPijpKOkpaSkAH8GoQA9rf2c +V608rf12V607rfyrXFetO638fVdXrTqt+6xeV1etOq3+gFcBVzqt/ahdVwFXOq3+clcBV/5VrTit +/ZhYVwFX/i+tOK3+ZFcBV/1OBa03rf53VwJX/R0ArTat/Y9YVwFX/D8AAK01rf2jXVcBV/tRCwAA +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 +GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sb +AA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsA +D6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAP +pA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+k +D9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP +0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QP0AP7GwAPpA/QA/sbAA+kD9AD+xsAD6QT0BsAD6QT0BsA +D6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT0BsAD6QT +0CsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsA +D1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cD +rSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsA +D1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cD +rSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsA +D1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAD1cDrSsAE1crABNXKwATVysAE1crABNXKwATVysAE1cr +ABNXKwATVysAE1crABNXKwATVysADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisA +Dx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8D +PisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisA +Dx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8D +PisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisA +Dx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisADx8DPisAEx8rABMfKwAT +HysAEx8rABMfKwATHysAEx8rABMfKwATHysAEx8rABMfKwATHxsAH/8DgBsAH/8DgBsAH/8DgBsA +H/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8D +gBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsA +H/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8D +gBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsA +H/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8DgBsAH/8D +gBsAH/8DgBsAI/8bACP/GwAj/xsAI/8bACP/GwAj/xsAI/8bACP/GwAj/xsAI/8bACP/GwAj/38N +APt/AwDQfw0ArX8DAFd/DQA+fwMAH38NAIB/AwD/D9APpB8AD9APpB8AD9APpB8AD9APpB8AD9AP +pB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8A +D9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9AP +pB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8A +D9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9AP +pB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8A +D9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9APpB8AD9AP +pB8AD9APpB8AD9APpB8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9X +LwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cv +AA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8A +D1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAP +Vy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA9XLwAPVy8AD1cvAA8fLwAPHy8ADx8vAA8f +LwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8v +AA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8A +Dx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAP +Hy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8fLwAPHy8ADx8vAA8f +LwAPHy8ADx8vAA8fLwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8f +AB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8A +H/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf +/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB// +HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8AH/8fAB//HwAf/x8ALwAHpAfQLwAHpAfQLwAH +pAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQ +LwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAH +pAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQ +LwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAH +pAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQ +LwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAHpAfQLwAH +pAfQLwAHpAfQLwAHpAfQLwAHpP7J0AXQLwAHpP2uydAE0DcAB1c3AAdXNwAHVzcAB1c3AAdXNwAH +VzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdX +NwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3 +AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcA +B1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwAHVzcAB1c3AAdXNwD+ +SVcFVzcA/RNIVwRXNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83 +AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcA +Bx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAH +HzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AAcf +NwAHHzcABx83AAcfNwAHHzcABx83AAcfNwAHHzcABx83AP4aHwUfNwD9BxofBB8vAA//LwAP/y8A +D/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP +/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA// +LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8v +AA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8AD/8vAA//LwAP/y8A +D/8vAA//LwD+/v8N/y8A/un/Df8vAP7I/w3/fw4A+38CANB/DgCtfwIAV38OAD5/AgAffw4AgH8C +AP8T+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6Qb +ABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsA +E/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT ++wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7 +B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH +0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQ +B6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AH +pBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAE/sH0AekGwAT+wfQB6QbABP7B9AHpBsAG9AHpBsA +G9AHpBsAG9AHpBsAG9AHpBsAG9AHpBsAG9AHpBsAGtD+yaQGpBsAGdD9ya2kBaT+pQAaABOtB1cj +ABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOt +B1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cj +ABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOt +B1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cj +ABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOt +B1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABOtB1cjABtXIwAbVyMAG1cj +ABtXIwAbVyMAG1cjABpX/kgAIgAZV/1IEwAiABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8j +ABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+ +Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8j +ABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+ +Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8j +ABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABM+ +Bx8jABM+Bx8jABM+Bx8jABM+Bx8jABsfIwAbHyMAGx8jABsfIwAbHyMAGx8jABof/hoAIgAZH/0a +BwAiABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8b +ABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOA +D/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8b +ABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOA +D/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8b +ABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bABOAD/8bACP/ +GwAj/xsAI/8bACP/GwAj/xsAIv/+/gAaACL//uEAGgAi//7LABoANwADpAPQNwADpAPQNwADpAPQ +NwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwAD +pAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQ +NwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwAD +pAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQ +NwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwAD +pAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQNwADpAPQ +NwADpAPQNwADpAPQNwADpAPQNwADpAPQOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7 +AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsA +A1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwAD +VzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANX +OwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAA1c7AANXOwADVzsAAx87 +AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsA +Ax87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwAD +HzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMf +OwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87AAMfOwADHzsAAx87 +AAMfOwADHzsAAx87AAMfOwADHzsAAx83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcA +B/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH +/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/ +NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83 +AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/NwAH/zcAB/83AAf/fxAA+38Q +AK1/EAA+fxAAgBv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6Qb +ABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsA +G/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb ++wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7 +A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD +0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQ +A6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9AD +pBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOk +GwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6QbABv7A9ADpBsAG/sD0AOkGwAb+wPQA6Qb +ABv7A9ADpBsAG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8A +G60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60D +Vx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8A +G60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60D +Vx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8A +G60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60D +Vx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AG60DVx8AGz4DHx8A +Gz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4D +Hx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8A +Gz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4D +Hx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8A +Gz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4D +Hx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8A +Gz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AGz4DHx8AG4AH/xsAG4AH/xsAG4AH/xsAG4AH +/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsA +G4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH +/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsA +G4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH +/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsA +G4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH/xsAG4AH +/xsAG4AH/xsAG4AH/xsAG4AH/xsAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/CgAA +fwoAAH8KAAB/CgAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/ +EAAAfxAAAH8QAAB/EAAAfxAAABsAD6QT0BsAD6QT0BsAD6T+ydAR0BsAD6T9rsnQENAbACOkGwD+ +o6QhpBsA/qOkIaQbAP6mpCGkHAD+o6QgpBwAIqQdACGkHQD9oaOkHqQeACCkHgD+qqQepB8A/qqk +HaQgAP2fpaQbpCIA/aSjpBmkIwD9oqOkGKQlAP6lpBekJwD7qqOko6QSpH8LAAArABNXKwATVysA +/klXEVcrAP0TSFcQV38PAAArABMfKwATHysA/hofER8rAP0HGh8QH38PAAAbACP/GwAj/xsA/u3/ +If8bAP7T/yH/GwD+t/8h/xsA/o7/If8bAP5Z/yH/GwD9FPf/IP8cAP6n/yD/HAD+O/8g/x0A/q7/ +H/8dAP0m+P8e/x4A/nj/Hv8eAP0Dn/8d/x8A/QO//xz/IAD9CKH/G/8iAP1r+P8Z/yMA/SzA/xj/ +JQD8MK71/xX/JwD5CUuMwOPo/xD/fwsAAH8BANB/BACkfwsAAH8BAFd/DwAAfwEAH38PAAB/BQD/ +fwsAAA/QD6QfAA/QD6QfAA7Q/smkDqQfAA3Q/cmtpA6kHwAfpB8AHqT+pQAeAB6k/qMAHgAepP6f +AB4AHqQgAB2k/qIAHwAcpP6jACAAHKT+pgAgABykIgAbpCMAGaT9o6oAIgAYpP2lmQAjABik/oAA +JAAWpP6oACYAE6QBpSkADaQCo/ylpJ0AfwsrAA9XLwAPVy8ADlf+SAAuAA1X/UgTAH8PLwAPHy8A +Dx8vAA4f/hoALgANH/0aBwB/Dy8AH/8fAB7//v4AHgAe//7fAB4AHv/+3wAeAB7//r8AHgAe//6N +AB4AHv/+SAAeAB3//fQIAB4AHf/+rgAfABz//f0sAB8AHP/+tQAgABv//fcrACAAG//+bQAhABr/ +/p0AIgAZ//3ABgAiABj//awFACMAFv/893gCACQAFf/9sCMAJgAS//zvnj4AKAAN//nqzrKNVw0A +fwsrAC8AD6QvAP6lpA2kLwD9/6OkDKQwAP6jpAykMQD+paQLpDIADKQzAP6lpAmkNQAJpH8OAAB/ +EAAAfxAAAC8A/pf/Df8vAP5B/w3/LwD9AcP/DP8wAP0v/P8L/zEA/mb/C/8yAP1r+f8J/zMA/TO7 +/wj/NQD7Q4zK4f8E/38OAAB/AgCkfw4AAH8QAAB/EAAAfwIA/38OAAAjpBsAI6QbACKkHAAhpP6j +ABsAIaQdAB+k/qMAHQAdpAGjHwAcpP2l/wB/DiAAfxAAAH8QAAAi//6MABoAIv/+QwAaACH//rsA +GwAg//35MgAbACD//mgAHAAe//37ZwAdAB3//cMvAB4AGf/66MeVPgEAfw4gADcAA6QD0DcAA6QD +0DcA/qOkAaT+ydAB0DcAA6T7rsnQ0AA2AAekOAAGpDgA/qqkBKQ6APqlpKOkpAB/Df8AOwADVzsA +A1c7AP5JVwFXOwD7E0hXVwB/Dv8AOwADHzsAAx87AP4aHwEfOwD7BxofHwB/Dv8ANwAH/zcA/v7/ +Bf83AP7c/wX/NwD+qf8F/zcA/lH/Bf84AP6m/wT/OAD9D6b/A/86APpPqNz//wB/Df8AfwEA0H8B +AKR/DgAAfwEAV38PAAB/AQAffw8AAH8CAP9/DgAAH9ADpBsAH9ADpBsAHtD+yaQCpBsAHdD9ya2k +AaT+owAaACKk/qMAGgAipBwAIaT+qgAbACCkfw4fAB9XHwAfVx8AHlf+SAAeAB1X/UgTAH8PHwAf +Hx8AHx8fAB4f/hoAHgAdH/0aBwB/Dx8AI/8bACL//v4AGgAi//7bABoAIv/+pwAaACL//k4AGgAh +//6jABsAIP/9qA8AGwAd//zbplEAfw4eAH8QAAB/EAAAfxAAAH8QAAB/EAAAfxAAAH8QAAB/EAAA +fwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/ +CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8K +AAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoA +AH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAA +fwoAAH8KAAB/CgAAfwoAAH8KAAB/CgAAfwoAAH8GQAB/BkAAfwZAAH8GQAAAAAH0AAAB9AAAAAAA +AAD6AAAA+gAAAAAAAAB9AAAAfQAAAAAAAAA+AAAAPgAAAAA= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/gswin64c/488450070287cd66d418d312b70b4285.msg b/share/extensions/tests/data/cmd/gswin64c/488450070287cd66d418d312b70b4285.msg new file mode 100644 index 0000000..dcdf9a3 --- /dev/null +++ b/share/extensions/tests/data/cmd/gswin64c/488450070287cd66d418d312b70b4285.msg @@ -0,0 +1,63 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: gswin64c +Arguments: -q -P- -dSAFER -dNOPAUSE -dBATCH -sDEVICE#pdfwrite -dCompatibilityLevel#1.4 -sOutputFile#.\output.pdf -dAutoRotatePages#/None test.ps + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.pdf + +JVBERi0xLjQKJcfsj6IKJSVJbnZvY2F0aW9uOiBwYXRoL2dzIC1QLSAtZFNBRkVSIC1kQ29tcGF0 +aWJpbGl0eUxldmVsPTEuNCAtZEF1dG9Sb3RhdGVQYWdlcz0vTm9uZSAtcSAtUC0gLWROT1BBVVNF +IC1kQkFUQ0ggLXNERVZJQ0U9cGRmd3JpdGUgLXNzdGRvdXQ9PyAtc091dHB1dEZpbGU9PyAtUC0g +LWRTQUZFUiAtZENvbXBhdGliaWxpdHlMZXZlbD0xLjQgLWRBdXRvUm90YXRlUGFnZXM9L05vbmUg +Pwo1IDAgb2JqCjw8L0xlbmd0aCA2IDAgUi9GaWx0ZXIgL0ZsYXRlRGVjb2RlPj4Kc3RyZWFtCnic +XY9NDkIhDIT3PUVPUId/egy9AonPBW+h3j8REIgxBOhXwsz0yRDD6Gve5aTLLfHxJogCTltbwtiv +g0wUb2BZM/gkNUmcH1BJbXvzOkidkxRYk5WoujE6CcqFJttx1oXGS/S5yU2hpu2089dlYdkhVqdS +q4CUdwdbDNOlEJZ/7eVMtj720L+zFXr8zXqnK30ALt066mVuZHN0cmVhbQplbmRvYmoKNiAwIG9i +agoxNTAKZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01lZGlhQm94IFswIDAgOTQgOThdCi9Q +YXJlbnQgMyAwIFIKL1Jlc291cmNlczw8L1Byb2NTZXRbL1BERl0KL0V4dEdTdGF0ZSA4IDAgUgo+ +PgovQ29udGVudHMgNSAwIFIKPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRz +IFsKNCAwIFIKXSAvQ291bnQgMQo+PgplbmRvYmoKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nIC9Q +YWdlcyAzIDAgUgovTWV0YWRhdGEgOSAwIFIKPj4KZW5kb2JqCjcgMCBvYmoKPDwvVHlwZS9FeHRH +U3RhdGUKL09QTSAxPj5lbmRvYmoKOCAwIG9iago8PC9SNwo3IDAgUj4+CmVuZG9iago5IDAgb2Jq +Cjw8L1R5cGUvTWV0YWRhdGEKL1N1YnR5cGUvWE1ML0xlbmd0aCAxMzY2Pj5zdHJlYW0KPD94cGFj +a2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPD9hZG9iZS14 +YXAtZmlsdGVycyBlc2M9IkNSTEYiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRh +LycgeDp4bXB0az0nWE1QIHRvb2xraXQgMi45LjEtMTMsIGZyYW1ld29yayAxLjYnPgo8cmRmOlJE +RiB4bWxuczpyZGY9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMn +IHhtbG5zOmlYPSdodHRwOi8vbnMuYWRvYmUuY29tL2lYLzEuMC8nPgo8cmRmOkRlc2NyaXB0aW9u +IHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHht +bG5zOnBkZj0naHR0cDovL25zLmFkb2JlLmNvbS9wZGYvMS4zLycgcGRmOlByb2R1Y2VyPSdHUEwg +R2hvc3RzY3JpcHQgOS41MCcvPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJm +NjFmNS1kNzM4LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHhtbG5zOnhtcD0naHR0cDovL25zLmFk +b2JlLmNvbS94YXAvMS4wLyc+PHhtcDpNb2RpZnlEYXRlPjIwMjItMDMtMDhUMjE6MDg6NDYrMDE6 +MDA8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0ZURhdGU+MjAyMi0wMy0wOFQyMTowODo0Nisw +MTowMDwveG1wOkNyZWF0ZURhdGU+Cjx4bXA6Q3JlYXRvclRvb2w+Y2Fpcm8gMS4xNS4xMCAoaHR0 +cDovL2NhaXJvZ3JhcGhpY3Mub3JnKTwveG1wOkNyZWF0b3JUb29sPjwvcmRmOkRlc2NyaXB0aW9u +Pgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4LTExZjctMDAw +MC1lYTcwYWVjZmY4MGUnIHhtbG5zOnhhcE1NPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAv +bW0vJyB4YXBNTTpEb2N1bWVudElEPSd1dWlkOjFjMmY2MWY1LWQ3MzgtMTFmNy0wMDAwLWVhNzBh +ZWNmZjgwZScvPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4 +LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHhtbG5zOmRjPSdodHRwOi8vcHVybC5vcmcvZGMvZWxl +bWVudHMvMS4xLycgZGM6Zm9ybWF0PSdhcHBsaWNhdGlvbi9wZGYnPjxkYzp0aXRsZT48cmRmOkFs +dD48cmRmOmxpIHhtbDpsYW5nPSd4LWRlZmF1bHQnPlVudGl0bGVkPC9yZGY6bGk+PC9yZGY6QWx0 +PjwvZGM6dGl0bGU+PC9yZGY6RGVzY3JpcHRpb24+CjwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0ndyc/PgplbmRzdHJl +YW0KZW5kb2JqCjIgMCBvYmoKPDwvUHJvZHVjZXIoR1BMIEdob3N0c2NyaXB0IDkuNTApCi9DcmVh +dGlvbkRhdGUoRDoyMDIyMDMwODIxMDg0NiswMScwMCcpCi9Nb2REYXRlKEQ6MjAyMjAzMDgyMTA4 +NDYrMDEnMDAnKQovQ3JlYXRvcihjYWlybyAxLjE1LjEwIFwoaHR0cDovL2NhaXJvZ3JhcGhpY3Mu +b3JnXCkpPj5lbmRvYmoKeHJlZgowIDEwCjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDY1NyAw +MDAwMCBuIAowMDAwMDAyMjMzIDAwMDAwIG4gCjAwMDAwMDA1OTggMDAwMDAgbiAKMDAwMDAwMDQ2 +OSAwMDAwMCBuIAowMDAwMDAwMjMwIDAwMDAwIG4gCjAwMDAwMDA0NTAgMDAwMDAgbiAKMDAwMDAw +MDcyMSAwMDAwMCBuIAowMDAwMDAwNzYyIDAwMDAwIG4gCjAwMDAwMDA3OTEgMDAwMDAgbiAKdHJh +aWxlcgo8PCAvU2l6ZSAxMCAvUm9vdCAxIDAgUiAvSW5mbyAyIDAgUgovSUQgWzw0MjBGREMzQkUx +QTY5NDY2MzI5Q0NGMjFBRDkyNjVBQT48NDIwRkRDM0JFMUE2OTQ2NjMyOUNDRjIxQUQ5MjY1QUE+ +XQo+PgpzdGFydHhyZWYKMjQwOQolJUVPRgo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/gswin64c/67ad522b1b2203d1e9355c8bcb6bacfc.msg b/share/extensions/tests/data/cmd/gswin64c/67ad522b1b2203d1e9355c8bcb6bacfc.msg new file mode 100644 index 0000000..287e00b --- /dev/null +++ b/share/extensions/tests/data/cmd/gswin64c/67ad522b1b2203d1e9355c8bcb6bacfc.msg @@ -0,0 +1,63 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: gswin64c +Arguments: -q -P- -dSAFER -dNOPAUSE -dBATCH -sDEVICE#pdfwrite -dCompatibilityLevel#1.4 -sOutputFile#.\output.pdf -dAutoRotatePages#/None test.eps + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.pdf + +JVBERi0xLjQKJcfsj6IKJSVJbnZvY2F0aW9uOiBwYXRoL2dzIC1QLSAtZFNBRkVSIC1kQ29tcGF0 +aWJpbGl0eUxldmVsPTEuNCAtZEF1dG9Sb3RhdGVQYWdlcz0vTm9uZSAtcSAtUC0gLWROT1BBVVNF +IC1kQkFUQ0ggLXNERVZJQ0U9cGRmd3JpdGUgLXNzdGRvdXQ9PyAtc091dHB1dEZpbGU9PyAtUC0g +LWRTQUZFUiAtZENvbXBhdGliaWxpdHlMZXZlbD0xLjQgLWRBdXRvUm90YXRlUGFnZXM9L05vbmUg +Pwo1IDAgb2JqCjw8L0xlbmd0aCA2IDAgUi9GaWx0ZXIgL0ZsYXRlRGVjb2RlPj4Kc3RyZWFtCnic +XY9LDgIxCIb3nIITIPQ5HEM3HqDRcdExGb1/Ih3bxhjSlo/CD+zIJMjN+ls2OF0yrm/YobEGOwvj +64ZXfAJTis6HYPkLu+ybE0WyKL5WkERB2B0FG6hksoQGFdTZX9CD1HvKETU7SqoTk6eoWKCzO+46 +UAKlsJhcFzJtr42/XQaWOcSIVDCPOS8zwlOMe5diu/b+tbl9slHYhv7drcDjb9c7nM0+x5xBzGVu +ZHN0cmVhbQplbmRvYmoKNiAwIG9iagoxNzEKZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01l +ZGlhQm94IFswIDAgNTk1IDg0Ml0KL1BhcmVudCAzIDAgUgovUmVzb3VyY2VzPDwvUHJvY1NldFsv +UERGXQovRXh0R1N0YXRlIDggMCBSCj4+Ci9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKMyAwIG9i +ago8PCAvVHlwZSAvUGFnZXMgL0tpZHMgWwo0IDAgUgpdIC9Db3VudCAxCj4+CmVuZG9iagoxIDAg +b2JqCjw8L1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDMgMCBSCi9NZXRhZGF0YSA5IDAgUgo+PgplbmRv +YmoKNyAwIG9iago8PC9UeXBlL0V4dEdTdGF0ZQovT1BNIDE+PmVuZG9iago4IDAgb2JqCjw8L1I3 +CjcgMCBSPj4KZW5kb2JqCjkgMCBvYmoKPDwvVHlwZS9NZXRhZGF0YQovU3VidHlwZS9YTUwvTGVu +Z3RoIDEzNjY+PnN0cmVhbQo8P3hwYWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJl +U3pOVGN6a2M5ZCc/Pgo8P2Fkb2JlLXhhcC1maWx0ZXJzIGVzYz0iQ1JMRiI/Pgo8eDp4bXBtZXRh +IHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJyB4OnhtcHRrPSdYTVAgdG9vbGtpdCAyLjkuMS0xMywg +ZnJhbWV3b3JrIDEuNic+CjxyZGY6UkRGIHhtbG5zOnJkZj0naHR0cDovL3d3dy53My5vcmcvMTk5 +OS8wMi8yMi1yZGYtc3ludGF4LW5zIycgeG1sbnM6aVg9J2h0dHA6Ly9ucy5hZG9iZS5jb20vaVgv +MS4wLyc+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFm +Ny0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6cGRmPSdodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8x +LjMvJyBwZGY6UHJvZHVjZXI9J0dQTCBHaG9zdHNjcmlwdCA5LjUwJy8+CjxyZGY6RGVzY3JpcHRp +b24gcmRmOmFib3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScg +eG1sbnM6eG1wPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvJz48eG1wOk1vZGlmeURhdGU+ +MjAyMi0wMy0wOFQyMTowOTo0MCswMTowMDwveG1wOk1vZGlmeURhdGU+Cjx4bXA6Q3JlYXRlRGF0 +ZT4yMDIyLTAzLTA4VDIxOjA5OjQwKzAxOjAwPC94bXA6Q3JlYXRlRGF0ZT4KPHhtcDpDcmVhdG9y +VG9vbD5jYWlybyAxLjE1LjEwIChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmcpPC94bXA6Q3JlYXRv +clRvb2w+PC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlk +OjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6eGFwTU09J2h0dHA6 +Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8nIHhhcE1NOkRvY3VtZW50SUQ9J3V1aWQ6M2M1ZjIw +ZjUtZDczOC0xMWY3LTAwMDAtODMwZGI0OGE4ZGRlJy8+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFi +b3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6ZGM9 +J2h0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvJyBkYzpmb3JtYXQ9J2FwcGxpY2F0aW9u +L3BkZic+PGRjOnRpdGxlPjxyZGY6QWx0PjxyZGY6bGkgeG1sOmxhbmc9J3gtZGVmYXVsdCc+VW50 +aXRsZWQ8L3JkZjpsaT48L3JkZjpBbHQ+PC9kYzp0aXRsZT48L3JkZjpEZXNjcmlwdGlvbj4KPC9y +ZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hw +YWNrZXQgZW5kPSd3Jz8+CmVuZHN0cmVhbQplbmRvYmoKMiAwIG9iago8PC9Qcm9kdWNlcihHUEwg +R2hvc3RzY3JpcHQgOS41MCkKL0NyZWF0aW9uRGF0ZShEOjIwMjIwMzA4MjEwOTQwKzAxJzAwJykK +L01vZERhdGUoRDoyMDIyMDMwODIxMDk0MCswMScwMCcpCi9DcmVhdG9yKGNhaXJvIDEuMTUuMTAg +XChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmdcKSk+PmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAw +MCA2NTUzNSBmIAowMDAwMDAwNjgwIDAwMDAwIG4gCjAwMDAwMDIyNTYgMDAwMDAgbiAKMDAwMDAw +MDYyMSAwMDAwMCBuIAowMDAwMDAwNDkwIDAwMDAwIG4gCjAwMDAwMDAyMzAgMDAwMDAgbiAKMDAw +MDAwMDQ3MSAwMDAwMCBuIAowMDAwMDAwNzQ0IDAwMDAwIG4gCjAwMDAwMDA3ODUgMDAwMDAgbiAK +MDAwMDAwMDgxNCAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDEwIC9Sb290IDEgMCBSIC9JbmZv +IDIgMCBSCi9JRCBbPDFCMTc4NTEyQUMzRTA0QkM2OUE4RTdFNUZFMjM3OEJCPjwxQjE3ODUxMkFD +M0UwNEJDNjlBOEU3RTVGRTIzNzhCQj5dCj4+CnN0YXJ0eHJlZgoyNDMyCiUlRU9GCg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/03dd4e9c9ee257c7ae161057ebe7c8a3.msg b/share/extensions/tests/data/cmd/inkscape/03dd4e9c9ee257c7ae161057ebe7c8a3.msg new file mode 100644 index 0000000..0e85321 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/03dd4e9c9ee257c7ae161057ebe7c8a3.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:951:1000:1000 --export-filename=guides_8.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_8.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_8.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/054966b8da855f76de0c1c5c2615c696.msg b/share/extensions/tests/data/cmd/inkscape/054966b8da855f76de0c1c5c2615c696.msg new file mode 100644 index 0000000..152778f --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/054966b8da855f76de0c1c5c2615c696.msg @@ -0,0 +1,93 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=364:0:794:495 --export-filename=output_1.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output_1.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output_1.png + +iVBORw0KGgoAAAANSUhEUgAAAa4AAAHvCAYAAAAM8TtTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAADz1JREFUeJzt3XusZVddB/BvmbbT +mY6ddoDykFYJWqEKKgot7ZQ5bYlYIVWjUQMmBjURjfCPrahBoxirVjQoqUaDKcbGpNjEByoxEOda +KS1WLI+C7/poYSr0YaelTjudXv9YvXK5c8/e65yz9z773vl8kvPXWXet37nnnP07ez0TAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +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 +SFzb0P8B5XOkSURDMFMAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/0ac64d7c051206284e72bf3e0800186d.msg b/share/extensions/tests/data/cmd/inkscape/0ac64d7c051206284e72bf3e0800186d.msg new file mode 100644 index 0000000..8ec387e --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/0ac64d7c051206284e72bf3e0800186d.msg @@ -0,0 +1,1025 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:49:953:951 --export-filename=guides_4.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_4.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_4.png + +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 +EkVERPyloCgiIl6b6zrFggnvvwv+1dNqREREZNYUFEVExGtzCYoFFz6gkCgiIrIwKCiKiIin5rBF +RsGFD2yBf5mXgkRERGTWFBRFRMRT5uyCYsGAOxUSRUREFhYFRRER8dQstsiwXPjgJvi/81qQiIiI +zJqCooiIeCoARyltcVGO5ZZGEv+5EjWJiIjI7CgoioiIp+4E24BDZU6xDdiqkCgiIrJwKSiKiIjn +yjS0sQ3YvAm+UdGCREREZFYUFEVExHPG2YOi7cIWhUQREZGFT0FRREQ8d5YRRZvSdNOv+1GPiIiI +zE7Q7wJERKQmTex8ahvwkU3woG/ViIiIyKxoRFFERDznvDGiaAMf3QQP+FmPiIiIzI6CooiIeG4Q +DgAW8NHNsN3vekRERERERGQBeADe7ncNIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJSmwy/C6gX +X4flNqwzYJ0LF7pwgQGtQGLsTxOQcsE2IAMMAmlK/94D7DFgrwF7grDnztIxERERERERzykozoN7 +wFwDlxtwqwu3GXAjkPL4NqeBR1142IGdH4G9Hl9fRERERGTOXDC2wXID1huwDrgIWA0088Zgyfi/ +Q2mAZGDsnxlgwID9Lrzqwl4X9myBowa4lf/b1B8FRY98CSKt8E4XPgzcBrRMfD4YDRBOhYikgkRS +ISINIYIREzNoYgQNAiETM2SC62IXXZyCg110cIouxVGbQtoin7YoDBfJpy1sy5lawjEX/h3Yvh8e +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 +N/B+4HJgFXBusonaXh/1PS8fC+DWjXBv4CqPDbUFPhTB1RFcHMB5Sedpc89Tv2j8t5N3faU5YVGU +mtBNcEsAVyWdQ4n6Ri9cmXQISZLUmhx6KjWhAL6YdAYlKgzhU0mHkCRJrcuiKDWhXrgfh5u0rQhu +uxaeSjqHJElqXRZFqUnV4JMRlJLOoYYrpuE3kw4hSZJam0VRalLXwfYAPpN0DjXcb26EbUmHkCRJ +rc2iKDWxLPwv4KtJ51DD/E0vfCHpEJIkqfVZFKUmtgFqWfh54PtJZ9HciuDuyf3MJEmS5pxFUWpy +G6BWgfcHcGPSWTQ3Avj7CXjvBignnUWSJLUH91GUWshm+JUIPh9AZ9JZNCuKwGefhz/+DIRJh5Ek +Se3Doii1mBvhwgC+GMA7k86i0/LNDviNq2BH0kEkSVL7sShKLWoLvDGqb8r+74EFSefRSRkJ6vtj +fvUauCfpMJIkqX1ZFKUWtxW6S3BFAO+K4OIAzgMywKqks7WzCA4D+4B9KXgugodK8J2fg1zS2SRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiS1hP8P8aK48RBoJeEAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/106011cd22941d59371660c2b4abf75c.msg b/share/extensions/tests/data/cmd/inkscape/106011cd22941d59371660c2b4abf75c.msg new file mode 100644 index 0000000..b7ea54f --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/106011cd22941d59371660c2b4abf75c.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:0:47:49 --export-filename=f0oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f0oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f0oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/12146d0ed761a6686175edea7c8df347.msg b/share/extensions/tests/data/cmd/inkscape/12146d0ed761a6686175edea7c8df347.msg new file mode 100644 index 0000000..0de85fa --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/12146d0ed761a6686175edea7c8df347.msg @@ -0,0 +1,171 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=364:495:794:1123 --export-filename=output_3.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output_3.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output_3.png + +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 + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/1b0252977bd9eafe0af2686834decd6e.msg b/share/extensions/tests/data/cmd/inkscape/1b0252977bd9eafe0af2686834decd6e.msg new file mode 100644 index 0000000..4240d93 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/1b0252977bd9eafe0af2686834decd6e.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:951:953:1000 --export-filename=guides_7.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_7.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_7.png + +iVBORw0KGgoAAAANSUhEUgAAA4oAAAAxCAYAAACcaFfTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAMNJREFUeJztwTEBAAAAwqD1T20M +H6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAATga19wABjrwhtgAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/1c734cd0171b9097039996e1bd63ed6f.msg b/share/extensions/tests/data/cmd/inkscape/1c734cd0171b9097039996e1bd63ed6f.msg new file mode 100644 index 0000000..4e28399 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/1c734cd0171b9097039996e1bd63ed6f.msg @@ -0,0 +1,569 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area-page --export-background-opacity=0 --export-dpi=96 --export-filename=Slide2.png --export-id-only --export-id=layer2 --export-type=png Slide2.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide2.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide2.png + +iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoCAYAAABNo9TkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAIABJREFUeJzs3Xe4bGV99//3cABF +bNgriopdYzeKLcYYa3rsLU+MGpPYYouKDkWjiZonGlP8PYkR7GgSS1RUTCL22EGsoNgQUZAmcOCc ++f2xNoIdzp6918zer9d1rWv2OTr3+nBm77XnO/e97m8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAOeajB0AgPUxq0tWlzvfcdkfOy5fXbratdp95Wm7r/y5ao+Vx/P/76dXW1e+ +PmnlcevK35//f/9+dUL1vfMd3z3f43cndcp8/kuBpfeCLtHWrta2rtxwvbp0k/Zo1qUbrkWXXjn2 +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 +yUXqxPe3eVup7aiPVHfSJ31jmtUDGzbaGqOY+ujKuV8/qZNGOD9rZKWV2wOqP6huPUKEM6uHT4YP +ntgo9uv+zfqXhk0M19VNrlCPuVU95KYbtxf5ZvX9M+u1Rw7F+se+NVqM97Wl/9O+HT1aAlhiO40d +gB114l+nON8Rt224t5MNZjbsePyq1rc4396w0duvTeq2k/pHxfnGM6mTJvUPk7pNw3X34NZ3ZcRF +q9fNarqO52QtTXtss17TOhbnF9kyzJQf/gf1mT+ux95acb4Rbd02HNvHvRv8Tm3rM+3X45uqNeDC +MoO+lKb3aVhC6/XbMbPqd2r6H2MHYfVmw8/BS6s/WcfTntmwhP3Fk7KvwSY0q+tVT6oe1lBAr5eX +VE+Y2Ixpee3XM5t14Hqdbvdd6lG3rCffvq5yifU6K+vprG311i/UQZ+ud355aNW2QN6/Mpv+pbGD +wLJQ4C2d6Z7VJ6vLjJ1kyZ1UW25Z+35l7CDsuNmwCuifqkeu0ylPrP6uetmkvrNO52SBzeoK1Z82 +fEC0Xtflf6weq0hfOpOmvbDhg501d6mL1J/epp7wy3W5dV9Ez3r44Nfr4M8Mm8SddObYaX6uM6pn +dcP+tvvZlwV+kZ3HDsCFMqn+NcX5POxR215e/drYQdgxK8X5KxpmMNfaqdX/rV40qZPX4XwsiZUP +ap49qxdVT66eUF18jU/7mGqXWT1qko2YlsSkaf9YPWqtT7T7LvWUfYbC/FKWsG84X/3+UJQf/On6 +0oljp7nAdqv266h+0PABI/BzmEFfKvs9uGavGjvFxjJ5QD3n9WOn4MKbDUt9/2yNT3NO9Q/VAVpd +cUGszKg/u3p0a/8h+P+d1BPX+BzMw7T9q33X8hQ7Tep3b1AvvHvteam1PBPr7Yxz6m1frJd/vA47 +ZqmWzmyvPlQdVL2maaeNnAeWggJ9aUwvWX2u0p10vr5dF71+Pd2s6BKZ1TOq567xad7bcK/vEWt8 +HjaglXvU/6a65xqf6umTesEan4PVmPbI6v9by1Pcda960d3rZlday7OwnrbN6t1HD7Pl/z5u67Qd +cVSTDmrWq5v2jbHDwLKxxH15HJjifC1cqc58Tut0TyCrN6sH1ZpusHRc9bhJvXENz8EGN6kvVPea +1f2rv62uuEan+stZfW1Sr12j8VmNafdqWIWzJi5/sXrpver+N1qrM7DejvxOvfLT9Zoj6lunjp3m +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 +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkpREJXUBbWAD4H+ALYB7 +gPOA+5NWJEmSJElSm9kaeAro6TdWAD8Bdk5YlyRJkiRJbeVXvDScrzr+CByYrDpJkiRJktrEE6w9 +oPeN24DDgMFpypQkSZIkqbX9g7iA3jfuBz4CjExRrCRJkiRJrepEsgX0vvEUcAowsfElS6VVwYUt +JUmSJNVoPPAstYX0HmAxcDawaYPrlsqmAnwVOAdDuiRJkqQafZnaA3rf6AIuAXZrcO1SGfSF877n +gyFdkiRJLckPucXbELgPGJrT/q4HzgIuJYQVqZVVgK8AH1vl388FPozPAUlqF2OAzQhnFW4ATOod +k4GxvWMUMLp3W4CO3n/vs5DwvvEM4eDHYmA58BywrPe/c1cZjwOPERb+XVHQ3yZJarAfUP9R9FXH +X4F348rval2rHjlfdXwVv2SUpFazDrAv8FHg28CfCWvz5P05KuvoJgT2m4HvAZ8GXgdsUszdIEkq +0naEF/Yi3jDuJRxJHNGwv0Yq3kDh3NPdJak1TCRcavYbwO2Eo9Spw3jWsQj4C/AdwhlfuwCD8ryT +JEn5u4xi3xyeBKrAhAb9PVJRYsO5IV2SmtNWhCvd/IXmDOSxof1S4BhgdzzjUZJKZxaNeUNYTAg3 +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 +/4R1SZIkSZLUdmYAD7AymHcBJyatSJIkSZKanKfvqlYjCEfMJwDXElaclSRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJTWZQ +6gKkl5jDm5jFSDqZm7oUSZIkSWqkjtQFSC/RwyuBP1Bl29SlSJIkSVIjGdBVNlsDE4ErOY3pqYuR +JEmSpEYxoKtstun973p0cTmnMS1pNVKZzOFNnMouqcuQJElSMQzoKo8qg4HN+v3LhnTRyelskqok +qVR6eCXdXMGp7JS6FEmSJOXPgK7yGMQ0YOgq/7oxK/gjVSanKEkqmW2Adenm97aASJIktR4Dusqj +i63X8H+2BC7nDCY0shyphPqeI6EFpPqSM04kSZLU5AzoKpNt1vL/tuMFruBMxjWsGqlMVtcCAlfb +AiJJktQ6DOgqkzUdQe+zI8v4LVVGN6QaqUzW1gLyGaakKEmSJEn5MqCrTAYK6AB7AL/mS4wouhip +VNbWArKcP9gCIkmS1PwM6CqTrSK3249n+DnVlx1NlFqZLSCSJEktzoCucqiyLrB+hlscBPy4ty9X +agcxLSCXcRZjGlKNJEmScmdAV1ms7ejgmrwZ+DEXMyjvYqQSimkB2Z2lXMbnGVV4NZIkScqdAV3l +UIkKH6vzVu7ku1Sdy2p5sS0ge7GEn9kCIkmS1HwMNSqHnujwsTpHAF/JqRKpfLK3gLwO+IktIJIk +Sc3FgK6yqOUU9/4+SpUv5VKJVD61PD/ehC0gkiRJTcWArrKo9RT3/j7BHE7KYT9SudgCIkmS1Bb8 +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 +AABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/1f50fa6d71e2543dd18dfc807fe56018.msg b/share/extensions/tests/data/cmd/inkscape/1f50fa6d71e2543dd18dfc807fe56018.msg new file mode 100644 index 0000000..d712d0c --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/1f50fa6d71e2543dd18dfc807fe56018.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:951:1000:1000 --export-filename=f8oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f8oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f8oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/21e5197995b5aa619151b61ebee79f23.msg b/share/extensions/tests/data/cmd/inkscape/21e5197995b5aa619151b61ebee79f23.msg new file mode 100644 index 0000000..4be9ba8 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/21e5197995b5aa619151b61ebee79f23.msg @@ -0,0 +1,261 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area-page --export-background-opacity=0 --export-dpi=96 --export-filename=Slide1.png --export-id-only --export-id=layer1 --export-type=png Slide1.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide1.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide1.png + +iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoCAYAAABNo9TkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAIABJREFUeJzs3Xm8bfd8+P/XvTeR +gURGQ81BQ1ElYh6DolVDzepbtIpqqzorlRxDabX1rVJFh6hSokMMxZcKMdY8l8QQsxCEBJnvvb8/ +Pvv87rknd8i5Z5/xPp+Px36cs9Ze+7Pee69h7/f6DKsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaWTSsdAMvi8OrQ6oeT6UOrI6pzVyyiPbNv +de3qx9XmXSx3tcmy5y9DTKwfV6qu0Ni/duXqjXPnBTt5flN1ncb+d0m1oTqqurC6eCqRrk4HN469 +QyePK7T2zjGsLUdWB7X7YxYA1owNKx0AO/TI6tbVr+/guedXn6r+YQHl/XX1M9WdJ9MnVL9Y3XTP +Q+yx1Y2rJ86b/1fVlatfrrbMmf/H1X7VzCLW+ZPV6ZP1/u8ulvtI9abqaYtY11x/Mvn7rB08d1L1 +yur1k+m/qK41+X9LdWb1H9V75rzmFdXlJv9fUn2t+ufqM5N5h1d/t5NY3lP9zeT/v6quMfl/62Rd +/1W9bXdvaI17ZPXz1Se79DY5qHFsbGhst88toNxXNPbRB02mb1jtX31s3nKfqP6zevpOyjmyOqu6 +Q2N77dNIzO9TvWEB8awVG6tXVQ+uftDYF/evvlldb5ljOab6UeM8MW3Xrw6pPrQEZS+F+1b/p/qp +yfSXq3dVf199b4VimraXVVes7r/CcQDA1Gxc6QDYoZs2EpAduVd182WMZWe2VL/RSCZnHdRI2B9c +3WTO/A3Vk6rLL1t003WH6o47ee6B1Q3mTN+9um7jIsHpjW357ra/2PKLjdrGjzR+NN+tkWz+7OT5 +AxtJ4uWqM+Y9zppTzj0aLQo+Un22kVD+dztPHNeLmzaS3T+pDpv33IMaicmD2n7f3BNPqv5sB/NP +bPsLLruzpfrz6guLjGe1Oq56QGO/P7SxTWZWKJa/rH5zicp+bNsujq1mGxr76L81LlY8p3FR9p2N +4+IDKxcaALA7+6x0AEzNQY0fyN+ovrOHZVxxUsbZjcRxV05tXOC5Q/XaybzbVd9u1G7fqVHTWCNx +vNLkNbMu10hsN1entfMm6wc0aq6+uYtYDqyObrz3s3ax3HL5VCMhm/XGRsIyt1b83XOWOaHxWT2t +euucZV7Z+JG9K5+ct66TqydMylzPvlRdVD20etGc+Y9qtGZ40A5eMy1/vcDlt1RP3slzGxvHwQ8b +LSl25ODGcfnVVmfN57UbNednXIZlr9CoVT/3Mi4/bddo1IJ/vp13UVjrntBowXS/Lt1i47mNC1g7 +cvnGtvlq9f3JvMMa3TW+1Ti/LsZBc8rf2X58tcaFtc+34y5K+zRaBJxTfWWR8QDAqqQGfe3b1PjR +9d1Grd63GjUk19jVi+bZOCnjO43E8UuTsq62i9d8ofp625rN10jK39loRjl//uZJ2TWSp282mop+ +vHEx4C5zlr9jo5nsr02W+3ijWfOO/OJkmfc2frA9v9XXdeN9jQsUO2tBcHHjs7jOFNb1icb4AvtP +oazV7p8bCfms61W3rV4+b7mrNPan286b/9pGTeOO/HWjxvRnJ6/d2qhRr/EZL+QCyD6T1//CnHlb +G0n7p6uPNpKWtzQuSM3at3pB49h+V+Pi07saXUhWi5MaTaYPb9vntLP4jm+cY97XOH98uNE3v0bi +flH1c3OWf92kvLnHxeeqP9xJ+W9qnHd+c04ss+VdZ7LerzbOFec2LmzNniue0fic5543n9K48HDd +yfO/3+h6NFv28TuJY6X9dvXmdtydYmvbLqhW3Xsy71cb3x0fa5yf961e2the72qc69/c9i1WTm4c +g3Pdq21dHGp8/lsbLYjObHw/fKtLHz/XmDz39cZ3zw8bx+Dc3yi3aFzU+UijO9B/tf3xAgDrggR9 +9Zpt5jz/cYV5yz2l8ePq7pPnjmw0a/zXBazr16vfqR42KeOoxg/uV+3mdac2ku9Zd278mHtXI8ne +OGf+Rxs/im/UqBn+l0aNyiGNH8wnd+kf9r/RqKHf2EgC5jui0Qfxnxu1/4dNyrjJDpZdSbdpJFc7 +G8hon+rYLt1q4dZdevvvqk/v/tU9Gy0S1mvt4FyvaIytcKPJ9COrUxo/8hfrSY0E5a2NJG5DC685 +353faRx7BzT6Tt++cSzP+tNGF4o7NI6VqzYuyO3sosJKeEj1+EZyO/s5fXsHyz280Yrk8Y1zzDUm +y57cOL5/1LiweNfJ8vs0zi1nzZl3zUZrmlN2EsvPNc5JL5wTy5sarXXe3KgVvlKjRcJdGzXNj5q8 +9umNiyWvmqz7DpN5j62+2EjG/7J6/5yyn7GrD2aFHNH4jBbaT/6xjX1wU/XqRveRhzfOJ5dvnFNv +1Dgm9sRjJnFdsbGPn9C2i7ibGsn2xY19/OBGa6xHtq1r0KbGd8anG+f52S5Cv7iH8QAALMjzGjXO +Z+/gsbntm/R+u/qDea+/WaPW4qqT6b9u++bls02qZ32wSyf0952UsauE8DGTeA5rWw3YDRoDbZ1f +/XTjh+yZjRr6GknHN9s2SFqNiwHnt+3H2GwN+r3nre8nJ/NnE7LfaSQGc2uLj5zE8cxdxL1Qb2n7 +pudzbW77Gr2PN344/lHjcz6lEfMfzVnmvOr/TeY9q1GTuLnRj7dG8rK1kbTM3/6PmVPOpxvNTv97 +sp4zG01Db7nwt7imPK/R575GLetzG0neVxoXmX6m8fndZrLMZa1Bf0Xbdyl4SWPbz7e7GvQjJ+u7 +/WR6ZzXo88cKOLmRhNS2pPXx85a5Y6PJ/EG7WP9ye1yX7lbzh23f5/4tjSR5rjs1PodjJ9NPbxw/ +NS5OfW8yb/ZC4aMn83Z1YfkdjVYHc927cXwdOW/+38yL6ScaFwRe1OhuMH+gxr+o/mcX614NbtD4 +TH9l3vxHN/bn2cfsd8NsDfqd5i3/5UZrpLl+rfE5HjKZXkgN+r3mLXdK9ZrJ/8dNlpnf6uvPG7Xq +Ncbp2Nq2Fhc1kvYvT+IAgHVDH/TV6xuNGqP55o5KfXijRujhbRtgrEbzxBrJ9ZmXYV3Xb9SazPXB +yd+fbOeDW53atn7o5zcSyNMbP6Q+0PjRd1EjQTp1Tkwfn8yf9b3JOn5yXvmfvAxxf6bta4u/02jG +Om0LaTZ/1cYPyvMb/dGf3mhVMNf1Gj8wz20kFY9qJNxzPbrd90H/RmPU9is09oWNLc37X61eVv1t +9fZG7dxrG+MRrAWfnTd9VtuO+Ws2ai5/tW0XbmokPhsaza4/3tpx/cYFkLk+1DhX/OTk/1Ma4zBc +qVHD/Y7GxafHN97zXRvnkS0tzA0bd0uYfxHyWm1/XH+z8Xm/vnHc/s4C17ManDf5O3/wxFlXawxA ++vy2/26Ye67dv5Esz6+F/2Dj/HK9xkXFhfjovOkPN2rna2yfzdU/zVvm6o2a8hr7yPxxDjZ36Tss +AMCaJ0Ff22Z/vLy5S/9Q+dsWdoup+S5LQjq3H/p5jSR06+S52X7oFzV+HF+WUa+3zpu+LPcxX47+ +5md36YsHNUas3tioxZ/rrW3fN3pHTmy0JlisuYPE/Xnjh+/fNEbS3xu8sVEj+HeN/tCXZZ+Zte/u +F1lSl8ybnrv/zx7br290WZjrb9r5gHJr2fsb55G7NJLx1zQu9B3YaI1zXDu+1eHuHDQpd0fNs+fv +L3dtbJerNJLcXQ1OuRp9vdGU/4bz5p84edy9Hd8hZE/PtfPn7clvioMa3xM72j6zF3K37mT9ALDu +SNDXtq81ahU2t/ua1l35fNuamc6abSa9uyT/1EZN+flt32f9XY0m6xe3rf/57Lp+pdHEffbH1+GN +Wpm/XWDcn2v0gT2gbT8wr9SOWx4sxucbP2oPagxeNOsWc+JYDX7UaDb/2karhnfvevF14aJGLfpj +2nnf7LMbta5XmjNvYyOJ2dWo/xe1cufI2VGsL2xxx/ZqsaNzzLGNpGv2+LmocSHvFxrdEx7XOH+8 +q/qtRsuUnfU/n7WjbfapRrPsj7TrkePv2xhg7l6N/vKvbLSEmb3DxEruD5fVlkZrqF9q9Jvfk5HX +L2h8txzb9q0ebjkpf7ZF1fxB9Wpb96P5jmmMBzDrFm278PTJxjn8s126FdGsz7XtLiNfnMzb1OjO +pRYdgHXFIHFr2yWNgYt+r1FjOlsjeM3JvMvqxEYz2ge2rQnjcxr9/3Z37+ZTG/elPrZt/QVr9NW8 +YuNH76lz5r+ykZD/eaMp5UGNPp8XVP+5gJhr9Nfdd1LW5Ro1bS9o+jUtr5qU/9LGD9J9Gvei/6vG +j8z3T3l9s45q/LCd+9hd8+3XNy6IzCxRTKvRHzZqO3e2HS5qJGe/2aiZPrB6dru+S0GNZO7GjSTg +qMb+vFzOb9SUP7VxDM0mhkc1Rulea06s7tFoWbKpcRz930Z//rnNpU9pXHQ7q5HUz857ZKN2+PTd +rOeLjeT+ho3P6sDGOAWnNc49N5gst29jTIL7Taav2Whi/axGs/qHNc5rT5tT9hmNljTHTso+dPdv +e0U8rZE8n9p4fwe17TO/585ftp0TG839Z7tO/XRj4Lj/aFwUrnG83bnxeW9oXBT8rZ2U98zG8bax +sS3v0raxVN7S6K7xz43jrcb2uVXbbpd4aiOBf0HjGN6nMQ7E7o5hAICpeF4770f8ubYfJG5jo6bk +3EYicl6j1mlubcXuBonb0EjIL5y8futk+Z+4DLFed7L8d7v0BZ//accDBD2g8QN8tvn7l9t+kKLZ +QeLmD+o0f5C4GsnL2Y0E/4LGe/1I0x0krsZgSl9q2y2WtjYuSFx33nIfb9To7sp5jcRrZ2YHidvR +471zlvt09Q87eP19JsvecTdxrFVzB4nbkfmDxNWo/ftmY3+7uHGx5fXtepC4KzaSu7Nb2G3WLusg +cQ+c97oXt/2gZfs0LiT8uHFsrtYa9csySFyNO06c17ZzzAe69K0Fbz55bm5/5NntOX9Ash05qtF3 +/Ydtf5u1azQSwS2NliaXTGJ+bCMZfN/kdZvmlHW/yXKzt4A8oPHZf7fVfZu1Gq1FXta2z3r28clG +4j17rp4dJG7+bRn3bXzPXDKnjDe0/UWJfRsDtG1tnMtPb/Tb39EgcY9rfO4/miz7J/PWd9VJ+Zvb +tn2+Vz1xzjI3b5yDL24cC29otBYwSBwAsCpdrpG43rBRa7QnDmrUGi1HrcQ+jXiPbvEtOQ5o1PAc +sdigLoNrN2pU5188YPXbp1GDupruI35Z7N+oWbxBa/++z5dvHKvT7oZyWR3eOH6v3vbJ+Hq1X2O/ ++enGe1+oQxqf166Omas0vnd2dB6fTdAPaAxk+dNtGwV+Rw6brO+a7bg7wabG98b8pvUAAADALsxN +0AGAy0AfdAAAAAAAWKf2bfRbd4s0AAAAAAAAAAAAAAAAAABgZ54zeezKHasPd9kHMr3RZPmrLCIu +AIAVZxR3YK15cfWKJSr78dWnl6hshqOq6+xmmYUOLnb56pjqcouICwBgxe2z0gEALNDlJ4+lsH91 +xSUqm8vulOq6Kx0EAMByU4MOrCWPq+5QHVu9ZvK425znH12dWp1evaH6uTnPPax6eXXQnHk/NSnj +2Ek5j6wOn1P2Y5fgPawnN6te3fY1139bvWDO9H6TZW4277X3q95Tfap6Ydtvl1s0Pv+531FHVH9V +fbz6bGP73nlemUdW/1SdVr1tB88DAAAwJcdU76o+WD1o8jhq8tyfVt+vfr+6Z/XM6qK2JekHNRL3 +V06mD2wkh69tNKU+qjqx+u6cso9Z0nez9h1Rba7uNJm+SnXJ5HHlybw7TZY5fDJ9UvWVRnL+kOpX +qm9XL51T7n2qrdWmyfQh1ecmj0dX96p+r20XUG45Wf5/q6dU920k+OdVV53GGwUAAODS/qU6ed68 +q1UXVw+cN/9F1TvnTP9MdX71mOrvqy83+jrPelL1tSnGujf4WPWMyf8Prz4yeTxsMu8Z1UfnLH9S +dVbb15j/dvW9OdPzE/SnVT9s54PAzSbovzln3v7VOY0LAAAAa4I+6MB6cPPG+exqbd8sff/GCN+z +Pl79biNxr1G7+/3lCHAdO6W6a3X85O8pk/l3rV41b96sDzYS7lmnV4dVBzQuoMx3p0kZ39pNLG+f +8/8FjZr6q+/2HQAArBISdGA9uFq1pbrdDp57+7zpTzTOfV+pPrnEce0NTmnUgB/cSMYfN5n/4kYt ++S0b3Q3m+tG86Usmf3f2nXRAY3vtzo7K3bSjBQEAViMJOrDWbO3St9/6ZmNAsT9sNFvfmcMatbqv +bCTzL2z0aZ61ZQdls2vvbmyTX2k0QX934zP8icm8LZN5i/GF6icXWQYAwKpnFHdgrTmrUWM+1ymT ++c9q+wuPG9p2z+0NjRG+z2k0g39oo8/0/5lX9mxTay6bH1UfqP64en9jYLYfT/5/yuS5Hy9yHW+s +bl/9/Lz5S3W7PQCAFSFBB9aakxq3Rzu9+nB1/0YC+ODGiO2fqV42We70xq25qp7YuJXaQxr9nD/Y +SCpfVB09WeYtjT7pn5uU/dSlfjPrxCnVldq+r/nbdjBvT72m+rvqddX/a1xoeX9j8DgAgHVDU05g +LTqycV/tKzZGDD9jMv/QRsJ+3eoHjWT9lOrCxsjg36w+NKecDY1bcn1tUk6NWtlbNJLLM+bMZ+eu +Xt2mel/1jcm8q1W3rf6n+vqcZW89+fv+OfOuXN2xMTr/JY3m8ber/r3RfH7ua49r3Hf9C9V/Nbbz +YY3+729s1ODPuntjm//vYt4cAAAAwELduLrpEpV9zeoOS1Q2AAAArCv/0miJsBSe1GhtAgAsEX3Q +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 +95GVDgbWE/dEBVYN90GHpeM+6GvIM7t+m/vTRvN3243VZGv1b23qKT2tL650MLAeOekDq4YEHZaO +BH0NmunG1fHVg1Y6FKje1saerMYclpYva2DVkKDD0pGgr2Ez3bF6SvWz2Y4sry3VW6s/bab3rHQw +sDdwkgdWDQk6LB0J+jow0/Wqx0weh69wNKxv51QnVc9vps+sdDCwN/FlDawaEnRYOhL0dWSmA6uH +Vg+p7lLtu7IBsU5cVL2jek316mY6b4Xjgb2SL2tg1ZCgw9KRoK9Tf9HlO6/j2tqDqvtWB690SKwp +51enVP9Wvb6ZfrDC8cBez5c1sGpI0GHpSND3AjPt08aObku3q25fHVPdMNuebc6sPtKG3tPW3tth +fagnduFKBwVs44QNrBoSdFg6EvS91ExHtLHrt6XrVEfV///3oEZt+wHV5Sf/b1qxOFmMzdW51Y+q +Cyb/n1t9qQ2d0da+VJ1RfaGZvrtyYQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AP9fe3BIAAAAACDo/2tnWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Bf2JDlg/m2H/wAAAABJ +RU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/2911a62f9cfb6cf1e950992909bf7efb.msg b/share/extensions/tests/data/cmd/inkscape/2911a62f9cfb6cf1e950992909bf7efb.msg new file mode 100644 index 0000000..c63e43e --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/2911a62f9cfb6cf1e950992909bf7efb.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:0:1000:49 --export-filename=f2oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f2oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f2oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/2aee6b61724952541d5114e64953ae32.msg b/share/extensions/tests/data/cmd/inkscape/2aee6b61724952541d5114e64953ae32.msg new file mode 100644 index 0000000..f5f42a9 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/2aee6b61724952541d5114e64953ae32.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:49:47:951 --export-filename=guides_3.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_3.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_3.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAOGCAYAAAB83MkXAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAALxJREFUeJztwQENAAAAwqD3T20P +BxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCDAZoM +AAG1xnPlAAAAAElFTkSuQmCC + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/37d9cfceb38aade8eda7ad77e4ad0c29.msg b/share/extensions/tests/data/cmd/inkscape/37d9cfceb38aade8eda7ad77e4ad0c29.msg new file mode 100644 index 0000000..e7f73cd --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/37d9cfceb38aade8eda7ad77e4ad0c29.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:0:1000:49 --export-filename=guides_2.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_2.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_2.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/4b7027944d0833efa65b5f203a16a5d0.msg b/share/extensions/tests/data/cmd/inkscape/4b7027944d0833efa65b5f203a16a5d0.msg new file mode 100644 index 0000000..6df3b41 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/4b7027944d0833efa65b5f203a16a5d0.msg @@ -0,0 +1,375 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=select-all;page-fit-to-selection;clone-unlink-recursively;vacuum-defs --export-filename=output.svg --export-type=svg --pdf-page=1 --pdf-poppler input.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgd2lkdGg9Ijc0Ljc2OTUzMXB0IgogICBoZWlnaHQ9IjI3LjU3NjYyMnB0IgogICB2aWV3 +Qm94PSIwIDAgNzQuNzY5NTMxIDI3LjU3NjYyMiIKICAgdmVyc2lvbj0iMS4yIgogICBpZD0ic3Zn +MTQxIgogICBzb2RpcG9kaTpkb2NuYW1lPSJpbnB1dC5wZGYiCiAgIHhtbG5zOmlua3NjYXBlPSJo +dHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICB4bWxuczpzb2Rp +cG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQi +CiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c3ZnPSJodHRw +Oi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJu +YW1lZHZpZXcxNDMiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIj +MDAwMDAwIgogICAgIGJvcmRlcm9wYWNpdHk9IjAuMjUiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRv +dz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2Vj +aGVja2VyYm9hcmQ9IjAiCiAgICAgaW5rc2NhcGU6ZGVza2NvbG9yPSIjZDFkMWQxIgogICAgIGlu +a3NjYXBlOmRvY3VtZW50LXVuaXRzPSJwdCIgLz4KICA8ZGVmcwogICAgIGlkPSJkZWZzNzAiIC8+ +CiAgPGcKICAgICBpZD0ic3VyZmFjZTEiCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTkzLjEy +MTA5NCwtNzIuOTIwODc2KSI+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxs +LW9wYWNpdHk6MSIKICAgICAgIGlkPSJnNzQiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlNzIi +CiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkzLjEyMTAwMiw4MS43MTI5OTcpIj4KICAg +ICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJt +IDIuNjQwNjI1LC0zLjcxODc1IGggMS4xMjUgQyAzLjQzNzUsLTIuMjUgMy4zNDM3NSwtMS44MTI1 +IDMuMzQzNzUsLTEuMTQwNjI1IGMgMCwwLjE0MDYyNSAwLDAuNDA2MjUgMC4wNzgxMjUsMC43NSAw +LjEwOTM3NSwwLjQzNzUgMC4yMTg3NSwwLjUgMC4zNTkzNzUsMC41IDAuMjAzMTI1LDAgMC40MjE4 +NzUsLTAuMTcxODc1IDAuNDIxODc1LC0wLjM3NSAwLC0wLjA2MjUgMCwtMC4wNzgxMjUgLTAuMDYy +NSwtMC4yMTg3NSAtMC4yOTY4NzUsLTAuNzE4NzUgLTAuMjk2ODc1LC0xLjM3NSAtMC4yOTY4NzUs +LTEuNjU2MjUgMCwtMC41MTU2MjUgMC4wNzgxMjUsLTEuMDYyNSAwLjE4NzUsLTEuNTc4MTI1IGgg +MS4xMjUgYyAwLjE0MDYyNSwwIDAuNSwwIDAuNSwtMC4zNDM3NSAwLC0wLjIzNDM3NSAtMC4yMTg3 +NSwtMC4yMzQzNzUgLTAuNDA2MjUsLTAuMjM0Mzc1IEggMS45MDYyNSBjIC0wLjIxODc1LDAgLTAu +NTkzNzUsMCAtMS4wMzEyNSwwLjQ2ODc1IC0wLjM0Mzc1LDAuMzkwNjI1IC0wLjYwOTM3NSwwLjg0 +Mzc1IC0wLjYwOTM3NSwwLjg5MDYyNSAwLDAuMDE1NjI1IDAsMC4xMDkzNzUgMC4xMjUsMC4xMDkz +NzUgMC4wNzgxMjUsMCAwLjA5Mzc1LC0wLjA0Njg3NSAwLjE1NjI1LC0wLjEyNSBDIDEuMDMxMjUs +LTMuNzE4NzUgMS42MDkzNzUsLTMuNzE4NzUgMS44MTI1LC0zLjcxODc1IEggMi4zNzUgQyAyLjA2 +MjUsLTIuNTE1NjI1IDEuNTMxMjUsLTEuMzEyNSAxLjEwOTM3NSwtMC40MDYyNSAxLjAzMTI1LC0w +LjI1IDEuMDMxMjUsLTAuMjM0Mzc1IDEuMDMxMjUsLTAuMTU2MjUgYyAwLDAuMTg3NSAwLjE1NjI1 +LDAuMjY1NjI1IDAuMjgxMjUsMC4yNjU2MjUgMC4yOTY4NzUsMCAwLjM3NSwtMC4yODEyNSAwLjUs +LTAuNjQwNjI1IEMgMS45NTMxMjUsLTEgMS45NTMxMjUsLTEuMDE1NjI1IDIuMDc4MTI1LC0xLjUx +NTYyNSBaIG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTQ1IiAvPgogICAgICA8L2c+CiAgICA8 +L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAg +ICAgIGlkPSJnNzgiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlNzYiCiAgICAgICAgIHRyYW5z +Zm9ybT0idHJhbnNsYXRlKDk5LjE1Njk5OCw3OC4wOTcpIj4KICAgICAgICA8cGF0aAogICAgICAg +ICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJNIDMuNTE1NjI1LC0xLjI2NTYy +NSBIIDMuMjgxMjUgYyAtMC4wMTU2MjUsMC4xNTYyNSAtMC4wOTM3NSwwLjU2MjUgLTAuMTg3NSww +LjYyNSBDIDMuMDQ2ODc1LC0wLjU5Mzc1IDIuNTE1NjI1LC0wLjU5Mzc1IDIuNDA2MjUsLTAuNTkz +NzUgSCAxLjEyNSBjIDAuNzM0Mzc1LC0wLjY0MDYyNSAwLjk4NDM3NSwtMC44NDM3NSAxLjM5MDYy +NSwtMS4xNzE4NzUgMC41MTU2MjUsLTAuNDA2MjUgMSwtMC44NDM3NSAxLC0xLjUgMCwtMC44NDM3 +NSAtMC43MzQzNzUsLTEuMzU5Mzc1IC0xLjYyNSwtMS4zNTkzNzUgLTAuODU5Mzc1LDAgLTEuNDUz +MTI1LDAuNjA5Mzc1IC0xLjQ1MzEyNSwxLjI1IDAsMC4zNDM3NSAwLjI5Njg3NSwwLjM5MDYyNSAw +LjM3NSwwLjM5MDYyNSAwLjE1NjI1LDAgMC4zNTkzNzUsLTAuMTI1IDAuMzU5Mzc1LC0wLjM3NSAw +LC0wLjEyNSAtMC4wNDY4NzUsLTAuMzc1IC0wLjQwNjI1LC0wLjM3NSBDIDAuOTg0Mzc1LC00LjIx +ODc1IDEuNDUzMTI1LC00LjM3NSAxLjc4MTI1LC00LjM3NSBjIDAuNzAzMTI1LDAgMS4wNjI1LDAu +NTQ2ODc1IDEuMDYyNSwxLjEwOTM3NSAwLDAuNjA5Mzc1IC0wLjQzNzUsMS4wNzgxMjUgLTAuNjU2 +MjUsMS4zMjgxMjUgTCAwLjUxNTYyNSwtMC4yNjU2MjUgQyAwLjQzNzUsLTAuMjAzMTI1IDAuNDM3 +NSwtMC4xODc1IDAuNDM3NSwwIGggMi44NzUgeiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDE0 +OSIgLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5v +bmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjAuMzk4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7 +c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS1vcGFjaXR5 +OjEiCiAgICAgICBkPSJNIDkuMzc1ZS01LDAuMDAxMDYyNSBIIDEwLjUwNzkwNiIKICAgICAgIHRy +YW5zZm9ybT0ibWF0cml4KDEsMCwwLC0xLDkzLjEyMSw4NS45NjIpIgogICAgICAgaWQ9InBhdGg4 +MCIgLz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgog +ICAgICAgaWQ9Imc4NCI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U4MiIKICAgICAgICAgdHJh +bnNmb3JtPSJ0cmFuc2xhdGUoOTUuODgzMDAzLDk1LjI4NjAwMykiPgogICAgICAgIDxwYXRoCiAg +ICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gMS4zMTI1LC0zLjI2 +NTYyNSB2IC0wLjI1IGMgMCwtMi41MTU2MjUgMS4yMzQzNzUsLTIuODc1IDEuNzUsLTIuODc1IDAu +MjM0Mzc1LDAgMC42NTYyNSwwLjA2MjUgMC44NzUsMC40MDYyNSAtMC4xNTYyNSwwIC0wLjU0Njg3 +NSwwIC0wLjU0Njg3NSwwLjQzNzUgMCwwLjMxMjUgMC4yMzQzNzUsMC40Njg3NSAwLjQ1MzEyNSww +LjQ2ODc1IDAuMTU2MjUsMCAwLjQ2ODc1LC0wLjA5Mzc1IDAuNDY4NzUsLTAuNDg0Mzc1IDAsLTAu +NTkzNzUgLTAuNDM3NSwtMS4wNzgxMjUgLTEuMjY1NjI1LC0xLjA3ODEyNSAtMS4yODEyNSwwIC0y +LjYyNSwxLjI4MTI1IC0yLjYyNSwzLjQ4NDM3NSAwLDIuNjcxODc1IDEuMTU2MjUsMy4zNzUgMi4w +NzgxMjUsMy4zNzUgMS4xMDkzNzUsMCAyLjA2MjUsLTAuOTM3NSAyLjA2MjUsLTIuMjUgMCwtMS4y +NjU2MjUgLTAuODkwNjI1LC0yLjIxODc1IC0yLC0yLjIxODc1IC0wLjY3MTg3NSwwIC0xLjA0Njg3 +NSwwLjUgLTEuMjUsMC45ODQzNzUgeiBNIDIuNSwtMC4wNjI1IGMgLTAuNjI1LDAgLTAuOTIxODc1 +LC0wLjU5Mzc1IC0wLjk4NDM3NSwtMC43NSAtMC4xODc1LC0wLjQ2ODc1IC0wLjE4NzUsLTEuMjY1 +NjI1IC0wLjE4NzUsLTEuNDM3NSAwLC0wLjc4MTI1IDAuMzI4MTI1LC0xLjc4MTI1IDEuMjE4NzUs +LTEuNzgxMjUgMC4xNzE4NzUsMCAwLjYyNSwwIDAuOTM3NSwwLjYyNSAwLjE3MTg3NSwwLjM1OTM3 +NSAwLjE3MTg3NSwwLjg3NSAwLjE3MTg3NSwxLjM1OTM3NSAwLDAuNDg0Mzc1IDAsMC45ODQzNzUg +LTAuMTcxODc1LDEuMzQzNzUgQyAzLjE4NzUsLTAuMTA5Mzc1IDIuNzM0Mzc1LC0wLjA2MjUgMi41 +LC0wLjA2MjUgWiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDE1MyIgLz4KICAgICAgPC9nPgog +ICAgPC9nPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEi +CiAgICAgICBpZD0iZzg4Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTg2IgogICAgICAgICB0 +cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDcuNTg5LDg4LjQ1MjAwMykiPgogICAgICAgIDxwYXRoCiAg +ICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gNi44NDM3NSwtMy4y +NjU2MjUgYyAwLjE1NjI1LDAgMC4zNDM3NSwwIDAuMzQzNzUsLTAuMTg3NSBDIDcuMTg3NSwtMy42 +NTYyNSA3LC0zLjY1NjI1IDYuODU5Mzc1LC0zLjY1NjI1IGggLTUuOTY4NzUgYyAtMC4xNDA2MjUs +MCAtMC4zMjgxMjUsMCAtMC4zMjgxMjUsMC4yMDMxMjUgMCwwLjE4NzUgMC4xODc1LDAuMTg3NSAw +LjMyODEyNSwwLjE4NzUgeiBtIDAuMDE1NjI1LDEuOTM3NSBjIDAuMTQwNjI1LDAgMC4zMjgxMjUs +MCAwLjMyODEyNSwtMC4yMDMxMjUgMCwtMC4xODc1IC0wLjE4NzUsLTAuMTg3NSAtMC4zNDM3NSwt +MC4xODc1IEggMC44OTA2MjUgYyAtMC4xNDA2MjUsMCAtMC4zMjgxMjUsMCAtMC4zMjgxMjUsMC4x +ODc1IDAsMC4yMDMxMjUgMC4xODc1LDAuMjAzMTI1IDAuMzI4MTI1LDAuMjAzMTI1IHogbSAwLDAi +CiAgICAgICAgICAgaWQ9InBhdGgxNTciIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAg +ICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9Imc5NiI+ +CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U5MCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xh +dGUoMTIxLjU5NDQyLDg4LjQ1MjAwMykiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9 +InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Ik0gMS43NjU2MjUsLTYuOTIxODc1IDAuMzI4MTI1 +LC02LjgxMjUgViAtNi41IGMgMC43MDMxMjUsMCAwLjc4MTI1LDAuMDYyNSAwLjc4MTI1LDAuNTYy +NSBWIC0wLjc1IGMgMCwwLjQzNzUgLTAuMTA5Mzc1LDAuNDM3NSAtMC43ODEyNSwwLjQzNzUgViAw +IEMgMC42NTYyNSwtMC4wMTU2MjUgMS4xODc1LC0wLjAzMTI1IDEuNDM3NSwtMC4wMzEyNSBjIDAu +MjUsMCAwLjczNDM3NSwwLjAxNTYyNSAxLjEwOTM3NSwwLjAzMTI1IHYgLTAuMzEyNSBjIC0wLjY3 +MTg3NSwwIC0wLjc4MTI1LDAgLTAuNzgxMjUsLTAuNDM3NSB6IG0gMCwwIgogICAgICAgICAgIGlk +PSJwYXRoMTYxIiAvPgogICAgICA8L2c+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U5MiIKICAg +ICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI0LjM2MjAzLDg4LjQ1MjAwMykiPgogICAgICAg +IDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Ik0gMS43 +NjU2MjUsLTQuNDA2MjUgMC4zNzUsLTQuMjk2ODc1IHYgMC4zMTI1IGMgMC42NDA2MjUsMCAwLjcz +NDM3NSwwLjA2MjUgMC43MzQzNzUsMC41NDY4NzUgViAtMC43NSBjIDAsMC40Mzc1IC0wLjEwOTM3 +NSwwLjQzNzUgLTAuNzgxMjUsMC40Mzc1IFYgMCBDIDAuNjQwNjI1LC0wLjAxNTYyNSAxLjE4NzUs +LTAuMDMxMjUgMS40MjE4NzUsLTAuMDMxMjUgMS43ODEyNSwtMC4wMzEyNSAyLjEyNSwtMC4wMTU2 +MjUgMi40Njg3NSwwIHYgLTAuMzEyNSBjIC0wLjY3MTg3NSwwIC0wLjcwMzEyNSwtMC4wNDY4NzUg +LTAuNzAzMTI1LC0wLjQzNzUgeiBtIDAuMDMxMjUsLTEuNzM0Mzc1IGMgMCwtMC4zMTI1IC0wLjIz +NDM3NSwtMC41MzEyNSAtMC41MTU2MjUsLTAuNTMxMjUgLTAuMzEyNSwwIC0wLjUzMTI1LDAuMjY1 +NjI1IC0wLjUzMTI1LDAuNTMxMjUgMCwwLjI2NTYyNSAwLjIxODc1LDAuNTMxMjUgMC41MzEyNSww +LjUzMTI1IDAuMjgxMjUsMCAwLjUxNTYyNSwtMC4yMTg3NSAwLjUxNTYyNSwtMC41MzEyNSB6IG0g +MCwwIgogICAgICAgICAgIGlkPSJwYXRoMTY1IiAvPgogICAgICA8L2c+CiAgICAgIDxnCiAgICAg +ICAgIGlkPSJ1c2U5NCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI3LjEyOTY1LDg4 +LjQ1MjAwMykiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgog +ICAgICAgICAgIGQ9Ik0gMS4wOTM3NSwtMy40MjE4NzUgViAtMC43NSBjIDAsMC40Mzc1IC0wLjEw +OTM3NSwwLjQzNzUgLTAuNzgxMjUsMC40Mzc1IFYgMCBjIDAuMzU5Mzc1LC0wLjAxNTYyNSAwLjg1 +OTM3NSwtMC4wMzEyNSAxLjE0MDYyNSwtMC4wMzEyNSAwLjI1LDAgMC43NjU2MjUsMC4wMTU2MjUg +MS4xMDkzNzUsMC4wMzEyNSB2IC0wLjMxMjUgYyAtMC42NzE4NzUsMCAtMC43ODEyNSwwIC0wLjc4 +MTI1LC0wLjQzNzUgViAtMi41OTM3NSBDIDEuNzgxMjUsLTMuNjI1IDIuNSwtNC4xODc1IDMuMTI1 +LC00LjE4NzUgYyAwLjY0MDYyNSwwIDAuNzUsMC41MzEyNSAwLjc1LDEuMTA5Mzc1IFYgLTAuNzUg +YyAwLDAuNDM3NSAtMC4xMDkzNzUsMC40Mzc1IC0wLjc4MTI1LDAuNDM3NSBWIDAgYyAwLjM0Mzc1 +LC0wLjAxNTYyNSAwLjg1OTM3NSwtMC4wMzEyNSAxLjEyNSwtMC4wMzEyNSAwLjI1LDAgMC43ODEy +NSwwLjAxNTYyNSAxLjEwOTM3NSwwLjAzMTI1IHYgLTAuMzEyNSBjIC0wLjY1NjI1LDAgLTAuNzY1 +NjI1LDAgLTAuNzY1NjI1LC0wLjQzNzUgdiAtMS44NDM3NSBjIDAsLTEuMDMxMjUgMC43MDMxMjUs +LTEuNTkzNzUgMS4zNDM3NSwtMS41OTM3NSAwLjYyNSwwIDAuNzM0Mzc1LDAuNTMxMjUgMC43MzQz +NzUsMS4xMDkzNzUgViAtMC43NSBjIDAsMC40Mzc1IC0wLjEwOTM3NSwwLjQzNzUgLTAuNzgxMjUs +MC40Mzc1IFYgMCBjIDAuMzQzNzUsLTAuMDE1NjI1IDAuODU5Mzc1LC0wLjAzMTI1IDEuMTI1LC0w +LjAzMTI1IDAuMjY1NjI1LDAgMC43ODEyNSwwLjAxNTYyNSAxLjEyNSwwLjAzMTI1IHYgLTAuMzEy +NSBjIC0wLjUxNTYyNSwwIC0wLjc2NTYyNSwwIC0wLjc4MTI1LC0wLjI5Njg3NSB2IC0xLjkwNjI1 +IGMgMCwtMC44NTkzNzUgMCwtMS4xNTYyNSAtMC4zMTI1LC0xLjUxNTYyNSAtMC4xNDA2MjUsLTAu +MTcxODc1IC0wLjQ2ODc1LC0wLjM3NSAtMS4wNDY4NzUsLTAuMzc1IC0wLjgyODEyNSwwIC0xLjI4 +MTI1LDAuNTkzNzUgLTEuNDM3NSwwLjk4NDM3NSBDIDQuMzkwNjI1LC00LjI5Njg3NSAzLjY1NjI1 +LC00LjQwNjI1IDMuMjAzMTI1LC00LjQwNjI1IDIuNDY4NzUsLTQuNDA2MjUgMiwtMy45ODQzNzUg +MS43MTg3NSwtMy4zNTkzNzUgViAtNC40MDYyNSBMIDAuMzEyNSwtNC4yOTY4NzUgdiAwLjMxMjUg +YyAwLjcwMzEyNSwwIDAuNzgxMjUsMC4wNjI1IDAuNzgxMjUsMC41NjI1IHogbSAwLDAiCiAgICAg +ICAgICAgaWQ9InBhdGgxNjkiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBz +dHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMDAiPgogICAg +ICA8ZwogICAgICAgICBpZD0idXNlOTgiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEx +OC4xMDUsOTQuNDMpIj4KICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9u +ZSIKICAgICAgICAgICBkPSJtIDAuODQzNzUsLTAuNDM3NSBjIC0wLjAxNTYyNSwwLjA5Mzc1IC0w +LjA2MjUsMC4yNjU2MjUgLTAuMDYyNSwwLjI4MTI1IDAsMC4xNTYyNSAwLjEyNSwwLjIxODc1IDAu +MjM0Mzc1LDAuMjE4NzUgMC4xMjUsMCAwLjIzNDM3NSwtMC4wNzgxMjUgMC4yODEyNSwtMC4xNDA2 +MjUgMC4wMzEyNSwtMC4wNjI1IDAuMDc4MTI1LC0wLjI5Njg3NSAwLjEyNSwtMC40Mzc1IDAuMDMx +MjUsLTAuMTI1IDAuMTA5Mzc1LC0wLjQ1MzEyNSAwLjE0MDYyNSwtMC42MjUgMC4wNDY4NzUsLTAu +MTU2MjUgMC4wOTM3NSwtMC4zMTI1IDAuMTI1LC0wLjQ2ODc1IDAuMDc4MTI1LC0wLjI4MTI1IDAu +MDkzNzUsLTAuMzQzNzUgMC4yOTY4NzUsLTAuNjI1IEMgMi4xNzE4NzUsLTIuNTE1NjI1IDIuNSwt +Mi44NzUgMy4wMzEyNSwtMi44NzUgYyAwLjM5MDYyNSwwIDAuNDA2MjUsMC4zNTkzNzUgMC40MDYy +NSwwLjQ4NDM3NSAwLDAuNDIxODc1IC0wLjI5Njg3NSwxLjE4NzUgLTAuNDA2MjUsMS40ODQzNzUg +LTAuMDc4MTI1LDAuMjAzMTI1IC0wLjEwOTM3NSwwLjI2NTYyNSAtMC4xMDkzNzUsMC4zNzUgMCww +LjM3NSAwLjI5Njg3NSwwLjU5Mzc1IDAuNjU2MjUsMC41OTM3NSAwLjcwMzEyNSwwIDEsLTAuOTUz +MTI1IDEsLTEuMDYyNSAwLC0wLjA5Mzc1IC0wLjA3ODEyNSwtMC4wOTM3NSAtMC4xMDkzNzUsLTAu +MDkzNzUgLTAuMDkzNzUsMCAtMC4wOTM3NSwwLjA0Njg3NSAtMC4xMjUsMC4xMjUgQyA0LjE4NzUs +LTAuNDA2MjUgMy44NzUsLTAuMTI1IDMuNjA5Mzc1LC0wLjEyNSBjIC0wLjE1NjI1LDAgLTAuMTg3 +NSwtMC4wOTM3NSAtMC4xODc1LC0wLjI1IDAsLTAuMTU2MjUgMC4wNDY4NzUsLTAuMjUgMC4xNzE4 +NzUsLTAuNTYyNSAwLjA3ODEyNSwtMC4yMTg3NSAwLjM1OTM3NSwtMC45NTMxMjUgMC4zNTkzNzUs +LTEuMzQzNzUgMCwtMC42NzE4NzUgLTAuNTMxMjUsLTAuNzk2ODc1IC0wLjkwNjI1LC0wLjc5Njg3 +NSAtMC41NzgxMjUsMCAtMC45Njg3NSwwLjM1OTM3NSAtMS4xNzE4NzUsMC42NDA2MjUgLTAuMDQ2 +ODc1LC0wLjQ4NDM3NSAtMC40NTMxMjUsLTAuNjQwNjI1IC0wLjc1LC0wLjY0MDYyNSAtMC4yOTY4 +NzUsMCAtMC40NTMxMjUsMC4yMTg3NSAtMC41NDY4NzUsMC4zNzUgLTAuMTU2MjUsMC4yNjU2MjUg +LTAuMjUsMC42NTYyNSAtMC4yNSwwLjcwMzEyNSAwLDAuMDc4MTI1IDAuMDkzNzUsMC4wNzgxMjUg +MC4xMjUsMC4wNzgxMjUgMC4wOTM3NSwwIDAuMDkzNzUsLTAuMDE1NjI1IDAuMTQwNjI1LC0wLjIw +MzEyNSAwLjEwOTM3NSwtMC40MDYyNSAwLjI1LC0wLjc1IDAuNTE1NjI1LC0wLjc1IDAuMTg3NSww +IDAuMjM0Mzc1LDAuMTU2MjUgMC4yMzQzNzUsMC4zNDM3NSAwLDAuMTI1IC0wLjA2MjUsMC4zOTA2 +MjUgLTAuMTI1LDAuNTc4MTI1IC0wLjA0Njg3NSwwLjE4NzUgLTAuMTA5Mzc1LDAuNDY4NzUgLTAu +MTQwNjI1LDAuNjI1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGgxNzMiIC8+CiAgICAgIDwv +Zz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0 +eToxIgogICAgICAgaWQ9ImcxMDYiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlMTAyIgogICAg +ICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjMuMDMsOTQuNDMpIj4KICAgICAgICA8cGF0aAog +ICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDYuNDA2MjUsLTEu +NTc4MTI1IGMgLTAuODc1LDAuNjQwNjI1IC0wLjk4NDM3NSwxLjU2MjUgLTAuOTg0Mzc1LDEuNTYy +NSAwLDAuMTA5Mzc1IDAuMDYyNSwwLjEwOTM3NSAwLjE1NjI1LDAuMTA5Mzc1IDAuMTI1LDAgMC4x +NTYyNSwwIDAuMTg3NSwtMC4xMjUgMC4wNDY4NzUsLTAuMTcxODc1IDAuMTU2MjUsLTAuNjA5Mzc1 +IDAuNTE1NjI1LC0xIDAuNDA2MjUsLTAuNDIxODc1IDAuNzUsLTAuNTMxMjUgMS4wNDY4NzUsLTAu +NjI1IDAuMDMxMjUsLTAuMDE1NjI1IDAuMDYyNSwtMC4wNDY4NzUgMC4wNjI1LC0wLjA3ODEyNSAw +LC0wLjA3ODEyNSAtMC4wMzEyNSwtMC4wOTM3NSAtMC4xMjUsLTAuMTI1IEMgNi4yNjU2MjUsLTIu +MTcxODc1IDUuOTA2MjUsLTIuODkwNjI1IDUuNzUsLTMuNSA1LjczNDM3NSwtMy41NzgxMjUgNS42 +NzE4NzUsLTMuNTc4MTI1IDUuNTc4MTI1LC0zLjU3ODEyNSBjIC0wLjA5Mzc1LDAgLTAuMTU2MjUs +MCAtMC4xNTYyNSwwLjA5Mzc1IDAsMC4wMTU2MjUgMC4wNjI1LDAuNDg0Mzc1IDAuNDA2MjUsMC45 +Njg3NSAwLjE1NjI1LDAuMjM0Mzc1IDAuMzU5Mzc1LDAuNDM3NSAwLjU3ODEyNSwwLjU5Mzc1IEgg +MC44MTI1IGMgLTAuMTA5Mzc1LDAgLTAuMjgxMjUsMCAtMC4yODEyNSwwLjE3MTg3NSAwLDAuMTcx +ODc1IDAuMTcxODc1LDAuMTcxODc1IDAuMjgxMjUsMC4xNzE4NzUgeiBtIDAsMCIKICAgICAgICAg +ICBpZD0icGF0aDE3NyIgLz4KICAgICAgPC9nPgogICAgICA8ZwogICAgICAgICBpZD0idXNlMTA0 +IgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMzAuOTcyNDYsOTQuNDMpIj4KICAgICAg +ICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDQu +MDMxMjUsLTEuOTA2MjUgYyAtMC4zNzUsLTAuNDM3NSAtMC40ODQzNzUsLTAuNTQ2ODc1IC0wLjc1 +LC0wLjczNDM3NSAtMC40MjE4NzUsLTAuMzEyNSAtMC44NzUsLTAuNDM3NSAtMS4yNSwtMC40Mzc1 +IC0wLjg3NSwwIC0xLjUsMC43NSAtMS41LDEuNTc4MTI1IDAsMC44MTI1IDAuNjA5Mzc1LDEuNTYy +NSAxLjQ2ODc1LDEuNTYyNSAwLjk2ODc1LDAgMS42NTYyNSwtMC43ODEyNSAxLjkwNjI1LC0xLjE1 +NjI1IDAuMzU5Mzc1LDAuNDM3NSAwLjQ4NDM3NSwwLjU0Njg3NSAwLjczNDM3NSwwLjczNDM3NSAw +LjQzNzUsMC4zMTI1IDAuODc1LDAuNDIxODc1IDEuMjY1NjI1LDAuNDIxODc1IDAuODU5Mzc1LDAg +MS40ODQzNzUsLTAuNzM0Mzc1IDEuNDg0Mzc1LC0xLjU2MjUgMCwtMC44MjgxMjUgLTAuNTkzNzUs +LTEuNTc4MTI1IC0xLjQ2ODc1LC0xLjU3ODEyNSAtMC45Njg3NSwwIC0xLjY0MDYyNSwwLjc5Njg3 +NSAtMS44OTA2MjUsMS4xNzE4NzUgeiBtIDAuMjE4NzUsMC4yNSBjIDAuMjgxMjUsLTAuNDUzMTI1 +IDAuODkwNjI1LC0xLjE1NjI1IDEuNzM0Mzc1LC0xLjE1NjI1IDAuNzE4NzUsMCAxLjIxODc1LDAu +NjQwNjI1IDEuMjE4NzUsMS4zMTI1IDAsMC42NTYyNSAtMC41NDY4NzUsMS4xODc1IC0xLjE4NzUs +MS4xODc1IC0wLjY1NjI1LDAgLTEuMDkzNzUsLTAuNTMxMjUgLTEuNzY1NjI1LC0xLjM0Mzc1IHog +TSAzLjY3MTg3NSwtMS4zNTkzNzUgQyAzLjQwNjI1LC0wLjkwNjI1IDIuNzk2ODc1LC0wLjE4NzUg +MS45Mzc1LC0wLjE4NzUgYyAtMC43MTg3NSwwIC0xLjIwMzEyNSwtMC42NDA2MjUgLTEuMjAzMTI1 +LC0xLjMxMjUgMCwtMC42NzE4NzUgMC41NDY4NzUsLTEuMTg3NSAxLjE4NzUsLTEuMTg3NSAwLjY0 +MDYyNSwwIDEuMDkzNzUsMC41MzEyNSAxLjc1LDEuMzI4MTI1IHogbSAwLDAiCiAgICAgICAgICAg +aWQ9InBhdGgxODEiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBzdHlsZT0i +ZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMTAiPgogICAgICA8Zwog +ICAgICAgICBpZD0idXNlMTA4IgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDUuMzU4 +OTksNzUuOTk5MDAxKSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5v +bmUiCiAgICAgICAgICAgZD0ibSAwLjg0Mzc1LC0wLjQzNzUgYyAtMC4wMTU2MjUsMC4wOTM3NSAt +MC4wNjI1LDAuMjY1NjI1IC0wLjA2MjUsMC4yODEyNSAwLDAuMTU2MjUgMC4xMjUsMC4yMTg3NSAw +LjIzNDM3NSwwLjIxODc1IDAuMTI1LDAgMC4yMzQzNzUsLTAuMDc4MTI1IDAuMjgxMjUsLTAuMTQw +NjI1IDAuMDMxMjUsLTAuMDYyNSAwLjA3ODEyNSwtMC4yOTY4NzUgMC4xMjUsLTAuNDM3NSAwLjAz +MTI1LC0wLjEyNSAwLjEwOTM3NSwtMC40NTMxMjUgMC4xNDA2MjUsLTAuNjI1IDAuMDQ2ODc1LC0w +LjE1NjI1IDAuMDkzNzUsLTAuMzEyNSAwLjEyNSwtMC40Njg3NSAwLjA3ODEyNSwtMC4yODEyNSAw +LjA5Mzc1LC0wLjM0Mzc1IDAuMjk2ODc1LC0wLjYyNSBDIDIuMTcxODc1LC0yLjUxNTYyNSAyLjUs +LTIuODc1IDMuMDMxMjUsLTIuODc1IGMgMC4zOTA2MjUsMCAwLjQwNjI1LDAuMzU5Mzc1IDAuNDA2 +MjUsMC40ODQzNzUgMCwwLjQyMTg3NSAtMC4yOTY4NzUsMS4xODc1IC0wLjQwNjI1LDEuNDg0Mzc1 +IC0wLjA3ODEyNSwwLjIwMzEyNSAtMC4xMDkzNzUsMC4yNjU2MjUgLTAuMTA5Mzc1LDAuMzc1IDAs +MC4zNzUgMC4yOTY4NzUsMC41OTM3NSAwLjY1NjI1LDAuNTkzNzUgMC43MDMxMjUsMCAxLC0wLjk1 +MzEyNSAxLC0xLjA2MjUgMCwtMC4wOTM3NSAtMC4wNzgxMjUsLTAuMDkzNzUgLTAuMTA5Mzc1LC0w +LjA5Mzc1IC0wLjA5Mzc1LDAgLTAuMDkzNzUsMC4wNDY4NzUgLTAuMTI1LDAuMTI1IEMgNC4xODc1 +LC0wLjQwNjI1IDMuODc1LC0wLjEyNSAzLjYwOTM3NSwtMC4xMjUgYyAtMC4xNTYyNSwwIC0wLjE4 +NzUsLTAuMDkzNzUgLTAuMTg3NSwtMC4yNSAwLC0wLjE1NjI1IDAuMDQ2ODc1LC0wLjI1IDAuMTcx +ODc1LC0wLjU2MjUgMC4wNzgxMjUsLTAuMjE4NzUgMC4zNTkzNzUsLTAuOTUzMTI1IDAuMzU5Mzc1 +LC0xLjM0Mzc1IDAsLTAuNjcxODc1IC0wLjUzMTI1LC0wLjc5Njg3NSAtMC45MDYyNSwtMC43OTY4 +NzUgLTAuNTc4MTI1LDAgLTAuOTY4NzUsMC4zNTkzNzUgLTEuMTcxODc1LDAuNjQwNjI1IC0wLjA0 +Njg3NSwtMC40ODQzNzUgLTAuNDUzMTI1LC0wLjY0MDYyNSAtMC43NSwtMC42NDA2MjUgLTAuMjk2 +ODc1LDAgLTAuNDUzMTI1LDAuMjE4NzUgLTAuNTQ2ODc1LDAuMzc1IC0wLjE1NjI1LDAuMjY1NjI1 +IC0wLjI1LDAuNjU2MjUgLTAuMjUsMC43MDMxMjUgMCwwLjA3ODEyNSAwLjA5Mzc1LDAuMDc4MTI1 +IDAuMTI1LDAuMDc4MTI1IDAuMDkzNzUsMCAwLjA5Mzc1LC0wLjAxNTYyNSAwLjE0MDYyNSwtMC4y +MDMxMjUgMC4xMDkzNzUsLTAuNDA2MjUgMC4yNSwtMC43NSAwLjUxNTYyNSwtMC43NSAwLjE4NzUs +MCAwLjIzNDM3NSwwLjE1NjI1IDAuMjM0Mzc1LDAuMzQzNzUgMCwwLjEyNSAtMC4wNjI1LDAuMzkw +NjI1IC0wLjEyNSwwLjU3ODEyNSAtMC4wNDY4NzUsMC4xODc1IC0wLjEwOTM3NSwwLjQ2ODc1IC0w +LjE0MDYyNSwwLjYyNSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTg1IiAvPgogICAgICA8 +L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNp +dHk6MSIKICAgICAgIGlkPSJnMTE0Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTExMiIKICAg +ICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQwLjYyNjAxLDc4Ljk4Nzk5OSkiPgogICAgICAg +IDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gMTIu +NjI1LDEzLjk1MzEyNSAxLjIwMzEyNSwtMy4xODc1IGggLTAuMjUgYyAtMC4zOTA2MjUsMS4wMzEy +NSAtMS40NTMxMjUsMS43MTg3NSAtMi41OTM3NSwyLjAxNTYyNSAtMC4yMDMxMjUsMC4wNDY4NyAt +MS4xODc1LDAuMzEyNSAtMy4wOTM3NSwwLjMxMjUgSCAxLjg3NSBMIDYuOTUzMTI1LDcuMTQwNjI1 +IEMgNy4wMTU2MjUsNy4wNjI1IDcuMDMxMjUsNy4wMzEyNSA3LjAzMTI1LDYuOTg0Mzc1IGMgMCwt +MC4wMzEyNSAwLC0wLjA2MjUgLTAuMDYyNSwtMC4xNTYyNSBMIDIuMzI4MTI1LDAuNDg0Mzc1IEgg +Ny43ODEyNSBjIDEuMzQzNzUsMCAyLjI1LDAuMTQwNjI1IDIuMzQzNzUsMC4xNTYyNSAwLjUzMTI1 +LDAuMDc4MTI1IDEuNDA2MjUsMC4yNSAyLjE4NzUsMC43NSAwLjI1LDAuMTU2MjUgMC45MjE4NzUs +MC42MDkzNzUgMS4yNjU2MjUsMS40MDYyNSBoIDAuMjUgTCAxMi42MjUsMCBIIDAuODQzNzUgYyAt +MC4yMzQzNzUsMCAtMC4yNSwwLjAxNTYyNSAtMC4yODEyNSwwLjA2MjUgMCwwLjAzMTI1IDAsMC4y +MzQzNzUgMCwwLjM0Mzc1IGwgNS4yNjU2MjUsNy4yMDMxMjUgLTUuMTU2MjUsNi4wNjI1IEMgMC41 +NjI1LDEzLjc4MTI1IDAuNTYyNSwxMy44NDM3NSAwLjU2MjUsMTMuODQzNzUgYyAwLDAuMTA5Mzc1 +IDAuMDkzNzUsMC4xMDkzNzUgMC4yODEyNSwwLjEwOTM3NSB6IG0gMCwwIgogICAgICAgICAgIGlk +PSJwYXRoMTg5IiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZp +bGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTE4Ij4KICAgICAgPGcKICAg +ICAgICAgaWQ9InVzZTExNiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQwLjU3Niwx +MDAuNDM1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAg +ICAgICAgICAgZD0ibSAyLjE4NzUsLTQuNjI1IGMgMCwtMC4wMTU2MjUgMC4wMTU2MjUsLTAuMTA5 +Mzc1IDAuMDE1NjI1LC0wLjEwOTM3NSAwLC0wLjA0Njg3NSAtMC4wMTU2MjUsLTAuMTA5Mzc1IC0w +LjEwOTM3NSwtMC4xMDkzNzUgLTAuMTQwNjI1LDAgLTAuNzE4NzUsMC4wNjI1IC0wLjg5MDYyNSww +LjA3ODEyNSAtMC4wNDY4NzUsMCAtMC4xNTYyNSwwLjAxNTYyNSAtMC4xNTYyNSwwLjE1NjI1IDAs +MC4wOTM3NSAwLjEwOTM3NSwwLjA5Mzc1IDAuMTg3NSwwLjA5Mzc1IDAuMzI4MTI1LDAgMC4zMjgx +MjUsMC4wNjI1IDAuMzI4MTI1LDAuMTA5Mzc1IDAsMC4wNDY4NzUgLTAuMDE1NjI1LDAuMDkzNzUg +LTAuMDE1NjI1LDAuMTU2MjUgTCAwLjU2MjUsLTAuMzEyNSBjIC0wLjA0Njg3NSwwLjEyNSAtMC4w +NDY4NzUsMC4xNDA2MjUgLTAuMDQ2ODc1LDAuMTU2MjUgMCwwLjEwOTM3NSAwLjA5Mzc1LDAuMjE4 +NzUgMC4yNSwwLjIxODc1IDAuMTg3NSwwIDAuMjY1NjI1LC0wLjEyNSAwLjMxMjUsLTAuMjgxMjUg +MC4wMTU2MjUsLTAuMDMxMjUgMC4zMTI1LC0xLjI2NTYyNSAwLjM0Mzc1LC0xLjM1OTM3NSAwLjUs +MC4wNDY4NzUgMC44OTA2MjUsMC4yMTg3NSAwLjg5MDYyNSwwLjU3ODEyNSAwLDAuMDMxMjUgMCww +LjA2MjUgLTAuMDE1NjI1LDAuMTQwNjI1IC0wLjAzMTI1LDAuMDkzNzUgLTAuMDMxMjUsMC4xNDA2 +MjUgLTAuMDMxMjUsMC4yMTg3NSAwLDAuNDg0Mzc1IDAuNDA2MjUsMC43MDMxMjUgMC43NSwwLjcw +MzEyNSAwLjY3MTg3NSwwIDAuODc1LC0xLjA0Njg3NSAwLjg3NSwtMS4wNjI1IDAsLTAuMDkzNzUg +LTAuMDc4MTI1LC0wLjA5Mzc1IC0wLjEwOTM3NSwtMC4wOTM3NSAtMC4wOTM3NSwwIC0wLjEwOTM3 +NSwwLjA0Njg3NSAtMC4xNDA2MjUsMC4xNzE4NzUgQyAzLjU2MjUsLTAuNjI1IDMuMzc1LC0wLjEy +NSAzLjAzMTI1LC0wLjEyNSBjIC0wLjE4NzUsMCAtMC4yNSwtMC4xNzE4NzUgLTAuMjUsLTAuMzU5 +Mzc1IDAsLTAuMTI1IDAsLTAuMTQwNjI1IDAuMDQ2ODc1LC0wLjMxMjUgMC4wMTU2MjUsLTAuMDMx +MjUgMC4wMzEyNSwtMC4xNDA2MjUgMC4wMzEyNSwtMC4yMTg3NSAwLC0wLjYyNSAtMC44MjgxMjUs +LTAuNzE4NzUgLTEuMTI1LC0wLjczNDM3NSBDIDEuOTM3NSwtMS44NzUgMi4xODc1LC0yLjEwOTM3 +NSAyLjMxMjUsLTIuMjE4NzUgMi42NzE4NzUsLTIuNTQ2ODc1IDMuMDE1NjI1LC0yLjg3NSAzLjQw +NjI1LC0yLjg3NSBjIDAuMDc4MTI1LDAgMC4xNzE4NzUsMC4wMTU2MjUgMC4yMzQzNzUsMC4wOTM3 +NSBDIDMuMzQzNzUsLTIuNzM0Mzc1IDMuMjgxMjUsLTIuNSAzLjI4MTI1LC0yLjM5MDYyNSBjIDAs +MC4xNDA2MjUgMC4xMDkzNzUsMC4yNSAwLjI2NTYyNSwwLjI1IDAuMjAzMTI1LDAgMC40MDYyNSwt +MC4xNTYyNSAwLjQwNjI1LC0wLjQzNzUgMCwtMC4yMzQzNzUgLTAuMTcxODc1LC0wLjUgLTAuNTMx +MjUsLTAuNSAtMC40MDYyNSwwIC0wLjc2NTYyNSwwLjI5Njg3NSAtMS4xMjUsMC42MjUgQyAyLC0y +LjE4NzUgMS43ODEyNSwtMS45Njg3NSAxLjQ4NDM3NSwtMS44NDM3NSBaIG0gMCwwIgogICAgICAg +ICAgIGlkPSJwYXRoMTkzIiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5 +bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTI0Ij4KICAgICAg +PGcKICAgICAgICAgaWQ9InVzZTEyMCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQ0 +Ljk3OSwxMDAuNDM1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5v +bmUiCiAgICAgICAgICAgZD0ibSA1LjM1OTM3NSwtMi4zNDM3NSBjIDAuMDkzNzUsMCAwLjI1LDAg +MC4yNSwtMC4xNzE4NzUgMCwtMC4xNzE4NzUgLTAuMTU2MjUsLTAuMTcxODc1IC0wLjI1LC0wLjE3 +MTg3NSBIIDAuNzUgYyAtMC4wOTM3NSwwIC0wLjI2NTYyNSwwIC0wLjI2NTYyNSwwLjE3MTg3NSAw +LDAuMTcxODc1IDAuMTU2MjUsMC4xNzE4NzUgMC4yNjU2MjUsMC4xNzE4NzUgeiBtIDAsMS41MzEy +NSBjIDAuMDkzNzUsMCAwLjI1LDAgMC4yNSwtMC4xNTYyNSAwLC0wLjE4NzUgLTAuMTU2MjUsLTAu +MTg3NSAtMC4yNSwtMC4xODc1IEggMC43NSBjIC0wLjEwOTM3NSwwIC0wLjI2NTYyNSwwIC0wLjI2 +NTYyNSwwLjE4NzUgMCwwLjE1NjI1IDAuMTcxODc1LDAuMTU2MjUgMC4yNjU2MjUsMC4xNTYyNSB6 +IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTk3IiAvPgogICAgICA8L2c+CiAgICAgIDxnCiAg +ICAgICAgIGlkPSJ1c2UxMjIiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1MS4wOTUw +MiwxMDAuNDM1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUi +CiAgICAgICAgICAgZD0ibSAyLjMyODEyNSwtNC40Mzc1IGMgMCwtMC4xODc1IDAsLTAuMTg3NSAt +MC4yMDMxMjUsLTAuMTg3NSAtMC40NTMxMjUsMC40Mzc1IC0xLjA3ODEyNSwwLjQzNzUgLTEuMzU5 +Mzc1LDAuNDM3NSB2IDAuMjUgYyAwLjE1NjI1LDAgMC42MjUsMCAxLC0wLjE4NzUgdiAzLjU0Njg3 +NSBjIDAsMC4yMzQzNzUgMCwwLjMyODEyNSAtMC42ODc1LDAuMzI4MTI1IEggMC44MTI1IFYgMCBj +IDAuMTI1LDAgMC45ODQzNzUsLTAuMDMxMjUgMS4yMzQzNzUsLTAuMDMxMjUgMC4yMTg3NSwwIDEu +MDkzNzUsMC4wMzEyNSAxLjI1LDAuMDMxMjUgViAtMC4yNSBIIDMuMDMxMjUgYyAtMC43MDMxMjUs +MCAtMC43MDMxMjUsLTAuMDkzNzUgLTAuNzAzMTI1LC0wLjMyODEyNSB6IG0gMCwwIgogICAgICAg +ICAgIGlkPSJwYXRoMjAxIiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5 +bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTI4Ij4KICAgICAg +PGcKICAgICAgICAgaWQ9InVzZTEyNiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTYw +LjQxNzAxLDgxLjcxMjk5NykiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9r +ZTpub25lIgogICAgICAgICAgIGQ9Im0gMi45Mzc1LC02LjM3NSBjIDAsLTAuMjUgMCwtMC4yNjU2 +MjUgLTAuMjM0Mzc1LC0wLjI2NTYyNSBDIDIuMDc4MTI1LC02IDEuMjAzMTI1LC02IDAuODkwNjI1 +LC02IHYgMC4zMTI1IGMgMC4yMDMxMjUsMCAwLjc4MTI1LDAgMS4yOTY4NzUsLTAuMjY1NjI1IHYg +NS4xNzE4NzUgYyAwLDAuMzU5Mzc1IC0wLjAzMTI1LDAuNDY4NzUgLTAuOTIxODc1LDAuNDY4NzUg +aCAtMC4zMTI1IFYgMCBjIDAuMzQzNzUsLTAuMDMxMjUgMS4yMDMxMjUsLTAuMDMxMjUgMS42MDkz +NzUsLTAuMDMxMjUgMC4zOTA2MjUsMCAxLjI2NTYyNSwwIDEuNjA5Mzc1LDAuMDMxMjUgdiAtMC4z +MTI1IGggLTAuMzEyNSBjIC0wLjkwNjI1LDAgLTAuOTIxODc1LC0wLjEwOTM3NSAtMC45MjE4NzUs +LTAuNDY4NzUgeiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDIwNSIgLz4KICAgICAgPC9nPgog +ICAgPC9nPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7 +c3Ryb2tlLXdpZHRoOjAuMzk4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1p +dGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJtIC0x +LjI1ZS00LDAuMDAxMDYyNSBoIDkuOTY4NzUiCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLDAs +MCwtMSwxNTcuOTIyLDg1Ljk2MikiCiAgICAgICBpZD0icGF0aDEzMCIgLz4KICAgIDxnCiAgICAg +ICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMzQiPgog +ICAgICA8ZwogICAgICAgICBpZD0idXNlMTMyIgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0 +ZSgxNTcuOTIyLDk1LjI4NjAwMykiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0 +cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gMi44NTkzNzUsLTYuODEyNSBjIDAsMCAwLC0wLjEw +OTM3NSAtMC4xMjUsLTAuMTA5Mzc1IC0wLjIzNDM3NSwwIC0wLjk1MzEyNSwwLjA3ODEyNSAtMS4y +MTg3NSwwLjEwOTM3NSAtMC4wNzgxMjUsMCAtMC4xODc1LDAuMDE1NjI1IC0wLjE4NzUsMC4xODc1 +IDAsMC4xMjUgMC4wOTM3NSwwLjEyNSAwLjIzNDM3NSwwLjEyNSAwLjQ4NDM3NSwwIDAuNSwwLjA2 +MjUgMC41LDAuMTcxODc1IEwgMi4wMzEyNSwtNi4xMjUgMC41OTM3NSwtMC4zOTA2MjUgYyAtMC4w +NDY4NzUsMC4xNDA2MjUgLTAuMDQ2ODc1LDAuMTU2MjUgLTAuMDQ2ODc1LDAuMjE4NzUgMCwwLjIz +NDM3NSAwLjIwMzEyNSwwLjI4MTI1IDAuMjk2ODc1LDAuMjgxMjUgMC4xMjUsMCAwLjI2NTYyNSwt +MC4wOTM3NSAwLjMyODEyNSwtMC4yMDMxMjUgMC4wNDY4NzUsLTAuMDkzNzUgMC41LC0xLjkzNzUg +MC41NjI1LC0yLjE4NzUgMC4zNDM3NSwwLjAzMTI1IDEuMTU2MjUsMC4xODc1IDEuMTU2MjUsMC44 +NDM3NSAwLDAuMDc4MTI1IDAsMC4xMDkzNzUgLTAuMDMxMjUsMC4yMTg3NSAtMC4wMTU2MjUsMC4x +MDkzNzUgLTAuMDMxMjUsMC4yMzQzNzUgLTAuMDMxMjUsMC4zNDM3NSAwLDAuNTc4MTI1IDAuMzkw +NjI1LDAuOTg0Mzc1IDAuOTA2MjUsMC45ODQzNzUgMC4yOTY4NzUsMCAwLjU3ODEyNSwtMC4xNTYy +NSAwLjc5Njg3NSwtMC41MzEyNSAwLjI1LC0wLjQzNzUgMC4zNTkzNzUsLTAuOTg0Mzc1IDAuMzU5 +Mzc1LC0xIDAsLTAuMTA5Mzc1IC0wLjA5Mzc1LC0wLjEwOTM3NSAtMC4xMjUsLTAuMTA5Mzc1IC0w +LjA5Mzc1LDAgLTAuMTA5Mzc1LDAuMDQ2ODc1IC0wLjE0MDYyNSwwLjE4NzUgLTAuMjAzMTI1LDAu +NzE4NzUgLTAuNDIxODc1LDEuMjM0Mzc1IC0wLjg1OTM3NSwxLjIzNDM3NSAtMC4yMDMxMjUsMCAt +MC4zMjgxMjUsLTAuMTA5Mzc1IC0wLjMyODEyNSwtMC40Njg3NSAwLC0wLjE3MTg3NSAwLjA0Njg3 +NSwtMC40MDYyNSAwLjA3ODEyNSwtMC41NjI1IEMgMy41NjI1LC0xLjMxMjUgMy41NjI1LC0xLjM0 +Mzc1IDMuNTYyNSwtMS40NTMxMjUgMy41NjI1LC0yLjA5Mzc1IDIuOTM3NSwtMi4zNzUgMi4wNzgx +MjUsLTIuNSAyLjM5MDYyNSwtMi42NzE4NzUgMi43MTg3NSwtMi45ODQzNzUgMi45Mzc1LC0zLjIz +NDM3NSAzLjQyMTg3NSwtMy43NjU2MjUgMy44NzUsLTQuMTg3NSA0LjM1OTM3NSwtNC4xODc1IGMg +MC4wNjI1LDAgMC4wNzgxMjUsMCAwLjA5Mzc1LDAuMDE1NjI1IDAuMTI1LDAuMDE1NjI1IDAuMTI1 +LDAuMDE1NjI1IDAuMjE4NzUsMC4wNzgxMjUgMC4wMTU2MjUsMCAwLjAxNTYyNSwwLjAxNTYyNSAw +LjAzMTI1LDAuMDMxMjUgLTAuNDY4NzUsMC4wMzEyNSAtMC41NjI1LDAuNDIxODc1IC0wLjU2MjUs +MC41NDY4NzUgMCwwLjE1NjI1IDAuMTA5Mzc1LDAuMzQzNzUgMC4zNzUsMC4zNDM3NSAwLjI2NTYy +NSwwIDAuNTQ2ODc1LC0wLjIxODc1IDAuNTQ2ODc1LC0wLjYwOTM3NSAwLC0wLjI5Njg3NSAtMC4y +MzQzNzUsLTAuNjI1IC0wLjY3MTg3NSwtMC42MjUgLTAuMjgxMjUsMCAtMC43MzQzNzUsMC4wNzgx +MjUgLTEuNDUzMTI1LDAuODc1IC0wLjM0Mzc1LDAuMzc1IC0wLjczNDM3NSwwLjc4MTI1IC0xLjEw +OTM3NSwwLjkyMTg3NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMjA5IiAvPgogICAgICA8 +L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNp +dHk6MSIKICAgICAgIGlkPSJnMTM4Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTEzNiIKICAg +ICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTYzLjQyMyw5Mi40MDc5OTcpIj4KICAgICAgICA8 +cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJNIDMuNTE1 +NjI1LC0xLjI2NTYyNSBIIDMuMjgxMjUgYyAtMC4wMTU2MjUsMC4xNTYyNSAtMC4wOTM3NSwwLjU2 +MjUgLTAuMTg3NSwwLjYyNSBDIDMuMDQ2ODc1LC0wLjU5Mzc1IDIuNTE1NjI1LC0wLjU5Mzc1IDIu +NDA2MjUsLTAuNTkzNzUgSCAxLjEyNSBjIDAuNzM0Mzc1LC0wLjY0MDYyNSAwLjk4NDM3NSwtMC44 +NDM3NSAxLjM5MDYyNSwtMS4xNzE4NzUgMC41MTU2MjUsLTAuNDA2MjUgMSwtMC44NDM3NSAxLC0x +LjUgMCwtMC44NDM3NSAtMC43MzQzNzUsLTEuMzU5Mzc1IC0xLjYyNSwtMS4zNTkzNzUgLTAuODU5 +Mzc1LDAgLTEuNDUzMTI1LDAuNjA5Mzc1IC0xLjQ1MzEyNSwxLjI1IDAsMC4zNDM3NSAwLjI5Njg3 +NSwwLjM5MDYyNSAwLjM3NSwwLjM5MDYyNSAwLjE1NjI1LDAgMC4zNTkzNzUsLTAuMTI1IDAuMzU5 +Mzc1LC0wLjM3NSAwLC0wLjEyNSAtMC4wNDY4NzUsLTAuMzc1IC0wLjQwNjI1LC0wLjM3NSBDIDAu +OTg0Mzc1LC00LjIxODc1IDEuNDUzMTI1LC00LjM3NSAxLjc4MTI1LC00LjM3NSBjIDAuNzAzMTI1 +LDAgMS4wNjI1LDAuNTQ2ODc1IDEuMDYyNSwxLjEwOTM3NSAwLDAuNjA5Mzc1IC0wLjQzNzUsMS4w +NzgxMjUgLTAuNjU2MjUsMS4zMjgxMjUgTCAwLjUxNTYyNSwtMC4yNjU2MjUgQyAwLjQzNzUsLTAu +MjAzMTI1IDAuNDM3NSwtMC4xODc1IDAuNDM3NSwwIGggMi44NzUgeiBtIDAsMCIKICAgICAgICAg +ICBpZD0icGF0aDIxMyIgLz4KICAgICAgPC9nPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/51125b32a740b8441210140690d55f8e.msg b/share/extensions/tests/data/cmd/inkscape/51125b32a740b8441210140690d55f8e.msg new file mode 100644 index 0000000..740c604 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/51125b32a740b8441210140690d55f8e.msg @@ -0,0 +1,13 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --query-id=t3 input.svg -X -Y -W -H + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +MzAwLjM5NAo4OC44NTY3CjY1LjgwNjgKNDguMDE3Nwo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/586740f52b3a497fe4ba77501ad443f4.msg b/share/extensions/tests/data/cmd/inkscape/586740f52b3a497fe4ba77501ad443f4.msg new file mode 100644 index 0000000..93e8558 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/586740f52b3a497fe4ba77501ad443f4.msg @@ -0,0 +1,73 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:0:364:495 --export-filename=output_0.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output_0.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output_0.png + +iVBORw0KGgoAAAANSUhEUgAAAWwAAAHvCAYAAABwu+XPAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAACtRJREFUeJzt3V2oZWUdx/HfGY9a +mhk2jKmQDtmLF472YlSaJqkpvRB1JRSUEd104UVUYjeVUREhWARFGFQEdZGigVlW9mIFWvZiSIkY +Jfna22g66jTTxTPiTM6c9Zxz9t5r/8/+fGAzMGfNef4zZ8737L3W2mslAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAACsxdLYA8yxi/Y8gPE8mOStYw8xL5bHHmCOnZzk9LGHgAX3yNgDzJNN +Yw8AQB/BBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGK +EGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihC +sAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjB +BihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQb +oAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyA +IgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGK +EGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihC +sAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjBBihCsAGKEGyAIgQboAjB +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 + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/67e526c4c1e53207e5e46274e8cdfcc0.msg b/share/extensions/tests/data/cmd/inkscape/67e526c4c1e53207e5e46274e8cdfcc0.msg new file mode 100644 index 0000000..fe04dbb --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/67e526c4c1e53207e5e46274e8cdfcc0.msg @@ -0,0 +1,17 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-dpi=1 --export-filename=Slide3.png --export-type=png Slide3.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide3.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide3.png + +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAAnAAAAJwEqCZFPAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAADFJREFUGJVjYBgwwIhL4j8DgywD +A4McVNFRFjyGKDEwMDhC2XgVPmFgYDhOqhMHEgAAHzAE3cTGGWYAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/683466390d1961f2c66be46d75893e9c.msg b/share/extensions/tests/data/cmd/inkscape/683466390d1961f2c66be46d75893e9c.msg new file mode 100644 index 0000000..b19614b --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/683466390d1961f2c66be46d75893e9c.msg @@ -0,0 +1,64 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:495:364:1123 --export-filename=output_2.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output_2.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output_2.png + +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 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAABwuP8CKTPDx0NXn34AAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/6bb74fec5efd21cdad5bc4e0bb7b7b40.msg b/share/extensions/tests/data/cmd/inkscape/6bb74fec5efd21cdad5bc4e0bb7b7b40.msg new file mode 100644 index 0000000..6dbdba2 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/6bb74fec5efd21cdad5bc4e0bb7b7b40.msg @@ -0,0 +1,120 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=select-all;page-fit-to-selection;clone-unlink-recursively;vacuum-defs --export-filename=output.svg --export-type=svg --pdf-page=1 --pdf-poppler input.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgd2lkdGg9IjM2LjkyOTY4OHB0IgogICBoZWlnaHQ9IjI3Ljg4MTEyNHB0IgogICB2aWV3 +Qm94PSIwIDAgMzYuOTI5Njg3IDI3Ljg4MTEyNCIKICAgdmVyc2lvbj0iMS4yIgogICBpZD0ic3Zn +NTUiCiAgIHNvZGlwb2RpOmRvY25hbWU9ImlucHV0LnBkZiIKICAgeG1sbnM6aW5rc2NhcGU9Imh0 +dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlw +b2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIK +ICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6 +Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9Im5h +bWVkdmlldzU3IgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzAw +MDAwMCIKICAgICBib3JkZXJvcGFjaXR5PSIwLjI1IgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9 +IjIiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlY2hl +Y2tlcmJvYXJkPSIwIgogICAgIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIKICAgICBpbmtz +Y2FwZTpkb2N1bWVudC11bml0cz0icHQiIC8+CiAgPGRlZnMKICAgICBpZD0iZGVmczI4Ij4KICAg +IDxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXAxIj4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAx +NiwxOCBoIDcgdiAxMC40NDkyMTkgaCAtNyB6IG0gMCwwIgogICAgICAgICBpZD0icGF0aDI1IiAv +PgogICAgPC9jbGlwUGF0aD4KICA8L2RlZnM+CiAgPGcKICAgICBpZD0ic3VyZmFjZTEiCiAgICAg +dHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuMTk1MzEyNSwtMC41Njk4NzUpIj4KICAgIDxnCiAgICAg +ICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImczNCI+CiAg +ICAgIDxnCiAgICAgICAgIGlkPSJ1c2UzMCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUo +MS4xOTYsMTMuMDE1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5v +bmUiCiAgICAgICAgICAgZD0ibSA0LjEyNSwtOS4xODc1IGMgMCwtMC4zNDM3NSAwLC0wLjM0Mzc1 +IC0wLjI4MTI1LC0wLjM0Mzc1IEMgMy41LC05LjE1NjI1IDIuNzgxMjUsLTguNjI1IDEuMzEyNSwt +OC42MjUgdiAwLjQyMTg3NSBjIDAuMzI4MTI1LDAgMS4wNDY4NzUsMCAxLjgyODEyNSwtMC4zNzUg +diA3LjQ2ODc1IGMgMCwwLjUxNTYyNSAtMC4wNDY4NzUsMC42ODc1IC0xLjI5Njg3NSwwLjY4NzUg +SCAxLjM5MDYyNSBWIDAgYyAwLjM5MDYyNSwtMC4wMzEyNSAxLjc4MTI1LC0wLjAzMTI1IDIuMjUs +LTAuMDMxMjUgMC40Njg3NSwwIDEuODU5Mzc1LDAgMi4yMzQzNzUsMC4wMzEyNSBWIC0wLjQyMTg3 +NSBIIDUuNDM3NSBjIC0xLjI2NTYyNSwwIC0xLjMxMjUsLTAuMTcxODc1IC0xLjMxMjUsLTAuNjg3 +NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoNTkiIC8+CiAgICAgIDwvZz4KICAgICAgPGcK +ICAgICAgICAgaWQ9InVzZTMyIgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSg4LjIxOTkw +MDEsMTMuMDE1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUi +CiAgICAgICAgICAgZD0iTSA1LjcxODc1LC0zLjMxMjUgSCA5LjY4NzUgYyAwLjIwMzEyNSwwIDAu +NDUzMTI1LDAgMC40NTMxMjUsLTAuMjY1NjI1IDAsLTAuMjY1NjI1IC0wLjI1LC0wLjI2NTYyNSAt +MC40NTMxMjUsLTAuMjY1NjI1IEggNS43MTg3NSB2IC0zLjk1MzEyNSBjIDAsLTAuMjAzMTI1IDAs +LTAuNDY4NzUgLTAuMjUsLTAuNDY4NzUgLTAuMjgxMjUsMCAtMC4yODEyNSwwLjI1IC0wLjI4MTI1 +LDAuNDY4NzUgViAtMy44NDM3NSBIIDEuMjM0Mzc1IGMgLTAuMjAzMTI1LDAgLTAuNDUzMTI1LDAg +LTAuNDUzMTI1LDAuMjY1NjI1IDAsMC4yNjU2MjUgMC4yMzQzNzUsMC4yNjU2MjUgMC40NTMxMjUs +MC4yNjU2MjUgSCA1LjE4NzUgdiAzLjk1MzEyNSBjIDAsMC4yMDMxMjUgMCwwLjQ2ODc1IDAuMjY1 +NjI1LDAuNDY4NzUgMC4yNjU2MjUsMCAwLjI2NTYyNSwtMC4yNSAwLjI2NTYyNSwtMC40Njg3NSB6 +IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoNjMiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAg +IDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9 +ImczOCI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2UzNiIKICAgICAgICAgdHJhbnNmb3JtPSJ0 +cmFuc2xhdGUoMTkuMTQ1LDEuMTQ4KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0i +c3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0iTSA1LjU3ODEyNSwxMi4yNjU2MjUgMy4wNjI1LDYu +Njg3NSBDIDIuOTUzMTI1LDYuNDUzMTI1IDIuODkwNjI1LDYuNDUzMTI1IDIuODQzNzUsNi40NTMx +MjUgYyAtMC4wMTU2MjUsMCAtMC4wOTM3NSwwIC0wLjI1LDAuMTA5Mzc1IEwgMS4yMzQzNzUsNy42 +MDkzNzUgYyAtMC4xODc1LDAuMTQwNjI1IC0wLjE4NzUsMC4xNzE4NzUgLTAuMTg3NSwwLjIxODc1 +IDAsMC4wNzgxMjUgMC4wNDY4NzUsMC4xNTYyNSAwLjE0MDYyNSwwLjE1NjI1IDAuMDkzNzUsMCAw +LjMyODEyNSwtMC4yMDMxMjUgMC40ODQzNzUsLTAuMzEyNSAwLjA5Mzc1LC0wLjA2MjUgMC4zMTI1 +LC0wLjIzNDM3NSAwLjQ2ODc1LC0wLjM0Mzc1IGwgMi44MjgxMjUsNi4yMTg3NSBjIDAuMDkzNzUs +MC4yMTg3NSAwLjE3MTg3NSwwLjIxODc1IDAuMjk2ODc1LDAuMjE4NzUgMC4yMTg3NSwwIDAuMjUs +LTAuMDc4MTMgMC4zNTkzNzUsLTAuMjgxMjUgTCAxMi4xNDA2MjUsMCBjIDAuMDkzNzUsLTAuMjAz +MTI1IDAuMDkzNzUsLTAuMjY1NjI1IDAuMDkzNzUsLTAuMjgxMjUgMCwtMC4xNTYyNSAtMC4xMDkz +NzUsLTAuMjk2ODc1IC0wLjI4MTI1LC0wLjI5Njg3NSAtMC4xMjUsMCAtMC4yMTg3NSwwLjA3ODEy +NSAtMC4zMjgxMjUsMC4zMTI1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGg2NyIgLz4KICAg +ICAgPC9nPgogICAgPC9nPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tl +OiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjAuNTc0O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxp +bmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAg +ICBkPSJNIDAuMDAxNTYyNSwwLjAwMTYyNSBIIDcuMDI1IgogICAgICAgdHJhbnNmb3JtPSJtYXRy +aXgoMSwwLDAsLTEsMzEuMSwwLjg2MSkiCiAgICAgICBpZD0icGF0aDQwIiAvPgogICAgPGcKICAg +ICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpZD0iZzQ0Ij4K +ICAgICAgPGcKICAgICAgICAgaWQ9InVzZTQyIgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0 +ZSgzMS4xLDEzLjAxNSkiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpu +b25lIgogICAgICAgICAgIGQ9Ik0gMS44NDM3NSwtOC4yMTg3NSBDIDIuNDUzMTI1LC04LjAxNTYy +NSAyLjk1MzEyNSwtOCAzLjEwOTM3NSwtOCBjIDEuNjI1LDAgMi42NTYyNSwtMS4xODc1IDIuNjU2 +MjUsLTEuMzkwNjI1IDAsLTAuMDYyNSAtMC4wMzEyNSwtMC4xNDA2MjUgLTAuMTA5Mzc1LC0wLjE0 +MDYyNSAtMC4wMzEyNSwwIC0wLjA2MjUsMCAtMC4xODc1LDAuMDYyNSAtMC44MTI1LDAuMzQzNzUg +LTEuNSwwLjM5MDYyNSAtMS44NzUsMC4zOTA2MjUgLTAuOTM3NSwwIC0xLjYwOTM3NSwtMC4yODEy +NSAtMS44OTA2MjUsLTAuNDA2MjUgLTAuMDkzNzUsLTAuMDQ2ODc1IC0wLjEyNSwtMC4wNDY4NzUg +LTAuMTQwNjI1LC0wLjA0Njg3NSAtMC4xMDkzNzUsMCAtMC4xMDkzNzUsMC4wOTM3NSAtMC4xMDkz +NzUsMC4zMjgxMjUgdiA0LjI1IGMgMCwwLjI2NTYyNSAwLDAuMzQzNzUgMC4xNzE4NzUsMC4zNDM3 +NSAwLjA2MjUsMCAwLjA3ODEyNSwtMC4wMTU2MjUgMC4yMTg3NSwtMC4xODc1IEMgMi4yNSwtNS4z +NzUgMi45MjE4NzUsLTUuNzE4NzUgMy42NDA2MjUsLTUuNzE4NzUgYyAwLjc2NTYyNSwwIDEuMTQw +NjI1LDAuNzAzMTI1IDEuMjUsMC45Mzc1IDAuMjUsMC41NjI1IDAuMjY1NjI1LDEuMjY1NjI1IDAu +MjY1NjI1LDEuODEyNSAwLDAuNTQ2ODc1IDAsMS4zNTkzNzUgLTAuNDA2MjUsMiAtMC4zMTI1LDAu +NTMxMjUgLTAuODc1LDAuODc1IC0xLjUxNTYyNSwwLjg3NSAtMC45Mzc1LDAgLTEuODc1LC0wLjY0 +MDYyNSAtMi4xMjUsLTEuNjg3NSAwLjA2MjUsMC4wMzEyNSAwLjE1NjI1LDAuMDQ2ODc1IDAuMjE4 +NzUsMC4wNDY4NzUgMC4yNSwwIDAuNjQwNjI1LC0wLjE0MDYyNSAwLjY0MDYyNSwtMC42MjUgQyAx +Ljk2ODc1LC0yLjc2NTYyNSAxLjY4NzUsLTMgMS4zMjgxMjUsLTMgYyAtMC4yNSwwIC0wLjYyNSww +LjEyNSAtMC42MjUsMC42ODc1IDAsMS4yMTg3NSAwLjk2ODc1LDIuNjA5Mzc1IDIuNTYyNSwyLjYw +OTM3NSAxLjYyNSwwIDMuMDQ2ODc1LC0xLjM1OTM3NSAzLjA0Njg3NSwtMy4xODc1IDAsLTEuNzAz +MTI1IC0xLjE1NjI1LC0zLjEyNSAtMi42NTYyNSwtMy4xMjUgLTAuODEyNSwwIC0xLjQ1MzEyNSww +LjM1OTM3NSAtMS44MTI1LDAuNzY1NjI1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGg3MSIg +Lz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7 +c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjAuODI2O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ry +b2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZS1vcGFjaXR5OjEi +CiAgICAgICBkPSJNIC02Ljg3NWUtNCwtMS41NjI1ZS00IEggMzYuOTI5IgogICAgICAgdHJhbnNm +b3JtPSJtYXRyaXgoMSwwLDAsLTEsMS4xOTYsMTYuMTYpIgogICAgICAgaWQ9InBhdGg0NiIgLz4K +ICAgIDxnCiAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcDEpIgogICAgICAgY2xpcC1ydWxlPSJu +b256ZXJvIgogICAgICAgaWQ9Imc1MiI+CiAgICAgIDxnCiAgICAgICAgIHN0eWxlPSJmaWxsOiMw +MDAwMDA7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICAgIGlkPSJnNTAiPgogICAgICAgIDxnCiAgICAg +ICAgICAgaWQ9InVzZTQ4IgogICAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2LjE0ODAw +MSwyOC40NTEpIj4KICAgICAgICAgIDxwYXRoCiAgICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5v +bmUiCiAgICAgICAgICAgICBkPSJNIDYuMzEyNSwtMi40MDYyNSBIIDYgYyAtMC4wNDY4NzUsMC4y +MzQzNzUgLTAuMTU2MjUsMS4wMzEyNSAtMC4zMTI1LDEuMjY1NjI1IC0wLjA5Mzc1LDAuMTI1IC0w +LjkwNjI1LDAuMTI1IC0xLjM0Mzc1LDAuMTI1IEggMS42ODc1IGMgMC4zOTA2MjUsLTAuMzI4MTI1 +IDEuMjY1NjI1LC0xLjI1IDEuNjQwNjI1LC0xLjU5Mzc1IDIuMTg3NSwtMi4wMTU2MjUgMi45ODQz +NzUsLTIuNzUgMi45ODQzNzUsLTQuMTcxODc1IDAsLTEuNjU2MjUgLTEuMzEyNSwtMi43NSAtMi45 +Njg3NSwtMi43NSAtMS42NzE4NzUsMCAtMi42NDA2MjUsMS40MDYyNSAtMi42NDA2MjUsMi42NDA2 +MjUgMCwwLjczNDM3NSAwLjYyNSwwLjczNDM3NSAwLjY3MTg3NSwwLjczNDM3NSAwLjI5Njg3NSww +IDAuNjcxODc1LC0wLjIxODc1IDAuNjcxODc1LC0wLjY3MTg3NSBDIDIuMDQ2ODc1LC03LjIzNDM3 +NSAxLjc4MTI1LC03LjUgMS4zNzUsLTcuNSAxLjI1LC03LjUgMS4yMTg3NSwtNy41IDEuMTcxODc1 +LC03LjQ4NDM3NSAxLjQ1MzEyNSwtOC40Njg3NSAyLjIxODc1LC05LjEyNSAzLjE1NjI1LC05LjEy +NSA0LjM3NSwtOS4xMjUgNS4xMjUsLTguMTA5Mzc1IDUuMTI1LC02Ljc4MTI1IDUuMTI1LC01LjU2 +MjUgNC40MjE4NzUsLTQuNSAzLjU5Mzc1LC0zLjU3ODEyNSBMIDAuNzAzMTI1LC0wLjM0Mzc1IFYg +MCBIIDUuOTM3NSBaIG0gMCwwIgogICAgICAgICAgICAgaWQ9InBhdGg3NSIgLz4KICAgICAgICA8 +L2c+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/7b45b58536327cfdced28568323b9f2c.msg b/share/extensions/tests/data/cmd/inkscape/7b45b58536327cfdced28568323b9f2c.msg new file mode 100644 index 0000000..59cd2b0 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/7b45b58536327cfdced28568323b9f2c.msg @@ -0,0 +1,115 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=select-all;page-fit-to-selection;clone-unlink-recursively;vacuum-defs --export-filename=output.svg --export-type=svg --pdf-page=1 --pdf-poppler input.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgd2lkdGg9IjIwLjYwMTU2MnB0IgogICBoZWlnaHQ9IjEzLjUwMjc0N3B0IgogICB2aWV3 +Qm94PSIwIDAgMjAuNjAxNTYyIDEzLjUwMjc0NiIKICAgdmVyc2lvbj0iMS4yIgogICBpZD0ic3Zn +NTAiCiAgIHNvZGlwb2RpOmRvY25hbWU9ImlucHV0LnBkZiIKICAgeG1sbnM6aW5rc2NhcGU9Imh0 +dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlw +b2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIK +ICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6 +Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9Im5h +bWVkdmlldzUyIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzAw +MDAwMCIKICAgICBib3JkZXJvcGFjaXR5PSIwLjI1IgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9 +IjIiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlY2hl +Y2tlcmJvYXJkPSIwIgogICAgIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIKICAgICBpbmtz +Y2FwZTpkb2N1bWVudC11bml0cz0icHQiIC8+CiAgPGRlZnMKICAgICBpZD0iZGVmczI1IiAvPgog +IDxnCiAgICAgaWQ9InN1cmZhY2UxIgogICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKC05My4xMjEw +OTQsLTcyLjMzNDI1MSkiPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1v +cGFjaXR5OjEiCiAgICAgICBpZD0iZzMxIj4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTI3Igog +ICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSg5My4xMjEwMDIsNzguNDU0MDAyKSI+CiAgICAg +ICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAy +LjMyODEyNSwtNC40Mzc1IGMgMCwtMC4xODc1IDAsLTAuMTg3NSAtMC4yMDMxMjUsLTAuMTg3NSAt +MC40NTMxMjUsMC40Mzc1IC0xLjA3ODEyNSwwLjQzNzUgLTEuMzU5Mzc1LDAuNDM3NSB2IDAuMjUg +YyAwLjE1NjI1LDAgMC42MjUsMCAxLC0wLjE4NzUgdiAzLjU0Njg3NSBjIDAsMC4yMzQzNzUgMCww +LjMyODEyNSAtMC42ODc1LDAuMzI4MTI1IEggMC44MTI1IFYgMCBjIDAuMTI1LDAgMC45ODQzNzUs +LTAuMDMxMjUgMS4yMzQzNzUsLTAuMDMxMjUgMC4yMTg3NSwwIDEuMDkzNzUsMC4wMzEyNSAxLjI1 +LDAuMDMxMjUgViAtMC4yNSBIIDMuMDMxMjUgYyAtMC43MDMxMjUsMCAtMC43MDMxMjUsLTAuMDkz +NzUgLTAuNzAzMTI1LC0wLjMyODEyNSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoNTQiIC8+ +CiAgICAgIDwvZz4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTI5IgogICAgICAgICB0cmFuc2Zv +cm09InRyYW5zbGF0ZSg5Ny4wOTI1ODMsNzguNDU0MDAyKSI+CiAgICAgICAgPHBhdGgKICAgICAg +ICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAzLjIxODc1LC0xLjU3ODEy +NSBoIDIuMTQwNjI1IGMgMC4wOTM3NSwwIDAuMjUsMCAwLjI1LC0wLjE1NjI1IDAsLTAuMTg3NSAt +MC4xNTYyNSwtMC4xODc1IC0wLjI1LC0wLjE4NzUgSCAzLjIxODc1IFYgLTQuMDYyNSBjIDAsLTAu +MDc4MTI1IDAsLTAuMjUgLTAuMTU2MjUsLTAuMjUgLTAuMTcxODc1LDAgLTAuMTcxODc1LDAuMTU2 +MjUgLTAuMTcxODc1LDAuMjUgdiAyLjE0MDYyNSBIIDAuNzUgYyAtMC4wOTM3NSwwIC0wLjI2NTYy +NSwwIC0wLjI2NTYyNSwwLjE3MTg3NSAwLDAuMTcxODc1IDAuMTU2MjUsMC4xNzE4NzUgMC4yNjU2 +MjUsMC4xNzE4NzUgSCAyLjg5MDYyNSBWIDAuNTYyNSBjIDAsMC4wOTM3NSAwLDAuMjY1NjI1IDAu +MTU2MjUsMC4yNjU2MjUgMC4xNzE4NzUsMCAwLjE3MTg3NSwtMC4xNzE4NzUgMC4xNzE4NzUsLTAu +MjY1NjI1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGg1OCIgLz4KICAgICAgPC9nPgogICAg +PC9nPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEiCiAg +ICAgICBpZD0iZzM1Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTMzIgogICAgICAgICB0cmFu +c2Zvcm09InRyYW5zbGF0ZSgxMDMuMjA4LDcyLjY3ODAwMSkiPgogICAgICAgIDxwYXRoCiAgICAg +ICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Ik0gMy4wOTM3NSw1Ljg3NSAx +LjcxODc1LDMuMTU2MjUgQyAxLjY4NzUsMy4wOTM3NSAxLjY3MTg3NSwzLjA0Njg3NSAxLjYwOTM3 +NSwzLjA0Njg3NSBjIC0wLjAzMTI1LDAgLTAuMDQ2ODc1LDAgLTAuMTA5Mzc1LDAuMDQ2ODc1IGwg +LTAuNzUsMC41IEMgMC42NTYyNSwzLjY1NjI1IDAuNjU2MjUsMy42ODc1IDAuNjU2MjUsMy43MTg3 +NSAwLjY1NjI1LDMuNzUgMC42ODc1LDMuODEyNSAwLjc1LDMuODEyNSBjIDAuMDMxMjUsMCAwLjA0 +Njg3NSwwIDAuMTQwNjI1LC0wLjA2MjUgQyAwLjk2ODc1LDMuNjg3NSAxLjE1NjI1LDMuNTQ2ODc1 +IDEuMjUsMy41IEwgMi43ODEyNSw2LjUxNTYyNSBDIDIuODI4MTI1LDYuNjA5Mzc1IDIuODQzNzUs +Ni42MjUgMi45Mzc1LDYuNjI1IDMsNi42MjUgMy4wNzgxMjUsNi42MjUgMy4xNDA2MjUsNi41IGwg +My41LC02LjUzMTI1IGMgMC4wNjI1LC0wLjA5Mzc1IDAuMDYyNSwtMC4wOTM3NSAwLjA2MjUsLTAu +MTQwNjI1IDAsLTAuMTA5Mzc1IC0wLjA5Mzc1LC0wLjE3MTg3NSAtMC4xNzE4NzUsLTAuMTcxODc1 +IC0wLjA5Mzc1LDAgLTAuMTQwNjI1LDAuMDYyNSAtMC4xNzE4NzUsMC4xNTYyNSB6IG0gMCwwIgog +ICAgICAgICAgIGlkPSJwYXRoNjIiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxwYXRoCiAg +ICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDowLjMzOTtz +dHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0ZXJsaW1p +dDoxMDtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSA5LjA2MjVlLTQsMS44NzVlLTQgSCAz +Ljk2OTY1NiIKICAgICAgIHRyYW5zZm9ybT0ibWF0cml4KDEsMCwwLC0xLDEwOS43NTMsNzIuNTA4 +KSIKICAgICAgIGlkPSJwYXRoMzciIC8+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAw +MDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnNDEiPgogICAgICA8ZwogICAgICAgICBpZD0i +dXNlMzkiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwOS43NTMsNzguNDU0MDAyKSI+ +CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAg +ZD0ibSAxLjA3ODEyNSwtMy44OTA2MjUgYyAwLjM1OTM3NSwwLjA5Mzc1IDAuNTYyNSwwLjA5Mzc1 +IDAuNjcxODc1LDAuMDkzNzUgMC45MjE4NzUsMCAxLjQ2ODc1LC0wLjYyNSAxLjQ2ODc1LC0wLjcz +NDM3NSAwLC0wLjA3ODEyNSAtMC4wNDY4NzUsLTAuMDkzNzUgLTAuMDc4MTI1LC0wLjA5Mzc1IC0w +LjAxNTYyNSwwIC0wLjAzMTI1LDAgLTAuMDYyNSwwLjAxNTYyNSAtMC4xNzE4NzUsMC4wNjI1IC0w +LjUzMTI1LDAuMjAzMTI1IC0xLjA0Njg3NSwwLjIwMzEyNSAtMC4yMDMxMjUsMCAtMC41NjI1LC0w +LjAxNTYyNSAtMS4wMTU2MjUsLTAuMTg3NSBDIDAuOTM3NSwtNC42MjUgMC45MjE4NzUsLTQuNjI1 +IDAuOTIxODc1LC00LjYyNSBjIC0wLjA5Mzc1LDAgLTAuMDkzNzUsMC4wNzgxMjUgLTAuMDkzNzUs +MC4xODc1IHYgMi4wNDY4NzUgYyAwLDAuMTI1IDAsMC4yMDMxMjUgMC4xMDkzNzUsMC4yMDMxMjUg +MC4wNjI1LDAgMC4wNzgxMjUsMCAwLjE0MDYyNSwtMC4wOTM3NSAwLjI5Njg3NSwtMC4zNzUgMC43 +MzQzNzUsLTAuNDM3NSAwLjk2ODc1LC0wLjQzNzUgMC40MjE4NzUsMCAwLjYwOTM3NSwwLjMyODEy +NSAwLjY0MDYyNSwwLjM5MDYyNSAwLjEyNSwwLjIzNDM3NSAwLjE3MTg3NSwwLjUgMC4xNzE4NzUs +MC45MDYyNSAwLDAuMjAzMTI1IDAsMC42MDkzNzUgLTAuMjE4NzUsMC45MjE4NzUgLTAuMTcxODc1 +LDAuMjUgLTAuNDY4NzUsMC40MjE4NzUgLTAuODEyNSwwLjQyMTg3NSAtMC40NTMxMjUsMCAtMC45 +MjE4NzUsLTAuMjUgLTEuMDkzNzUsLTAuNzE4NzUgMC4yNjU2MjUsMC4wMTU2MjUgMC40MDYyNSwt +MC4xNTYyNSAwLjQwNjI1LC0wLjM0Mzc1IDAsLTAuMjk2ODc1IC0wLjI2NTYyNSwtMC4zNDM3NSAt +MC4zNTkzNzUsLTAuMzQzNzUgMCwwIC0wLjM0Mzc1LDAgLTAuMzQzNzUsMC4zNzUgMCwwLjYyNSAw +LjU3ODEyNSwxLjI1IDEuNDA2MjUsMS4yNSAwLjg5MDYyNSwwIDEuNjcxODc1LC0wLjY1NjI1IDEu +NjcxODc1LC0xLjU0Njg3NSAwLC0wLjc4MTI1IC0wLjU5Mzc1LC0xLjUgLTEuNDUzMTI1LC0xLjUg +LTAuMzEyNSwwIC0wLjY3MTg3NSwwLjA2MjUgLTAuOTg0Mzc1LDAuMzI4MTI1IHogbSAwLDAiCiAg +ICAgICAgICAgaWQ9InBhdGg2NiIgLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPHBhdGgKICAg +ICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjAuMzk4O3N0 +cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0 +OjEwO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDkuMzc1ZS01LC0xLjU2MjVlLTQgSCAy +MC42MDE2NTYiCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLDAsMCwtMSw5My4xMjEsNzkuOTEp +IgogICAgICAgaWQ9InBhdGg0MyIgLz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAw +O2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9Imc0NyI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1 +c2U0NSIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAxLjQzNyw4NS44MzY5OTgpIj4K +ICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBk +PSJNIDMuNTE1NjI1LC0xLjI2NTYyNSBIIDMuMjgxMjUgYyAtMC4wMTU2MjUsMC4xNTYyNSAtMC4w +OTM3NSwwLjU2MjUgLTAuMTg3NSwwLjYyNSBDIDMuMDQ2ODc1LC0wLjU5Mzc1IDIuNTE1NjI1LC0w +LjU5Mzc1IDIuNDA2MjUsLTAuNTkzNzUgSCAxLjEyNSBjIDAuNzM0Mzc1LC0wLjY0MDYyNSAwLjk4 +NDM3NSwtMC44NDM3NSAxLjM5MDYyNSwtMS4xNzE4NzUgMC41MTU2MjUsLTAuNDA2MjUgMSwtMC44 +NDM3NSAxLC0xLjUgMCwtMC44NDM3NSAtMC43MzQzNzUsLTEuMzU5Mzc1IC0xLjYyNSwtMS4zNTkz +NzUgLTAuODU5Mzc1LDAgLTEuNDUzMTI1LDAuNjA5Mzc1IC0xLjQ1MzEyNSwxLjI1IDAsMC4zNDM3 +NSAwLjI5Njg3NSwwLjM5MDYyNSAwLjM3NSwwLjM5MDYyNSAwLjE1NjI1LDAgMC4zNTkzNzUsLTAu +MTI1IDAuMzU5Mzc1LC0wLjM3NSAwLC0wLjEyNSAtMC4wNDY4NzUsLTAuMzc1IC0wLjQwNjI1LC0w +LjM3NSBDIDAuOTg0Mzc1LC00LjIxODc1IDEuNDUzMTI1LC00LjM3NSAxLjc4MTI1LC00LjM3NSBj +IDAuNzAzMTI1LDAgMS4wNjI1LDAuNTQ2ODc1IDEuMDYyNSwxLjEwOTM3NSAwLDAuNjA5Mzc1IC0w +LjQzNzUsMS4wNzgxMjUgLTAuNjU2MjUsMS4zMjgxMjUgTCAwLjUxNTYyNSwtMC4yNjU2MjUgQyAw +LjQzNzUsLTAuMjAzMTI1IDAuNDM3NSwtMC4xODc1IDAuNDM3NSwwIGggMi44NzUgeiBtIDAsMCIK +ICAgICAgICAgICBpZD0icGF0aDcwIiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2 +Zz4K + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/7c51bb494fcde6ed09463674eed1e75f.msg b/share/extensions/tests/data/cmd/inkscape/7c51bb494fcde6ed09463674eed1e75f.msg new file mode 100644 index 0000000..b4b907f --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/7c51bb494fcde6ed09463674eed1e75f.msg @@ -0,0 +1,376 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=select-all;page-fit-to-selection;clone-unlink-recursively;vacuum-defs --export-filename=output.svg --export-type=svg --pdf-page=1 --pdf-poppler input.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgd2lkdGg9IjEwNC4xOTUzMXB0IgogICBoZWlnaHQ9IjQxLjkxOTEyOHB0IgogICB2aWV3 +Qm94PSIwIDAgMTA0LjE5NTMxIDQxLjkxOTEyOCIKICAgdmVyc2lvbj0iMS4yIgogICBpZD0ic3Zn +MTQxIgogICBzb2RpcG9kaTpkb2NuYW1lPSJpbnB1dC5wZGYiCiAgIHhtbG5zOmlua3NjYXBlPSJo +dHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICB4bWxuczpzb2Rp +cG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQi +CiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c3ZnPSJodHRw +Oi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJu +YW1lZHZpZXcxNDMiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIj +MDAwMDAwIgogICAgIGJvcmRlcm9wYWNpdHk9IjAuMjUiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRv +dz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2Vj +aGVja2VyYm9hcmQ9IjAiCiAgICAgaW5rc2NhcGU6ZGVza2NvbG9yPSIjZDFkMWQxIgogICAgIGlu +a3NjYXBlOmRvY3VtZW50LXVuaXRzPSJwdCIgLz4KICA8ZGVmcwogICAgIGlkPSJkZWZzNzAiIC8+ +CiAgPGcKICAgICBpZD0ic3VyZmFjZTEiCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEuMTk1 +MzEyNSwtMS4zNjI4NzUpIj4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwt +b3BhY2l0eToxIgogICAgICAgaWQ9Imc3NCI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U3MiIK +ICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS4xOTYsMTUuMDE2KSI+CiAgICAgICAgPHBh +dGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAzLjcxODc1 +LC01LjQwNjI1IGggMS42MDkzNzUgYyAtMC4zNzUsMS42MDkzNzUgLTAuNjI1LDIuNjU2MjUgLTAu +NjI1LDMuNzk2ODc1IDAsMC4yMDMxMjUgMCwxLjc1IDAuNTkzNzUsMS43NSAwLjI5Njg3NSwwIDAu +NTYyNSwtMC4yNjU2MjUgMC41NjI1LC0wLjUxNTYyNSAwLC0wLjA2MjUgMCwtMC4wOTM3NSAtMC4x +MDkzNzUsLTAuMzEyNSAtMC4zOTA2MjUsLTAuOTg0Mzc1IC0wLjM5MDYyNSwtMi4yMTg3NSAtMC4z +OTA2MjUsLTIuMzI4MTI1IDAsLTAuMDc4MTI1IDAsLTEuMDkzNzUgMC4zMTI1LC0yLjM5MDYyNSBo +IDEuNTkzNzUgYyAwLjE4NzUsMCAwLjY3MTg3NSwwIDAuNjcxODc1LC0wLjQ1MzEyNSBDIDcuOTM3 +NSwtNi4xODc1IDcuNjU2MjUsLTYuMTg3NSA3LjQwNjI1LC02LjE4NzUgSCAyLjY4NzUgYyAtMC4z +MjgxMjUsMCAtMC44MjgxMjUsMCAtMS40ODQzNzUsMC43MDMxMjUgLTAuMzc1LDAuNDIxODc1IC0w +LjgyODEyNSwxLjE4NzUgLTAuODI4MTI1LDEuMjY1NjI1IDAsMC4wOTM3NSAwLjA2MjUsMC4xMDkz +NzUgMC4xNTYyNSwwLjEwOTM3NSAwLjA5Mzc1LDAgMC4xMDkzNzUsLTAuMDMxMjUgMC4xODc1LC0w +LjEyNSAwLjc1LC0xLjE3MTg3NSAxLjQ4NDM3NSwtMS4xNzE4NzUgMS44NDM3NSwtMS4xNzE4NzUg +SCAzLjM5MDYyNSBDIDMuMDYyNSwtNC4zMjgxMjUgMi43MTg3NSwtMy4wNzgxMjUgMS41MzEyNSwt +MC41NzgxMjUgMS40MjE4NzUsLTAuMzQzNzUgMS40MjE4NzUsLTAuMzEyNSAxLjQyMTg3NSwtMC4y +MzQzNzUgYyAwLDAuMzEyNSAwLjI1LDAuMzc1IDAuMzkwNjI1LDAuMzc1IDAuNDA2MjUsMCAwLjUz +MTI1LC0wLjM3NSAwLjcwMzEyNSwtMC45Njg3NSAwLjIxODc1LC0wLjczNDM3NSAwLjIxODc1LC0w +Ljc2NTYyNSAwLjM3NSwtMS4zNDM3NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTQ1IiAv +PgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtm +aWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnNzgiPgogICAgICA8ZwogICAgICAgICBpZD0idXNl +NzYiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuNjc4OTk5OSw5LjgxMDAwMDQpIj4K +ICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBk +PSJtIDEuMzkwNjI1LC0wLjg0Mzc1IDEuMTU2MjUsLTEuMTI1IGMgMS43MDMxMjUsLTEuNSAyLjM0 +Mzc1LC0yLjA5Mzc1IDIuMzQzNzUsLTMuMTcxODc1IDAsLTEuMjUgLTAuOTY4NzUsLTIuMTI1IC0y +LjMxMjUsLTIuMTI1IC0xLjIxODc1LDAgLTIuMDMxMjUsMSAtMi4wMzEyNSwxLjk2ODc1IDAsMC42 +MjUgMC41NDY4NzUsMC42MjUgMC41NzgxMjUsMC42MjUgMC4xODc1LDAgMC41NjI1LC0wLjE0MDYy +NSAwLjU2MjUsLTAuNTc4MTI1IDAsLTAuMjk2ODc1IC0wLjE4NzUsLTAuNTc4MTI1IC0wLjU3ODEy +NSwtMC41NzgxMjUgLTAuMDc4MTI1LDAgLTAuMTA5Mzc1LDAgLTAuMTQwNjI1LDAuMDE1NjI1IDAu +MjUsLTAuNzAzMTI1IDAuODQzNzUsLTEuMTA5Mzc1IDEuNDY4NzUsLTEuMTA5Mzc1IDEsMCAxLjQ2 +ODc1LDAuODc1IDEuNDY4NzUsMS43ODEyNSAwLDAuODU5Mzc1IC0wLjU0Njg3NSwxLjczNDM3NSAt +MS4xNDA2MjUsMi40MDYyNSBsIC0yLjA5Mzc1LDIuMzI4MTI1IGMgLTAuMTI1LDAuMTI1IC0wLjEy +NSwwLjE0MDYyNSAtMC4xMjUsMC40MDYyNSBIIDQuNTkzNzUgTCA0Ljg5MDYyNSwtMS44OTA2MjUg +SCA0LjYyNSBDIDQuNTYyNSwtMS41NzgxMjUgNC41LC0xLjA5Mzc1IDQuMzkwNjI1LC0wLjkyMTg3 +NSA0LjMxMjUsLTAuODQzNzUgMy41OTM3NSwtMC44NDM3NSAzLjM0Mzc1LC0wLjg0Mzc1IFogbSAw +LDAiCiAgICAgICAgICAgaWQ9InBhdGgxNDkiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxw +YXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDow +LjU5ODtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0 +ZXJsaW1pdDoxMDtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAtNi44NzVlLTQsLTAuMDAx +NzE4NzUgSCAxNC40MzY4MTMiCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCgxLDAsMCwtMSwxLjE5 +NiwyMS4xMzUpIgogICAgICAgaWQ9InBhdGg4MCIgLz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmls +bDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9Imc4NCI+CiAgICAgIDxnCiAgICAg +ICAgIGlkPSJ1c2U4MiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNC45MDIsMzQuNTYy +KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAg +ICAgZD0ibSAxLjc2NTYyNSwtNC45ODQzNzUgYyAwLC0zLjY0MDYyNSAxLjc2NTYyNSwtNC4yMDMx +MjUgMi41MzEyNSwtNC4yMDMxMjUgMC41MTU2MjUsMCAxLjAzMTI1LDAuMTU2MjUgMS4zMTI1LDAu +NTc4MTI1IC0wLjE3MTg3NSwwIC0wLjcxODc1LDAgLTAuNzE4NzUsMC41OTM3NSAwLDAuMzEyNSAw +LjIxODc1LDAuNTc4MTI1IDAuNTkzNzUsMC41NzgxMjUgMC4zNTkzNzUsMCAwLjU5Mzc1LC0wLjIw +MzEyNSAwLjU5Mzc1LC0wLjYyNSAwLC0wLjc1IC0wLjU0Njg3NSwtMS40Njg3NSAtMS43OTY4NzUs +LTEuNDY4NzUgLTEuNzk2ODc1LDAgLTMuNjg3NSwxLjg0Mzc1IC0zLjY4NzUsNSAwLDMuOTM3NSAx +LjcxODc1LDQuODI4MTI1IDIuOTM3NSw0LjgyODEyNSAxLjU2MjUsMCAyLjg5MDYyNSwtMS4zNTkz +NzUgMi44OTA2MjUsLTMuMjE4NzUgMCwtMS45MDYyNSAtMS4zMjgxMjUsLTMuMTg3NSAtMi43NjU2 +MjUsLTMuMTg3NSAtMS4yODEyNSwwIC0xLjc1LDEuMTA5Mzc1IC0xLjg5MDYyNSwxLjUgeiBNIDMu +NTMxMjUsLTAuMDkzNzUgYyAtMC45MDYyNSwwIC0xLjM0Mzc1LC0wLjc5Njg3NSAtMS40Njg3NSwt +MS4wOTM3NSAtMC4xMjUsLTAuMzc1IC0wLjI2NTYyNSwtMS4wNzgxMjUgLTAuMjY1NjI1LC0yLjA3 +ODEyNSAwLC0xLjE0MDYyNSAwLjUxNTYyNSwtMi41NjI1IDEuNzk2ODc1LC0yLjU2MjUgMC43OTY4 +NzUsMCAxLjIxODc1LDAuNTMxMjUgMS40MjE4NzUsMS4wMTU2MjUgQyA1LjI1LC00LjI4MTI1IDUu +MjUsLTMuNTYyNSA1LjI1LC0yLjkzNzUgYyAwLDAuNzM0Mzc1IDAsMS4zNzUgLTAuMjY1NjI1LDEu +OTIxODc1IC0wLjM1OTM3NSwwLjY4NzUgLTAuODc1LDAuOTIxODc1IC0xLjQ1MzEyNSwwLjkyMTg3 +NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTUzIiAvPgogICAgICA8L2c+CiAgICA8L2c+ +CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAg +IGlkPSJnODgiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlODYiCiAgICAgICAgIHRyYW5zZm9y +bT0idHJhbnNsYXRlKDIwLjgxMiwyNC43MjEwMDEpIj4KICAgICAgICA8cGF0aAogICAgICAgICAg +IHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDkuNjg3NSwtNC42NDA2MjUgYyAw +LjIwMzEyNSwwIDAuNDUzMTI1LDAgMC40NTMxMjUsLTAuMjY1NjI1IDAsLTAuMjY1NjI1IC0wLjI1 +LC0wLjI2NTYyNSAtMC40NTMxMjUsLTAuMjY1NjI1IEggMS4yMzQzNzUgYyAtMC4yMDMxMjUsMCAt +MC40NTMxMjUsMCAtMC40NTMxMjUsMC4yNSAwLDAuMjgxMjUgMC4yMzQzNzUsMC4yODEyNSAwLjQ1 +MzEyNSwwLjI4MTI1IHogbSAwLDIuNjU2MjUgYyAwLjIwMzEyNSwwIDAuNDUzMTI1LDAgMC40NTMx +MjUsLTAuMjUgMCwtMC4yODEyNSAtMC4yNSwtMC4yODEyNSAtMC40NTMxMjUsLTAuMjgxMjUgSCAx +LjIzNDM3NSBjIC0wLjIwMzEyNSwwIC0wLjQ1MzEyNSwwIC0wLjQ1MzEyNSwwLjI2NTYyNSAwLDAu +MjY1NjI1IDAuMjM0Mzc1LDAuMjY1NjI1IDAuNDUzMTI1LDAuMjY1NjI1IHogbSAwLDAiCiAgICAg +ICAgICAgaWQ9InBhdGgxNTciIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBz +dHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9Imc5NiI+CiAgICAg +IDxnCiAgICAgICAgIGlkPSJ1c2U5MCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDAu +MTQ0OTM5LDI0LjcyMTAwMSkiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9r +ZTpub25lIgogICAgICAgICAgIGQ9Im0gMi40Njg3NSwtOS45NTMxMjUgLTIsMC4xNTYyNSBWIC05 +LjM3NSBjIDAuOTg0Mzc1LDAgMS4wOTM3NSwwLjA5Mzc1IDEuMDkzNzUsMC43OTY4NzUgViAtMS4w +NjI1IGMgMCwwLjY0MDYyNSAtMC4xNTYyNSwwLjY0MDYyNSAtMS4wOTM3NSwwLjY0MDYyNSBWIDAg +YyAwLjQwNjI1LC0wLjAzMTI1IDEuMTA5Mzc1LC0wLjAzMTI1IDEuNTQ2ODc1LC0wLjAzMTI1IDAu +NDIxODc1LDAgMS4xNDA2MjUsMCAxLjU0Njg3NSwwLjAzMTI1IHYgLTAuNDIxODc1IGMgLTAuOTIx +ODc1LDAgLTEuMDkzNzUsMCAtMS4wOTM3NSwtMC42NDA2MjUgeiBtIDAsMCIKICAgICAgICAgICBp +ZD0icGF0aDE2MSIgLz4KICAgICAgPC9nPgogICAgICA8ZwogICAgICAgICBpZD0idXNlOTIiCiAg +ICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ0LjA0NzEwOCwyNC43MjEwMDEpIj4KICAgICAg +ICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDIu +NSwtOC44MjgxMjUgYyAwLC0wLjM3NSAtMC4zMTI1LC0wLjcwMzEyNSAtMC43MDMxMjUsLTAuNzAz +MTI1IC0wLjM3NSwwIC0wLjY4NzUsMC4yOTY4NzUgLTAuNjg3NSwwLjY4NzUgMCwwLjQyMTg3NSAw +LjM0Mzc1LDAuNzAzMTI1IDAuNjg3NSwwLjcwMzEyNSAwLjQzNzUsMCAwLjcwMzEyNSwtMC4zNzUg +MC43MDMxMjUsLTAuNjg3NSB6IG0gLTEuOTg0Mzc1LDIuNjU2MjUgViAtNS43NSBjIDAuOTIxODc1 +LDAgMS4wNDY4NzUsMC4wNzgxMjUgMS4wNDY4NzUsMC43ODEyNSB2IDMuOTA2MjUgYyAwLDAuNjQw +NjI1IC0wLjE1NjI1LDAuNjQwNjI1IC0xLjA5Mzc1LDAuNjQwNjI1IFYgMCBDIDAuODc1LC0wLjAz +MTI1IDEuNTYyNSwtMC4wMzEyNSAxLjk4NDM3NSwtMC4wMzEyNSBjIDAuMTU2MjUsMCAwLjk4NDM3 +NSwwIDEuNDY4NzUsMC4wMzEyNSB2IC0wLjQyMTg3NSBjIC0wLjkyMTg3NSwwIC0wLjk4NDM3NSwt +MC4wNjI1IC0wLjk4NDM3NSwtMC42MjUgdiAtNS4yODEyNSB6IG0gMCwwIgogICAgICAgICAgIGlk +PSJwYXRoMTY1IiAvPgogICAgICA8L2c+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U5NCIKICAg +ICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDcuOTQ5MjcyLDI0LjcyMTAwMSkiPgogICAgICAg +IDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gMTAu +MjgxMjUsLTMuNDg0Mzc1IGMgMCwtMS4zMjgxMjUgMCwtMS43MzQzNzUgLTAuMzI4MTI1LC0yLjIw +MzEyNSBDIDkuNTMxMjUsLTYuMjM0Mzc1IDguODU5Mzc1LC02LjMyODEyNSA4LjM3NSwtNi4zMjgx +MjUgYyAtMS4xODc1LDAgLTEuNzk2ODc1LDAuODU5Mzc1IC0yLjAxNTYyNSwxLjQyMTg3NSBDIDYu +MTU2MjUsLTYuMDE1NjI1IDUuMzc1LC02LjMyODEyNSA0LjQ2ODc1LC02LjMyODEyNSBjIC0xLjM5 +MDYyNSwwIC0xLjkzNzUsMS4xODc1IC0yLjA0Njg3NSwxLjQ4NDM3NSBIIDIuNDA2MjUgdiAtMS40 +ODQzNzUgbCAtMS45NTMxMjUsMC4xNTYyNSBWIC01Ljc1IGMgMC45ODQzNzUsMCAxLjA5Mzc1LDAu +MDkzNzUgMS4wOTM3NSwwLjc5Njg3NSBWIC0xLjA2MjUgYyAwLDAuNjQwNjI1IC0wLjE1NjI1LDAu +NjQwNjI1IC0xLjA5Mzc1LDAuNjQwNjI1IFYgMCBjIDAuMzc1LC0wLjAzMTI1IDEuMTU2MjUsLTAu +MDMxMjUgMS41NjI1LC0wLjAzMTI1IDAuNDA2MjUsMCAxLjE4NzUsMCAxLjU2MjUsMC4wMzEyNSB2 +IC0wLjQyMTg3NSBjIC0wLjkyMTg3NSwwIC0xLjA5Mzc1LDAgLTEuMDkzNzUsLTAuNjQwNjI1IHYg +LTIuNjcxODc1IGMgMCwtMS41IDAuOTg0Mzc1LC0yLjI5Njg3NSAxLjg3NSwtMi4yOTY4NzUgMC44 +OTA2MjUsMCAxLjA5Mzc1LDAuNzE4NzUgMS4wOTM3NSwxLjU5Mzc1IHYgMy4zNzUgYyAwLDAuNjQw +NjI1IC0wLjE1NjI1LDAuNjQwNjI1IC0xLjA5Mzc1LDAuNjQwNjI1IFYgMCBjIDAuMzc1LC0wLjAz +MTI1IDEuMTU2MjUsLTAuMDMxMjUgMS41NDY4NzUsLTAuMDMxMjUgMC40MjE4NzUsMCAxLjE4NzUs +MCAxLjU2MjUsMC4wMzEyNSB2IC0wLjQyMTg3NSBjIC0wLjkwNjI1LDAgLTEuMDc4MTI1LDAgLTEu +MDc4MTI1LC0wLjY0MDYyNSB2IC0yLjY3MTg3NSBjIDAsLTEuNSAwLjk4NDM3NSwtMi4yOTY4NzUg +MS44NzUsLTIuMjk2ODc1IDAuODkwNjI1LDAgMS4wOTM3NSwwLjcxODc1IDEuMDkzNzUsMS41OTM3 +NSB2IDMuMzc1IGMgMCwwLjY0MDYyNSAtMC4xNzE4NzUsMC42NDA2MjUgLTEuMDkzNzUsMC42NDA2 +MjUgViAwIGMgMC4zNzUsLTAuMDMxMjUgMS4xNDA2MjUsLTAuMDMxMjUgMS41NDY4NzUsLTAuMDMx +MjUgMC40MjE4NzUsMCAxLjE4NzUsMCAxLjU2MjUsMC4wMzEyNSB2IC0wLjQyMTg3NSBjIC0wLjcx +ODc1LDAgLTEuMDc4MTI1LDAgLTEuMDkzNzUsLTAuNDIxODc1IHogbSAwLDAiCiAgICAgICAgICAg +aWQ9InBhdGgxNjkiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBzdHlsZT0i +ZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMDAiPgogICAgICA8Zwog +ICAgICAgICBpZD0idXNlOTgiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDM1LjcyMiwz +My42ODgpIj4KICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAg +ICAgICAgICBkPSJtIDAuOTUzMTI1LC0wLjY0MDYyNSBjIC0wLjAzMTI1LDAuMTU2MjUgLTAuMDkz +NzUsMC40MDYyNSAtMC4wOTM3NSwwLjQ2ODc1IDAsMC4xODc1IDAuMTU2MjUsMC4yOTY4NzUgMC4z +MTI1LDAuMjk2ODc1IEMgMS4zMTI1LDAuMTI1IDEuNSwwLjAzMTI1IDEuNTc4MTI1LC0wLjE4NzUg +MS41OTM3NSwtMC4yMDMxMjUgMS43MTg3NSwtMC43MTg3NSAxLjc4MTI1LC0xIGwgMC4yNSwtMC45 +Njg3NSBjIDAuMDYyNSwtMC4yNSAwLjEyNSwtMC40ODQzNzUgMC4xODc1LC0wLjczNDM3NSAwLjAz +MTI1LC0wLjE4NzUgMC4xMjUsLTAuNSAwLjE0MDYyNSwtMC41NDY4NzUgMC4xNTYyNSwtMC4zNDM3 +NSAwLjczNDM3NSwtMS4zMjgxMjUgMS43ODEyNSwtMS4zMjgxMjUgMC40ODQzNzUsMCAwLjU3ODEy +NSwwLjQwNjI1IDAuNTc4MTI1LDAuNzY1NjI1IDAsMC42NzE4NzUgLTAuNTMxMjUsMi4wNjI1IC0w +LjcwMzEyNSwyLjUzMTI1IC0wLjA5Mzc1LDAuMjUgLTAuMTA5Mzc1LDAuMzkwNjI1IC0wLjEwOTM3 +NSwwLjUgMCwwLjUxNTYyNSAwLjM3NSwwLjkwNjI1IDAuODkwNjI1LDAuOTA2MjUgMS4wMzEyNSww +IDEuNDM3NSwtMS41OTM3NSAxLjQzNzUsLTEuNjg3NSAwLC0wLjEwOTM3NSAtMC4xMDkzNzUsLTAu +MTA5Mzc1IC0wLjE0MDYyNSwtMC4xMDkzNzUgLTAuMTA5Mzc1LDAgLTAuMTA5Mzc1LDAuMDMxMjUg +LTAuMTU2MjUsMC4yMDMxMjUgQyA1LjcxODc1LC0wLjczNDM3NSA1LjM1OTM3NSwtMC4xMjUgNC44 +MjgxMjUsLTAuMTI1IDQuNjQwNjI1LC0wLjEyNSA0LjU2MjUsLTAuMjM0Mzc1IDQuNTYyNSwtMC40 +ODQzNzUgNC41NjI1LC0wLjc1IDQuNjU2MjUsLTEuMDE1NjI1IDQuNzUsLTEuMjUgYyAwLjIxODc1 +LC0wLjU3ODEyNSAwLjY3MTg3NSwtMS43ODEyNSAwLjY3MTg3NSwtMi40MDYyNSAwLC0wLjczNDM3 +NSAtMC40Njg3NSwtMS4xNzE4NzUgLTEuMjUsLTEuMTcxODc1IC0wLjk4NDM3NSwwIC0xLjUxNTYy +NSwwLjcwMzEyNSAtMS43MDMxMjUsMC45NTMxMjUgLTAuMDYyNSwtMC42MDkzNzUgLTAuNSwtMC45 +NTMxMjUgLTEsLTAuOTUzMTI1IC0wLjUxNTYyNSwwIC0wLjcxODc1LDAuNDM3NSAtMC44MjgxMjUs +MC42MjUgLTAuMTcxODc1LDAuMzc1IC0wLjMyODEyNSwxLjAxNTYyNSAtMC4zMjgxMjUsMS4wNjI1 +IDAsMC4xMDkzNzUgMC4xMDkzNzUsMC4xMDkzNzUgMC4xNDA2MjUsMC4xMDkzNzUgMC4xMDkzNzUs +MCAwLjEwOTM3NSwtMC4wMTU2MjUgMC4xNzE4NzUsLTAuMjUgMC4xODc1LC0wLjc4MTI1IDAuNDA2 +MjUsLTEuMjk2ODc1IDAuNzk2ODc1LC0xLjI5Njg3NSAwLjIxODc1LDAgMC4zNDM3NSwwLjE0MDYy +NSAwLjM0Mzc1LDAuNSAwLDAuMjM0Mzc1IC0wLjAzMTI1LDAuMzQzNzUgLTAuMTcxODc1LDAuOTIx +ODc1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGgxNzMiIC8+CiAgICAgIDwvZz4KICAgIDwv +Zz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAg +ICAgaWQ9ImcxMDYiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlMTAyIgogICAgICAgICB0cmFu +c2Zvcm09InRyYW5zbGF0ZSg0Mi4yNywzMy42ODgpIj4KICAgICAgICA8cGF0aAogICAgICAgICAg +IHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJNIDkuMDkzNzUsLTIuNTE1NjI1IEMg +OC41LC0yLjA0Njg3NSA4LjIwMzEyNSwtMS42MDkzNzUgOC4xMDkzNzUsLTEuNDY4NzUgNy42MjUs +LTAuNzAzMTI1IDcuNTMxMjUsLTAuMDE1NjI1IDcuNTMxMjUsLTAuMDE1NjI1IDcuNTMxMjUsMC4x +MjUgNy42NzE4NzUsMC4xMjUgNy43NSwwLjEyNSA3LjkzNzUsMC4xMjUgNy45NTMxMjUsMC4wOTM3 +NSA4LC0wLjA5Mzc1IDguMjUsLTEuMTcxODc1IDguODkwNjI1LC0yLjA3ODEyNSAxMC4xMjUsLTIu +NTc4MTI1IDEwLjI1LC0yLjYyNSAxMC4yODEyNSwtMi42NTYyNSAxMC4yODEyNSwtMi43MTg3NSBj +IDAsLTAuMDc4MTI1IC0wLjA2MjUsLTAuMTA5Mzc1IC0wLjA3ODEzLC0wLjEyNSBDIDkuNzE4NzQ1 +LC0zLjAzMTI1IDguMzkwNjIsLTMuNTc4MTI1IDcuOTg0MzcsLTUuNDA2MjUgNy45NTMxMjUsLTUu +NTQ2ODc1IDcuOTM3NSwtNS41NzgxMjUgNy43NSwtNS41NzgxMjUgYyAtMC4wNzgxMjUsMCAtMC4y +MTg3NSwwIC0wLjIxODc1LDAuMTQwNjI1IDAsMC4wMTU2MjUgMC4xMDkzNzUsMC43MDMxMjUgMC41 +NjI1LDEuNDM3NSAwLjIxODc1LDAuMzI4MTI1IDAuNTMxMjUsMC43MDMxMjUgMSwxLjA2MjUgSCAx +IGMgLTAuMjAzMTI1LDAgLTAuNDA2MjUsMCAtMC40MDYyNSwwLjIxODc1IDAsMC4yMDMxMjUgMC4y +MDMxMjUsMC4yMDMxMjUgMC40MDYyNSwwLjIwMzEyNSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJw +YXRoMTc3IiAvPgogICAgICA8L2c+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2UxMDQiCiAgICAg +ICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUzLjE3OTEsMzMuNjg4KSI+CiAgICAgICAgPHBhdGgK +ICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSA1LjU0Njg3NSwt +Mi45NTMxMjUgYyAtMC41OTM3NSwtMC43NSAtMC43MTg3NSwtMC45MDYyNSAtMS4wNjI1LC0xLjE4 +NzUgLTAuNjA5Mzc1LC0wLjQ4NDM3NSAtMS4yMTg3NSwtMC42ODc1IC0xLjc4MTI1LC0wLjY4NzUg +LTEuMjgxMjUsMCAtMi4xMDkzNzUsMS4yMDMxMjUgLTIuMTA5Mzc1LDIuNDg0Mzc1IDAsMS4yNSAw +LjgxMjUsMi40Njg3NSAyLjA2MjUsMi40Njg3NSAxLjI2NTYyNSwwIDIuMTcxODc1LC0xIDIuNzAz +MTI1LC0xLjg3NSAwLjU3ODEyNSwwLjc1IDAuNzE4NzUsMC45MDYyNSAxLjA0Njg3NSwxLjE4NzUg +MC42MjUsMC40ODQzNzUgMS4yMzQzNzUsMC42ODc1IDEuNzgxMjUsMC42ODc1IDEuMjgxMjUsMCAy +LjEwOTM3NSwtMS4yMDMxMjUgMi4xMDkzNzUsLTIuNDg0Mzc1IDAsLTEuMjUgLTAuODEyNSwtMi40 +Njg3NSAtMi4wNjI1LC0yLjQ2ODc1IC0xLjI1LDAgLTIuMTU2MjUsMSAtMi42ODc1LDEuODc1IHog +bSAwLjI4MTI1LDAuMzc1IGMgMC40Mzc1LC0wLjc5Njg3NSAxLjI1LC0xLjg5MDYyNSAyLjQ4NDM3 +NSwtMS44OTA2MjUgMS4xNTYyNSwwIDEuNzUsMS4xMjUgMS43NSwyLjEwOTM3NSAwLDEuMDc4MTI1 +IC0wLjczNDM3NSwxLjk1MzEyNSAtMS43MDMxMjUsMS45NTMxMjUgLTAuNjI1LDAgLTEuMTI1LC0w +LjQ1MzEyNSAtMS4zNDM3NSwtMC42ODc1IC0wLjI4MTI1LC0wLjI5Njg3NSAtMC41MzEyNSwtMC42 +MjUgLTEuMTg3NSwtMS40ODQzNzUgeiBtIC0wLjc1LDAuNDY4NzUgYyAtMC40NTMxMjUsMC43ODEy +NSAtMS4yNjU2MjUsMS44NzUgLTIuNSwxLjg3NSAtMS4xNTYyNSwwIC0xLjczNDM3NSwtMS4xMjUg +LTEuNzM0Mzc1LC0yLjEwOTM3NSAwLC0xLjA2MjUgMC43MzQzNzUsLTEuOTUzMTI1IDEuNjg3NSwt +MS45NTMxMjUgMC42MjUsMCAxLjEyNSwwLjQ1MzEyNSAxLjM0Mzc1LDAuNjg3NSAwLjI4MTI1LDAu +Mjk2ODc1IDAuNTMxMjUsMC42MjUgMS4yMDMxMjUsMS41IHogbSAwLDAiCiAgICAgICAgICAgaWQ9 +InBhdGgxODEiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmls +bDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMTAiPgogICAgICA8ZwogICAg +ICAgICBpZD0idXNlMTA4IgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3My45OTkwMDEs +Ni4xOTEpIj4KICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAg +ICAgICAgICBkPSJtIDAuOTUzMTI1LC0wLjY0MDYyNSBjIC0wLjAzMTI1LDAuMTU2MjUgLTAuMDkz +NzUsMC40MDYyNSAtMC4wOTM3NSwwLjQ2ODc1IDAsMC4xODc1IDAuMTU2MjUsMC4yOTY4NzUgMC4z +MTI1LDAuMjk2ODc1IEMgMS4zMTI1LDAuMTI1IDEuNSwwLjAzMTI1IDEuNTc4MTI1LC0wLjE4NzUg +MS41OTM3NSwtMC4yMDMxMjUgMS43MTg3NSwtMC43MTg3NSAxLjc4MTI1LC0xIGwgMC4yNSwtMC45 +Njg3NSBjIDAuMDYyNSwtMC4yNSAwLjEyNSwtMC40ODQzNzUgMC4xODc1LC0wLjczNDM3NSAwLjAz +MTI1LC0wLjE4NzUgMC4xMjUsLTAuNSAwLjE0MDYyNSwtMC41NDY4NzUgMC4xNTYyNSwtMC4zNDM3 +NSAwLjczNDM3NSwtMS4zMjgxMjUgMS43ODEyNSwtMS4zMjgxMjUgMC40ODQzNzUsMCAwLjU3ODEy +NSwwLjQwNjI1IDAuNTc4MTI1LDAuNzY1NjI1IDAsMC42NzE4NzUgLTAuNTMxMjUsMi4wNjI1IC0w +LjcwMzEyNSwyLjUzMTI1IC0wLjA5Mzc1LDAuMjUgLTAuMTA5Mzc1LDAuMzkwNjI1IC0wLjEwOTM3 +NSwwLjUgMCwwLjUxNTYyNSAwLjM3NSwwLjkwNjI1IDAuODkwNjI1LDAuOTA2MjUgMS4wMzEyNSww +IDEuNDM3NSwtMS41OTM3NSAxLjQzNzUsLTEuNjg3NSAwLC0wLjEwOTM3NSAtMC4xMDkzNzUsLTAu +MTA5Mzc1IC0wLjE0MDYyNSwtMC4xMDkzNzUgLTAuMTA5Mzc1LDAgLTAuMTA5Mzc1LDAuMDMxMjUg +LTAuMTU2MjUsMC4yMDMxMjUgQyA1LjcxODc1LC0wLjczNDM3NSA1LjM1OTM3NSwtMC4xMjUgNC44 +MjgxMjUsLTAuMTI1IDQuNjQwNjI1LC0wLjEyNSA0LjU2MjUsLTAuMjM0Mzc1IDQuNTYyNSwtMC40 +ODQzNzUgNC41NjI1LC0wLjc1IDQuNjU2MjUsLTEuMDE1NjI1IDQuNzUsLTEuMjUgYyAwLjIxODc1 +LC0wLjU3ODEyNSAwLjY3MTg3NSwtMS43ODEyNSAwLjY3MTg3NSwtMi40MDYyNSAwLC0wLjczNDM3 +NSAtMC40Njg3NSwtMS4xNzE4NzUgLTEuMjUsLTEuMTcxODc1IC0wLjk4NDM3NSwwIC0xLjUxNTYy +NSwwLjcwMzEyNSAtMS43MDMxMjUsMC45NTMxMjUgLTAuMDYyNSwtMC42MDkzNzUgLTAuNSwtMC45 +NTMxMjUgLTEsLTAuOTUzMTI1IC0wLjUxNTYyNSwwIC0wLjcxODc1LDAuNDM3NSAtMC44MjgxMjUs +MC42MjUgLTAuMTcxODc1LDAuMzc1IC0wLjMyODEyNSwxLjAxNTYyNSAtMC4zMjgxMjUsMS4wNjI1 +IDAsMC4xMDkzNzUgMC4xMDkzNzUsMC4xMDkzNzUgMC4xNDA2MjUsMC4xMDkzNzUgMC4xMDkzNzUs +MCAwLjEwOTM3NSwtMC4wMTU2MjUgMC4xNzE4NzUsLTAuMjUgMC4xODc1LC0wLjc4MTI1IDAuNDA2 +MjUsLTEuMjk2ODc1IDAuNzk2ODc1LC0xLjI5Njg3NSAwLjIxODc1LDAgMC4zNDM3NSwwLjE0MDYy +NSAwLjM0Mzc1LDAuNSAwLDAuMjM0Mzc1IC0wLjAzMTI1LDAuMzQzNzUgLTAuMTcxODc1LDAuOTIx +ODc1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGgxODUiIC8+CiAgICAgIDwvZz4KICAgIDwv +Zz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAg +ICAgaWQ9ImcxMTQiPgogICAgICA8ZwogICAgICAgICBpZD0idXNlMTEyIgogICAgICAgICB0cmFu +c2Zvcm09InRyYW5zbGF0ZSg2Ni40ODAwMDMsMTAuNjc0KSI+CiAgICAgICAgPHBhdGgKICAgICAg +ICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAxOC45MDYyNSwyMC45MDYy +NSAxLjgxMjUsLTQuNzgxMjUgaCAtMC4zNzUgYyAtMC41NzgxMjUsMS41NjI1IC0yLjE3MTg3NSwy +LjU3ODEyNSAtMy44NzUsMy4wMzEyNSAtMC4zMjgxMjUsMC4wNjI1IC0xLjc4MTI1LDAuNDUzMTI1 +IC00LjY1NjI1LDAuNDUzMTI1IGggLTkgTCAxMC40MDYyNSwxMC42ODc1IGMgMC4xMDkzNzUsLTAu +MTA5Mzc1IDAuMTQwNjI1LC0wLjE1NjI1IDAuMTQwNjI1LC0wLjIzNDM3NSAwLC0wLjAzMTI1IDAs +LTAuMDc4MTMgLTAuMTA5Mzc1LC0wLjIxODc1IEwgMy40ODQzNzUsMC43MTg3NSBoIDguMTg3NSBj +IDIsMCAzLjM1OTM3NSwwLjIwMzEyNSAzLjQ4NDM3NSwwLjIzNDM3NSAwLjgxMjUsMC4xMjUgMi4x +MDkzNzUsMC4zNzUgMy4yOTY4NzUsMS4xMjUgMC4zNzUsMC4yMzQzNzUgMS4zOTA2MjUsMC45MDYy +NSAxLjg5MDYyNSwyLjEyNSBoIDAuMzc1IEwgMTguOTA2MjUsMCBIIDEuMjUgQyAwLjkwNjI1LDAg +MC44OTA2MjUsMC4wMTU2MjUgMC44NDM3NSwwLjEwOTM3NSBjIDAsMC4wNDY4NzUgMCwwLjMyODEy +NSAwLDAuNDg0Mzc1IEwgOC43MzQzNzUsMTEuNDA2MjUgMSwyMC40ODQzNzUgYyAtMC4xNTYyNSww +LjE3MTg3NSAtMC4xNTYyNSwwLjI1IC0wLjE1NjI1LDAuMjY1NjI1IDAsMC4xNTYyNSAwLjE0MDYy +NSwwLjE1NjI1IDAuNDA2MjUsMC4xNTYyNSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTg5 +IiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAw +MDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTE4Ij4KICAgICAgPGcKICAgICAgICAgaWQ9 +InVzZTExNiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjcuMjkxLDQzLjE1NzAwMSki +PgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAg +IGQ9Im0gMy4xMjUsLTcuNDUzMTI1IGMgMCwwIDAsLTAuMTA5Mzc1IC0wLjE0MDYyNSwtMC4xMDkz +NzUgLTAuMjUsMCAtMS4wNDY4NzUsMC4wNzgxMjUgLTEuMzI4MTI1LDAuMTA5Mzc1IC0wLjA3ODEy +NSwwIC0wLjIwMzEyNSwwLjAxNTYyNSAtMC4yMDMxMjUsMC4yMTg3NSAwLDAuMTI1IDAuMDkzNzUs +MC4xMjUgMC4yNjU2MjUsMC4xMjUgMC41MTU2MjUsMCAwLjUzMTI1LDAuMDc4MTI1IDAuNTMxMjUs +MC4xODc1IGwgLTAuMDMxMjUsMC4yMTg3NSAtMS41NzgxMjUsNi4yODEyNSBDIDAuNTkzNzUsLTAu +MjY1NjI1IDAuNTkzNzUsLTAuMjUgMC41OTM3NSwtMC4xODc1IGMgMCwwLjI1IDAuMjE4NzUsMC4z +MTI1IDAuMzI4MTI1LDAuMzEyNSBDIDEuMDYyNSwwLjEyNSAxLjIxODc1LDAuMDE1NjI1IDEuMjgx +MjUsLTAuMTA5Mzc1IDEuMzQzNzUsLTAuMjAzMTI1IDEuODI4MTI1LC0yLjIxODc1IDEuODkwNjI1 +LC0yLjUgYyAwLjM3NSwwLjAzMTI1IDEuMjY1NjI1LDAuMjAzMTI1IDEuMjY1NjI1LDAuOTIxODc1 +IDAsMC4wNzgxMjUgMCwwLjEyNSAtMC4wMzEyNSwwLjIzNDM3NSAtMC4wMTU2MjUsMC4xNDA2MjUg +LTAuMDMxMjUsMC4yNjU2MjUgLTAuMDMxMjUsMC4zOTA2MjUgMCwwLjY0MDYyNSAwLjQyMTg3NSwx +LjA3ODEyNSAxLDEuMDc4MTI1IDAuMzI4MTI1LDAgMC42MjUsLTAuMTcxODc1IDAuODU5Mzc1LC0w +LjU3ODEyNSBDIDUuMjE4NzUsLTAuOTM3NSA1LjM0Mzc1LC0xLjUzMTI1IDUuMzQzNzUsLTEuNTYy +NSBjIDAsLTAuMTA5Mzc1IC0wLjA5Mzc1LC0wLjEwOTM3NSAtMC4xMjUsLTAuMTA5Mzc1IC0wLjEw +OTM3NSwwIC0wLjEyNSwwLjA0Njg3NSAtMC4xNTYyNSwwLjIwMzEyNSAtMC4yMTg3NSwwLjc5Njg3 +NSAtMC40Njg3NSwxLjM0Mzc1IC0wLjk1MzEyNSwxLjM0Mzc1IC0wLjIwMzEyNSwwIC0wLjM0Mzc1 +LC0wLjEwOTM3NSAtMC4zNDM3NSwtMC41IDAsLTAuMTg3NSAwLjA0Njg3NSwtMC40Mzc1IDAuMDc4 +MTI1LC0wLjYyNSAwLjA0Njg3NSwtMC4xNzE4NzUgMC4wNDY4NzUsLTAuMjE4NzUgMC4wNDY4NzUs +LTAuMzI4MTI1IDAsLTAuNzE4NzUgLTAuNjg3NSwtMS4wMzEyNSAtMS42MDkzNzUsLTEuMTQwNjI1 +IDAuMzQzNzUsLTAuMjAzMTI1IDAuNjg3NSwtMC41NDY4NzUgMC45Mzc1LC0wLjgxMjUgMC41MTU2 +MjUsLTAuNTc4MTI1IDEuMDMxMjUsLTEuMDQ2ODc1IDEuNTYyNSwtMS4wNDY4NzUgMC4wNjI1LDAg +MC4wNzgxMjUsMCAwLjA5Mzc1LDAuMDE1NjI1IEMgNSwtNC41NDY4NzUgNS4wMTU2MjUsLTQuNTQ2 +ODc1IDUuMTA5Mzc1LC00LjQ4NDM3NSA1LjEyNSwtNC40Njg3NSA1LjEyNSwtNC40NTMxMjUgNS4x +NDA2MjUsLTQuNDM3NSA0LjYyNSwtNC40MDYyNSA0LjUzMTI1LC0zLjk4NDM3NSA0LjUzMTI1LC0z +Ljg0Mzc1IGMgMCwwLjE3MTg3NSAwLjEwOTM3NSwwLjM3NSAwLjQwNjI1LDAuMzc1IDAuMjgxMjUs +MCAwLjYwOTM3NSwtMC4yMzQzNzUgMC42MDkzNzUsLTAuNjcxODc1IDAsLTAuMzEyNSAtMC4yNSwt +MC42ODc1IC0wLjc1LC0wLjY4NzUgLTAuMjk2ODc1LDAgLTAuODEyNSwwLjA5Mzc1IC0xLjU5Mzc1 +LDAuOTY4NzUgQyAyLjgyODEyNSwtMy40NTMxMjUgMi40MDYyNSwtMy4wMTU2MjUgMiwtMi44NDM3 +NSBaIG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTkzIiAvPgogICAgICA8L2c+CiAgICA8L2c+ +CiAgICA8ZwogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAg +IGlkPSJnMTI0Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTEyMCIKICAgICAgICAgdHJhbnNm +b3JtPSJ0cmFuc2xhdGUoNzMuMzE0MDAzLDQzLjE1NzAwMSkiPgogICAgICAgIDxwYXRoCiAgICAg +ICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gNy41LC0zLjU2MjUgYyAw +LjE1NjI1LDAgMC4zNTkzNzUsMCAwLjM1OTM3NSwtMC4yMTg3NSBDIDcuODU5Mzc1LC00IDcuNjU2 +MjUsLTQgNy41LC00IEggMC45Njg3NSBjIC0wLjE1NjI1LDAgLTAuMzU5Mzc1LDAgLTAuMzU5Mzc1 +LDAuMjE4NzUgMCwwLjIxODc1IDAuMjAzMTI1LDAuMjE4NzUgMC4zNzUsMC4yMTg3NSB6IG0gMCwy +LjEwOTM3NSBjIDAuMTU2MjUsMCAwLjM1OTM3NSwwIDAuMzU5Mzc1LC0wLjIxODc1IDAsLTAuMjE4 +NzUgLTAuMjAzMTI1LC0wLjIxODc1IC0wLjM1OTM3NSwtMC4yMTg3NSBIIDAuOTg0Mzc1IGMgLTAu +MTcxODc1LDAgLTAuMzc1LDAgLTAuMzc1LDAuMjE4NzUgMCwwLjIxODc1IDAuMjAzMTI1LDAuMjE4 +NzUgMC4zNTkzNzUsMC4yMTg3NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTk3IiAvPgog +ICAgICA8L2c+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2UxMjIiCiAgICAgICAgIHRyYW5zZm9y +bT0idHJhbnNsYXRlKDgxLjc5OTA5NSw0My4xNTcwMDEpIj4KICAgICAgICA8cGF0aAogICAgICAg +ICAgIHN0eWxlPSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDMuMjAzMTI1LC02Ljk4NDM3 +NSBjIDAsLTAuMjUgMCwtMC4yODEyNSAtMC4yNSwtMC4yODEyNSBDIDIuMjgxMjUsLTYuNTYyNSAx +LjMxMjUsLTYuNTYyNSAwLjk2ODc1LC02LjU2MjUgdiAwLjMyODEyNSBjIDAuMjE4NzUsMCAwLjg1 +OTM3NSwwIDEuNDM3NSwtMC4yODEyNSB2IDUuNjU2MjUgYyAwLDAuMzkwNjI1IC0wLjA0Njg3NSww +LjUxNTYyNSAtMS4wMTU2MjUsMC41MTU2MjUgSCAxLjAzMTI1IFYgMCBjIDAuMzkwNjI1LC0wLjAz +MTI1IDEuMzI4MTI1LC0wLjAzMTI1IDEuNzY1NjI1LC0wLjAzMTI1IDAuNDM3NSwwIDEuMzkwNjI1 +LDAgMS43NjU2MjUsMC4wMzEyNSBWIC0wLjM0Mzc1IEggNC4yMTg3NSBjIC0wLjk4NDM3NSwwIC0x +LjAxNTYyNSwtMC4xMDkzNzUgLTEuMDE1NjI1LC0wLjUxNTYyNSB6IG0gMCwwIgogICAgICAgICAg +IGlkPSJwYXRoMjAxIiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZwogICAgICAgc3R5bGU9 +ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTI4Ij4KICAgICAgPGcK +ICAgICAgICAgaWQ9InVzZTEyNiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTUuMDEw +MDAyLDE1LjAxNikiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25l +IgogICAgICAgICAgIGQ9Im0gNC4xMjUsLTkuMTg3NSBjIDAsLTAuMzQzNzUgMCwtMC4zNDM3NSAt +MC4yODEyNSwtMC4zNDM3NSBDIDMuNSwtOS4xNTYyNSAyLjc4MTI1LC04LjYyNSAxLjMxMjUsLTgu +NjI1IHYgMC40MjE4NzUgYyAwLjMyODEyNSwwIDEuMDQ2ODc1LDAgMS44MjgxMjUsLTAuMzc1IHYg +Ny40Njg3NSBjIDAsMC41MTU2MjUgLTAuMDQ2ODc1LDAuNjg3NSAtMS4yOTY4NzUsMC42ODc1IEgg +MS4zOTA2MjUgViAwIGMgMC4zOTA2MjUsLTAuMDMxMjUgMS43ODEyNSwtMC4wMzEyNSAyLjI1LC0w +LjAzMTI1IDAuNDY4NzUsMCAxLjg1OTM3NSwwIDIuMjM0Mzc1LDAuMDMxMjUgViAtMC40MjE4NzUg +SCA1LjQzNzUgYyAtMS4yNjU2MjUsMCAtMS4zMTI1LC0wLjE3MTg3NSAtMS4zMTI1LC0wLjY4NzUg +eiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDIwNSIgLz4KICAgICAgPC9nPgogICAgPC9nPgog +ICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdp +ZHRoOjAuNTk4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9r +ZS1taXRlcmxpbWl0OjEwO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDMuNDM3NWUtNCwt +MC4wMDE3MTg3NSBIIDEzLjczODYyNSIKICAgICAgIHRyYW5zZm9ybT0ibWF0cml4KDEsMCwwLC0x +LDkxLjY1MiwyMS4xMzUpIgogICAgICAgaWQ9InBhdGgxMzAiIC8+CiAgICA8ZwogICAgICAgc3R5 +bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnMTM0Ij4KICAgICAg +PGcKICAgICAgICAgaWQ9InVzZTEzMiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTEu +NjUyLDM0LjU2MikiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25l +IgogICAgICAgICAgIGQ9Im0gNC4wMzEyNSwtOS41OTM3NSBjIDAuMDE1NjI1LC0wLjA2MjUgMC4w +NDY4NzUsLTAuMTQwNjI1IDAuMDQ2ODc1LC0wLjIxODc1IDAsLTAuMTQwNjI1IC0wLjE0MDYyNSwt +MC4xNDA2MjUgLTAuMTcxODc1LC0wLjE0MDYyNSAtMC4wMTU2MjUsMCAtMC41MzEyNSwwLjA0Njg3 +NSAtMC43OTY4NzUsMC4wNjI1IEMgMi44NzUsLTkuODc1IDIuNjU2MjUsLTkuODQzNzUgMi4zOTA2 +MjUsLTkuODI4MTI1IGMgLTAuMzQzNzUsMC4wMzEyNSAtMC40Mzc1LDAuMDQ2ODc1IC0wLjQzNzUs +MC4yOTY4NzUgMCwwLjE1NjI1IDAuMTQwNjI1LDAuMTU2MjUgMC4yODEyNSwwLjE1NjI1IDAuNzM0 +Mzc1LDAgMC43MzQzNzUsMC4xMjUgMC43MzQzNzUsMC4yNjU2MjUgMCwwLjA2MjUgMCwwLjA5Mzc1 +IC0wLjA3ODEyNSwwLjM0Mzc1IEwgMC44NDM3NSwtMC41NjI1IGMgLTAuMDYyNSwwLjIxODc1IC0w +LjA2MjUsMC4yNSAtMC4wNjI1LDAuMzI4MTI1IDAsMC4zMjgxMjUgMC4yNSwwLjM3NSAwLjM5MDYy +NSwwLjM3NSAwLjQwNjI1LDAgMC40ODQzNzUsLTAuMzEyNSAwLjYwOTM3NSwtMC43NSBsIDAuNjcx +ODc1LC0yLjY4NzUgYyAxLjAzMTI1LDAuMTA5Mzc1IDEuNjU2MjUsMC41NDY4NzUgMS42NTYyNSwx +LjIzNDM3NSAwLDAuMDc4MTI1IDAsMC4xNDA2MjUgLTAuMDQ2ODc1LDAuMzU5Mzc1IEMgNCwtMS40 +ODQzNzUgNCwtMS4zMTI1IDQsLTEuMjUgYyAwLDAuODI4MTI1IDAuNTQ2ODc1LDEuMzkwNjI1IDEu +MjgxMjUsMS4zOTA2MjUgMC42NTYyNSwwIDEsLTAuNTkzNzUgMS4xMDkzNzUsLTAuNzk2ODc1IDAu +MzEyNSwtMC41MzEyNSAwLjUsLTEuMzQzNzUgMC41LC0xLjM5MDYyNSAwLC0wLjA3ODEyNSAtMC4w +NjI1LC0wLjE0MDYyNSAtMC4xNTYyNSwtMC4xNDA2MjUgLTAuMTI1LDAgLTAuMTQwNjI1LDAuMDYy +NSAtMC4xODc1LDAuMjk2ODc1IC0wLjIwMzEyNSwwLjc1IC0wLjUxNTYyNSwxLjc1IC0xLjIzNDM3 +NSwxLjc1IC0wLjI5Njg3NSwwIC0wLjQ4NDM3NSwtMC4xNDA2MjUgLTAuNDg0Mzc1LC0wLjY4NzUg +MCwtMC4yODEyNSAwLjA2MjUsLTAuNTkzNzUgMC4xMjUsLTAuODEyNSBDIDUsLTEuODkwNjI1IDUs +LTEuOTA2MjUgNSwtMi4wNzgxMjUgYyAwLC0wLjg0Mzc1IC0wLjc1LC0xLjMyODEyNSAtMi4wNzgx +MjUsLTEuNSAwLjUxNTYyNSwtMC4zMTI1IDEuMDMxMjUsLTAuODc1IDEuMjM0Mzc1LC0xLjA3ODEy +NSAwLjgyODEyNSwtMC45MjE4NzUgMS4zNzUsLTEuMzc1IDIuMDQ2ODc1LC0xLjM3NSAwLjMyODEy +NSwwIDAuNDA2MjUsMC4wNzgxMjUgMC41MTU2MjUsMC4xNzE4NzUgQyA2LjE4NzUsLTUuODEyNSA1 +Ljk4NDM3NSwtNS40Mzc1IDUuOTg0Mzc1LC01LjE1NjI1IGMgMCwwLjM0Mzc1IDAuMjY1NjI1LDAu +NDY4NzUgMC40Njg3NSwwLjQ2ODc1IDAuMzkwNjI1LDAgMC43MzQzNzUsLTAuMzI4MTI1IDAuNzM0 +Mzc1LC0wLjc5Njg3NSAwLC0wLjQwNjI1IC0wLjMyODEyNSwtMC44NDM3NSAtMC45ODQzNzUsLTAu +ODQzNzUgLTAuNzgxMjUsMCAtMS40MjE4NzUsMC41NjI1IC0yLjQzNzUsMS43MDMxMjUgLTAuMTU2 +MjUsMC4xNzE4NzUgLTAuNjg3NSwwLjcxODc1IC0xLjIxODc1LDAuOTIxODc1IHogbSAwLDAiCiAg +ICAgICAgICAgaWQ9InBhdGgyMDkiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAg +ICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9ImcxMzgiPgog +ICAgICA8ZwogICAgICAgICBpZD0idXNlMTM2IgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0 +ZSg5OS40MzkwMDMsMzAuNDE3OTk5KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0i +c3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAxLjM5MDYyNSwtMC44NDM3NSAxLjE1NjI1LC0x +LjEyNSBjIDEuNzAzMTI1LC0xLjUgMi4zNDM3NSwtMi4wOTM3NSAyLjM0Mzc1LC0zLjE3MTg3NSAw +LC0xLjI1IC0wLjk2ODc1LC0yLjEyNSAtMi4zMTI1LC0yLjEyNSAtMS4yMTg3NSwwIC0yLjAzMTI1 +LDEgLTIuMDMxMjUsMS45Njg3NSAwLDAuNjI1IDAuNTQ2ODc1LDAuNjI1IDAuNTc4MTI1LDAuNjI1 +IDAuMTg3NSwwIDAuNTYyNSwtMC4xNDA2MjUgMC41NjI1LC0wLjU3ODEyNSAwLC0wLjI5Njg3NSAt +MC4xODc1LC0wLjU3ODEyNSAtMC41NzgxMjUsLTAuNTc4MTI1IC0wLjA3ODEyNSwwIC0wLjEwOTM3 +NSwwIC0wLjE0MDYyNSwwLjAxNTYyNSAwLjI1LC0wLjcwMzEyNSAwLjg0Mzc1LC0xLjEwOTM3NSAx +LjQ2ODc1LC0xLjEwOTM3NSAxLDAgMS40Njg3NSwwLjg3NSAxLjQ2ODc1LDEuNzgxMjUgMCwwLjg1 +OTM3NSAtMC41NDY4NzUsMS43MzQzNzUgLTEuMTQwNjI1LDIuNDA2MjUgbCAtMi4wOTM3NSwyLjMy +ODEyNSBjIC0wLjEyNSwwLjEyNSAtMC4xMjUsMC4xNDA2MjUgLTAuMTI1LDAuNDA2MjUgSCA0LjU5 +Mzc1IEwgNC44OTA2MjUsLTEuODkwNjI1IEggNC42MjUgQyA0LjU2MjUsLTEuNTc4MTI1IDQuNSwt +MS4wOTM3NSA0LjM5MDYyNSwtMC45MjE4NzUgNC4zMTI1LC0wLjg0Mzc1IDMuNTkzNzUsLTAuODQz +NzUgMy4zNDM3NSwtMC44NDM3NSBaIG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMjEzIiAvPgog +ICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/7e16d346b278485f0e308b7c8eda301d.msg b/share/extensions/tests/data/cmd/inkscape/7e16d346b278485f0e308b7c8eda301d.msg new file mode 100644 index 0000000..3e6bff1 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/7e16d346b278485f0e308b7c8eda301d.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:0:47:49 --export-filename=guides_0.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_0.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_0.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/7f8bea1476711ae5f57b9d30111ec50b.msg b/share/extensions/tests/data/cmd/inkscape/7f8bea1476711ae5f57b9d30111ec50b.msg new file mode 100644 index 0000000..952ed60 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/7f8bea1476711ae5f57b9d30111ec50b.msg @@ -0,0 +1,94 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area-page --export-background-opacity=0 --export-dpi=96 --export-filename=Slide3.png --export-id-only --export-id=webslicer-layer --export-type=png Slide3.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide3.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide3.png + +iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoCAYAAABNo9TkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAETtJREFUeJzt18FNwwAQAMFzsEQp +6YeKaDAtpAy+8HQByLp9zFSw350BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAACAfzi2AwAA6Pqd+ZyZj+0O4B7HzM92A5dzOwAAgLSvmXluRwC3 ++d4O4PLYDgAAAAAMOgAAACQYdAAAAAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAABBh0A +AAACDDoAAAAEGHQAAAAIMOgAAAAQYNABAAAgwKADAABAgEEHAACAAIMOAAAAAQYdAAAAAgw6AAAA +BBh0AAAACDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAAgACDDgAAAAEGHQAAAAIMOgAAAAQYdAAAAAgw +6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAABBh0AAAACDDoAAAAEGHQAAAAIMOgAAAAQYNAB +AAAgwKADAABAgEEHAACAAIMOAAAAAQYdAAAAAgw6AAAABBh0AAAACDDoAAAAEGDQAQAAIMCgAwAA +QIBBBwAAgACDDgAAAAEGHQAAAAIMOgAAAAQYdAAAAAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAA +gw4AAAABBh0AAAACDDoAAAAEGHQAAAAIMOgAAAAQYNABAAAgwKADAABAgEEHAACAAIMOAAAAAQYd +AAAAAgw6AAAABBh0AAAACDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAAgACDDgAAAAEGHQAAAAIMOgAA +AAQYdAAAAAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAABBh0AAAACDDoAAAAEGHQAAAAI +MOgAAAAQYNABAAAgwKADAABAgEEHAACAAIMOAAAAAQYdAAAAAgw6AAAABBh0AAAACDDoAAAAEGDQ +AQAAIMCgAwAAQIBBBwAAgACDDgAAAAEGHQAAAAIMOgAAAAQYdAAAAAgw6AAAABBg0AEAACDAoAMA +AECAQQcAAIAAgw4AAAABBh0AAAACDDoAAAAEGHQAAAAIMOgAAAAQYNABAAAgwKADAABAgEEHAACA +AIMOAAAAAQYdAAAAAgw6AAAABBh0AAAACDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAAgACDDgAAAAEG +HQAAAAIMOgAAAAQYdAAAAAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAABBh0AAAACDDoA +AAAEGHQAAAAIMOgAAAAQYNABAAAgwKADAABAgEEHAACAAIMOAAAAAQYdAAAAAgw6AAAABBh0AAAA +CDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAAgACDDgAAAAEGHQAAAAIMOgAAAAQYdAAAAAgw6AAAABBg +0AEAACDAoAMAAECAQQcAAIAAgw4AAAABBh0AAAACDDoAAAAEGHQAAAAIMOgAAAAQYNABAAAgwKAD +AABAgEEHAACAAIMOAAAAAQYdAAAAAgw6AAAABBh0AAAACDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAA +gACDDgAAAAEGHQAAAAIMOgAAAAQYdAAAAAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAAB +Bh0AAAACDDoAAAAEGHQAAAAIMOgAAAAQYNABAAAgwKADAABAgEEHAACAAIMOAAAAAQYdAAAAAgw6 +AAAABBh0AAAACDDoAAAAEGDQAQAAIMCgAwAAQIBBBwAAgACDDgAAAAEGHQAAAAIMOgAAAAQYdAAA +AAgw6AAAABBg0AEAACDAoAMAAECAQQcAAIAAgw4AAAAB53YAAABpr5l5b0cAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA +Hf4AWlAGPhJKDywAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/88e23ddddb7b44e469a8309d48b71594.msg b/share/extensions/tests/data/cmd/inkscape/88e23ddddb7b44e469a8309d48b71594.msg new file mode 100644 index 0000000..44d6dea --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/88e23ddddb7b44e469a8309d48b71594.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:951:47:1000 --export-filename=f6oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f6oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f6oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/8d81a6ce40b41366bc5784c8b8e3f3e3.msg b/share/extensions/tests/data/cmd/inkscape/8d81a6ce40b41366bc5784c8b8e3f3e3.msg new file mode 100644 index 0000000..01c4c8b --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/8d81a6ce40b41366bc5784c8b8e3f3e3.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:0:953:49 --export-filename=f1oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f1oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f1oo.png + +iVBORw0KGgoAAAANSUhEUgAAA4oAAAAxCAYAAACcaFfTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAMNJREFUeJztwTEBAAAAwqD1T20M +H6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAATga19wABjrwhtgAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/9216316249e241e47bf118e187386687.msg b/share/extensions/tests/data/cmd/inkscape/9216316249e241e47bf118e187386687.msg new file mode 100644 index 0000000..922496e --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/9216316249e241e47bf118e187386687.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:0:953:49 --export-filename=guides_1.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_1.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_1.png + +iVBORw0KGgoAAAANSUhEUgAAA4oAAAAxCAYAAACcaFfTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAMNJREFUeJztwTEBAAAAwqD1T20M +H6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAATga19wABjrwhtgAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/925a03cfc32f34622997616ca335c846.msg b/share/extensions/tests/data/cmd/inkscape/925a03cfc32f34622997616ca335c846.msg new file mode 100644 index 0000000..746e966 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/925a03cfc32f34622997616ca335c846.msg @@ -0,0 +1,234 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=select-all;page-fit-to-selection;clone-unlink-recursively;vacuum-defs --export-filename=output.svg --export-type=svg --pdf-page=1 --pdf-poppler input.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgd2lkdGg9IjMzLjYxNjM5cHQiCiAgIGhlaWdodD0iMjYuMDg1MjUxcHQiCiAgIHZpZXdC +b3g9IjAgMCAzMy42MTYzOSAyNi4wODUyNTEiCiAgIHZlcnNpb249IjEuMiIKICAgaWQ9InN2Zzcz +IgogICBzb2RpcG9kaTpkb2NuYW1lPSJpbnB1dC5wZGYiCiAgIHhtbG5zOmlua3NjYXBlPSJodHRw +Oi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICB4bWxuczpzb2RpcG9k +aT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiCiAg +IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c3ZnPSJodHRwOi8v +d3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJuYW1l +ZHZpZXc3NSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiMwMDAw +MDAiCiAgICAgYm9yZGVyb3BhY2l0eT0iMC4yNSIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIy +IgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZWNoZWNr +ZXJib2FyZD0iMCIKICAgICBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiCiAgICAgaW5rc2Nh +cGU6ZG9jdW1lbnQtdW5pdHM9InB0IiAvPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMzNCIgLz4KICA8 +ZwogICAgIGlkPSJzdXJmYWNlMSIKICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC4yNjI4NzUs +LTEuMDkzNzUpIj4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0 +eToxIgogICAgICAgaWQ9ImczOCI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2UzNiIKICAgICAg +ICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCw2LjYyNSkiPgogICAgICAgIDxwYXRoCiAgICAgICAg +ICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Ik0gMy4xMjUsLTMuMDMxMjUgQyAz +LjA0Njg3NSwtMy4xNzE4NzUgMi44MjgxMjUsLTMuNTE1NjI1IDIuMzI4MTI1LC0zLjUxNTYyNSBj +IC0wLjkzNzUsMCAtMS45ODQzNzUsMS4xMDkzNzUgLTEuOTg0Mzc1LDIuMjgxMjUgMCwwLjg0Mzc1 +IDAuNTMxMjUsMS4zMTI1IDEuMTQwNjI1LDEuMzEyNSAwLjUxNTYyNSwwIDAuOTUzMTI1LC0wLjQw +NjI1IDEuMDkzNzUsLTAuNTYyNSAwLjE0MDYyNSwwLjU0Njg3NSAwLjY4NzUsMC41NjI1IDAuNzgx +MjUsMC41NjI1IDAuMzc1LDAgMC41NDY4NzUsLTAuMjk2ODc1IDAuNjA5Mzc1LC0wLjQzNzUgQyA0 +LjE0MDYyNSwtMC42NDA2MjUgNC4yNSwtMS4xMDkzNzUgNC4yNSwtMS4xNDA2MjUgNC4yNSwtMS4x +ODc1IDQuMjE4NzUsLTEuMjUgNC4xMjUsLTEuMjUgYyAtMC4wOTM3NSwwIC0wLjEwOTM3NSwwLjA2 +MjUgLTAuMTcxODc1LDAuMjUgLTAuMTA5Mzc1LDAuNDM3NSAtMC4yNSwwLjg1OTM3NSAtMC41NjI1 +LDAuODU5Mzc1IC0wLjE4NzUsMCAtMC4yNjU2MjUsLTAuMTU2MjUgLTAuMjY1NjI1LC0wLjM3NSAw +LC0wLjE0MDYyNSAwLjA3ODEyNSwtMC40MDYyNSAwLjEyNSwtMC42MDkzNzUgMC4wNDY4NzUsLTAu +MjAzMTI1IDAuMTcxODc1LC0wLjY3MTg3NSAwLjIwMzEyNSwtMC44MTI1IGwgMC4xNTYyNSwtMC42 +MDkzNzUgYyAwLjA0Njg3NSwtMC4xODc1IDAuMTI1LC0wLjUzMTI1IDAuMTI1LC0wLjU2MjUgMCwt +MC4xODc1IC0wLjE1NjI1LC0wLjI1IC0wLjI1LC0wLjI1IC0wLjEyNSwwIC0wLjMyODEyNSwwLjA3 +ODEyNSAtMC4zNTkzNzUsMC4zMjgxMjUgeiBtIC0wLjU0Njg3NSwyLjE3MTg3NSBjIC0wLjM5MDYy +NSwwLjU0Njg3NSAtMC44MTI1LDAuNzE4NzUgLTEuMDYyNSwwLjcxODc1IC0wLjM3NSwwIC0wLjU0 +Njg3NSwtMC4zNDM3NSAtMC41NDY4NzUsLTAuNzUgMCwtMC4zNzUgMC4yMDMxMjUsLTEuMjM0Mzc1 +IDAuMzkwNjI1LC0xLjU3ODEyNSAwLjIxODc1LC0wLjQ4NDM3NSAwLjYwOTM3NSwtMC44MjgxMjUg +MC45ODQzNzUsLTAuODI4MTI1IDAuNTE1NjI1LDAgMC42NzE4NzUsMC41OTM3NSAwLjY3MTg3NSww +LjY4NzUgMCwwLjAzMTI1IC0wLjIwMzEyNSwwLjgxMjUgLTAuMjUsMS4wMTU2MjUgLTAuMTA5Mzc1 +LDAuMzc1IC0wLjEwOTM3NSwwLjM5MDYyNSAtMC4xODc1LDAuNzM0Mzc1IHogbSAwLDAiCiAgICAg +ICAgICAgaWQ9InBhdGg3NyIgLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcKICAgICAgIHN0 +eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpZD0iZzQyIj4KICAgICAg +PGcKICAgICAgICAgaWQ9InVzZTQwIgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNS4w +OTA1ODcsNi42MjUpIj4KICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxlPSJzdHJva2U6bm9u +ZSIKICAgICAgICAgICBkPSJtIDEuOTM3NSwtNS4yOTY4NzUgYyAwLjAxNTYyNSwtMC4wMTU2MjUg +MC4wMzEyNSwtMC4xMDkzNzUgMC4wMzEyNSwtMC4xMjUgMCwtMC4wMzEyNSAtMC4wMzEyNSwtMC4x +MDkzNzUgLTAuMTI1LC0wLjEwOTM3NSAtMC4wMzEyNSwwIC0wLjI4MTI1LDAuMDMxMjUgLTAuNDUz +MTI1LDAuMDQ2ODc1IEwgMC45Mzc1LC01LjQ1MzEyNSBjIC0wLjE3MTg3NSwwLjAxNTYyNSAtMC4y +NSwwLjAxNTYyNSAtMC4yNSwwLjE1NjI1IDAsMC4xMjUgMC4xMDkzNzUsMC4xMjUgMC4yMDMxMjUs +MC4xMjUgMC4zOTA2MjUsMCAwLjM5MDYyNSwwLjA0Njg3NSAwLjM5MDYyNSwwLjEwOTM3NSAwLDAu +MDQ2ODc1IC0wLjA5Mzc1LDAuMzc1IC0wLjE0MDYyNSwwLjU0Njg3NSBsIC0wLjY4NzUsMi43ODEy +NSBjIC0wLjA2MjUsMC4yNjU2MjUgLTAuMDYyNSwwLjM5MDYyNSAtMC4wNjI1LDAuNTE1NjI1IDAs +MC44MjgxMjUgMC41LDEuMjk2ODc1IDEuMTA5Mzc1LDEuMjk2ODc1IDAuOTg0Mzc1LDAgMiwtMS4x +MjUgMiwtMi4yODEyNSBDIDMuNSwtMyAzLC0zLjUxNTYyNSAyLjM1OTM3NSwtMy41MTU2MjUgYyAt +MC40NTMxMjUsMCAtMC43OTY4NzUsMC4yODEyNSAtMC45Njg3NSwwLjQzNzUgeiBNIDEuNSwtMC4x +NDA2MjUgYyAtMC4yODEyNSwwIC0wLjU2MjUsLTAuMjE4NzUgLTAuNTYyNSwtMC44MTI1IDAsLTAu +MjAzMTI1IDAuMDMxMjUsLTAuNDA2MjUgMC4xMjUsLTAuNzk2ODc1IEMgMS4xMDkzNzUsLTEuOTY4 +NzUgMS4xNzE4NzUsLTIuMjAzMTI1IDEuMjM0Mzc1LC0yLjQzNzUgMS4yODEyNSwtMi41NzgxMjUg +MS4yODEyNSwtMi41OTM3NSAxLjM3NSwtMi43MDMxMjUgMS42NDA2MjUsLTMuMDQ2ODc1IDIsLTMu +Mjk2ODc1IDIuMzI4MTI1LC0zLjI5Njg3NSBjIDAuNDA2MjUsMCAwLjU2MjUsMC4zOTA2MjUgMC41 +NjI1LDAuNzUgMCwwLjI5Njg3NSAtMC4xODc1LDEuMTU2MjUgLTAuNDIxODc1LDEuNjI1IEMgMi4y +NjU2MjUsLTAuNSAxLjg3NSwtMC4xNDA2MjUgMS41LC0wLjE0MDYyNSBaIG0gMCwwIgogICAgICAg +ICAgIGlkPSJwYXRoODEiIC8+CiAgICAgIDwvZz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBzdHls +ZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaWQ9Imc0NiI+CiAgICAgIDxn +CiAgICAgICAgIGlkPSJ1c2U0NCIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjkuOTQy +ODY5LDYuNjI1KSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUi +CiAgICAgICAgICAgZD0ibSAzLjI2NTYyNSwtMy4wNDY4NzUgYyAtMC4zMjgxMjUsMC4wMzEyNSAt +MC40Mzc1LDAuMjgxMjUgLTAuNDM3NSwwLjQzNzUgMCwwLjIzNDM3NSAwLjIwMzEyNSwwLjI5Njg3 +NSAwLjMxMjUsMC4yOTY4NzUgMC4wMzEyNSwwIDAuNDM3NSwtMC4wMzEyNSAwLjQzNzUsLTAuNTE1 +NjI1IDAsLTAuNDg0Mzc1IC0wLjUxNTYyNSwtMC42ODc1IC0xLC0wLjY4NzUgLTEuMTI1LDAgLTIu +MjM0Mzc1LDEuMDkzNzUgLTIuMjM0Mzc1LDIuMjE4NzUgMCwwLjc1IDAuNTMxMjUsMS4zNzUgMS40 +MDYyNSwxLjM3NSAxLjI2NTYyNSwwIDEuOTIxODc1LC0wLjc5Njg3NSAxLjkyMTg3NSwtMC45MDYy +NSAwLC0wLjA3ODEyNSAtMC4wNzgxMjUsLTAuMTI1IC0wLjEyNSwtMC4xMjUgLTAuMDQ2ODc1LDAg +LTAuMDc4MTI1LDAuMDE1NjI1IC0wLjEwOTM3NSwwLjA2MjUgLTAuNjI1LDAuNzUgLTEuNTMxMjUs +MC43NSAtMS42NzE4NzUsMC43NSBDIDEuMzQzNzUsLTAuMTQwNjI1IDEsLTAuNDA2MjUgMSwtMS4w +MTU2MjUgYyAwLC0wLjM0Mzc1IDAuMTU2MjUsLTEuMTg3NSAwLjUzMTI1LC0xLjY4NzUgMC4zNDM3 +NSwtMC40Mzc1IDAuNzUsLTAuNTkzNzUgMS4wNjI1LC0wLjU5Mzc1IDAuMDkzNzUsMCAwLjQ1MzEy +NSwwLjAxNTYyNSAwLjY3MTg3NSwwLjI1IHogbSAwLDAiCiAgICAgICAgICAgaWQ9InBhdGg4NSIg +Lz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7 +ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpZD0iZzUwIj4KICAgICAgPGcKICAgICAgICAgaWQ9InVz +ZTQ4IgogICAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3LDE2LjA4OTAwMSkiPgogICAg +ICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0g +NC4yODEyNSwtNS4yOTY4NzUgYyAwLjAxNTYyNSwtMC4wMTU2MjUgMC4wMzEyNSwtMC4xMDkzNzUg +MC4wMzEyNSwtMC4xMjUgMCwtMC4wMzEyNSAtMC4wMzEyNSwtMC4xMDkzNzUgLTAuMTI1LC0wLjEw +OTM3NSAtMC4wMzEyNSwwIC0wLjI4MTI1LDAuMDMxMjUgLTAuNDUzMTI1LDAuMDQ2ODc1IGwgLTAu +NDUzMTI1LDAuMDMxMjUgYyAtMC4xNzE4NzUsMC4wMTU2MjUgLTAuMjUsMC4wMTU2MjUgLTAuMjUs +MC4xNTYyNSAwLDAuMTI1IDAuMTA5Mzc1LDAuMTI1IDAuMjAzMTI1LDAuMTI1IDAuMzkwNjI1LDAg +MC4zOTA2MjUsMC4wNDY4NzUgMC4zOTA2MjUsMC4xMDkzNzUgMCwwLjA0Njg3NSAtMC4wNzgxMjUs +MC4zMTI1IC0wLjEwOTM3NSwwLjQ2ODc1IEwgMy4xMjUsLTMuMDMxMjUgQyAzLjA0Njg3NSwtMy4x +NzE4NzUgMi44MjgxMjUsLTMuNTE1NjI1IDIuMzI4MTI1LC0zLjUxNTYyNSBjIC0wLjkzNzUsMCAt +MS45ODQzNzUsMS4xMDkzNzUgLTEuOTg0Mzc1LDIuMjgxMjUgMCwwLjg0Mzc1IDAuNTMxMjUsMS4z +MTI1IDEuMTQwNjI1LDEuMzEyNSAwLjUxNTYyNSwwIDAuOTUzMTI1LC0wLjQwNjI1IDEuMDkzNzUs +LTAuNTYyNSAwLjE0MDYyNSwwLjU0Njg3NSAwLjY4NzUsMC41NjI1IDAuNzgxMjUsMC41NjI1IDAu +Mzc1LDAgMC41NDY4NzUsLTAuMjk2ODc1IDAuNjA5Mzc1LC0wLjQzNzUgQyA0LjE0MDYyNSwtMC42 +NDA2MjUgNC4yNSwtMS4xMDkzNzUgNC4yNSwtMS4xNDA2MjUgNC4yNSwtMS4xODc1IDQuMjE4NzUs +LTEuMjUgNC4xMjUsLTEuMjUgYyAtMC4wOTM3NSwwIC0wLjEwOTM3NSwwLjA2MjUgLTAuMTcxODc1 +LDAuMjUgLTAuMTA5Mzc1LDAuNDM3NSAtMC4yNSwwLjg1OTM3NSAtMC41NjI1LDAuODU5Mzc1IC0w +LjE4NzUsMCAtMC4yNjU2MjUsLTAuMTU2MjUgLTAuMjY1NjI1LC0wLjM3NSAwLC0wLjE1NjI1IDAu +MDMxMjUsLTAuMjM0Mzc1IDAuMDQ2ODc1LC0wLjM0Mzc1IHogbSAtMS43MDMxMjUsNC40Mzc1IGMg +LTAuMzkwNjI1LDAuNTQ2ODc1IC0wLjgxMjUsMC43MTg3NSAtMS4wNjI1LDAuNzE4NzUgLTAuMzc1 +LDAgLTAuNTQ2ODc1LC0wLjM0Mzc1IC0wLjU0Njg3NSwtMC43NSAwLC0wLjM3NSAwLjIwMzEyNSwt +MS4yMzQzNzUgMC4zOTA2MjUsLTEuNTc4MTI1IDAuMjE4NzUsLTAuNDg0Mzc1IDAuNjA5Mzc1LC0w +LjgyODEyNSAwLjk4NDM3NSwtMC44MjgxMjUgMC41MTU2MjUsMCAwLjY3MTg3NSwwLjU5Mzc1IDAu +NjcxODc1LDAuNjg3NSAwLDAuMDMxMjUgLTAuMjAzMTI1LDAuODEyNSAtMC4yNSwxLjAxNTYyNSAt +MC4xMDkzNzUsMC4zNzUgLTAuMTA5Mzc1LDAuMzkwNjI1IC0wLjE4NzUsMC43MzQzNzUgeiBtIDAs +MCIKICAgICAgICAgICBpZD0icGF0aDg5IiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8Zwog +ICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnNTQi +PgogICAgICA8ZwogICAgICAgICBpZD0idXNlNTIiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNs +YXRlKDE0LjkzOTgxNiwxNi4wODkwMDEpIj4KICAgICAgICA8cGF0aAogICAgICAgICAgIHN0eWxl +PSJzdHJva2U6bm9uZSIKICAgICAgICAgICBkPSJtIDEuNjA5Mzc1LC0xLjgxMjUgYyAwLjE3MTg3 +NSwwIDAuNzY1NjI1LC0wLjAxNTYyNSAxLjE4NzUsLTAuMTU2MjUgMC42ODc1LC0wLjI1IDAuNzE4 +NzUsLTAuNzE4NzUgMC43MTg3NSwtMC44NDM3NSAwLC0wLjQ1MzEyNSAtMC40MjE4NzUsLTAuNzAz +MTI1IC0wLjkzNzUsLTAuNzAzMTI1IC0wLjkwNjI1LDAgLTIuMTg3NSwwLjcwMzEyNSAtMi4xODc1 +LDIuMTI1IDAsMC44MTI1IDAuNSwxLjQ2ODc1IDEuMzc1LDEuNDY4NzUgMS4yMzQzNzUsMCAxLjkw +NjI1LC0wLjc5Njg3NSAxLjkwNjI1LC0wLjkwNjI1IDAsLTAuMDc4MTI1IC0wLjA3ODEyNSwtMC4x +MjUgLTAuMTI1LC0wLjEyNSAtMC4wNDY4NzUsMCAtMC4wNzgxMjUsMC4wMTU2MjUgLTAuMTA5Mzc1 +LDAuMDYyNSAtMC42MjUsMC43NSAtMS41MzEyNSwwLjc1IC0xLjY1NjI1LDAuNzUgLTAuNTkzNzUs +MCAtMC43NjU2MjUsLTAuNSAtMC43NjU2MjUsLTAuOTM3NSAwLC0wLjI1IDAuMDc4MTI1LC0wLjYw +OTM3NSAwLjEwOTM3NSwtMC43MzQzNzUgeiBNIDEuMTg3NSwtMi4wNDY4NzUgYyAwLjI1LC0wLjk2 +ODc1IDAuOTg0Mzc1LC0xLjI1IDEuMzkwNjI1LC0xLjI1IDAuMzEyNSwwIDAuNjI1LDAuMTcxODc1 +IDAuNjI1LDAuNDg0Mzc1IDAsMC43NjU2MjUgLTEuMzEyNSwwLjc2NTYyNSAtMS42NTYyNSwwLjc2 +NTYyNSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoOTMiIC8+CiAgICAgIDwvZz4KICAgIDwv +Zz4KICAgIDxnCiAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxIgogICAg +ICAgaWQ9Imc1OCI+CiAgICAgIDxnCiAgICAgICAgIGlkPSJ1c2U1NiIKICAgICAgICAgdHJhbnNm +b3JtPSJ0cmFuc2xhdGUoMjkuMzAxMTQsMTYuMDg5MDAxKSI+CiAgICAgICAgPHBhdGgKICAgICAg +ICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAzLjA0Njg3NSwtMy4xNzE4 +NzUgaCAwLjc1IGMgMC4xNTYyNSwwIDAuMjUsMCAwLjI1LC0wLjE1NjI1IEMgNC4wNDY4NzUsLTMu +NDM3NSAzLjkzNzUsLTMuNDM3NSAzLjgxMjUsLTMuNDM3NSBIIDMuMDkzNzUgYyAwLjE0MDYyNSwt +MC43MTg3NSAwLjIxODc1LC0xLjE3MTg3NSAwLjI5Njg3NSwtMS41MzEyNSAwLjAzMTI1LC0wLjEy +NSAwLjA0Njg3NSwtMC4yMTg3NSAwLjE3MTg3NSwtMC4zMTI1IDAuMTA5Mzc1LC0wLjA5Mzc1IDAu +MTcxODc1LC0wLjEwOTM3NSAwLjI1LC0wLjEwOTM3NSAwLjEyNSwwIDAuMjUsMC4wMzEyNSAwLjM1 +OTM3NSwwLjA5Mzc1IC0wLjA0Njg3NSwwLjAxNTYyNSAtMC4wOTM3NSwwLjAzMTI1IC0wLjEyNSww +LjA2MjUgLTAuMTQwNjI1LDAuMDc4MTI1IC0wLjIzNDM3NSwwLjIxODc1IC0wLjIzNDM3NSwwLjM3 +NSAwLDAuMTg3NSAwLjE0MDYyNSwwLjI5Njg3NSAwLjMxMjUsMC4yOTY4NzUgMC4yMzQzNzUsMCAw +LjQ1MzEyNSwtMC4yMDMxMjUgMC40NTMxMjUsLTAuNDg0Mzc1IDAsLTAuMzc1IC0wLjM5MDYyNSwt +MC41NjI1IC0wLjc2NTYyNSwtMC41NjI1IC0wLjI4MTI1LDAgLTAuNzgxMjUsMC4xMjUgLTEuMDMx +MjUsMC44NTkzNzUgQyAyLjcwMzEyNSwtNC41NjI1IDIuNzAzMTI1LC00LjU0Njg3NSAyLjUsLTMu +NDM3NSBIIDEuODkwNjI1IGMgLTAuMTU2MjUsMCAtMC4yNSwwIC0wLjI1LDAuMTU2MjUgMCwwLjEw +OTM3NSAwLjEwOTM3NSwwLjEwOTM3NSAwLjIzNDM3NSwwLjEwOTM3NSBIIDIuNDUzMTI1IEwgMS44 +NzUsLTAuMDc4MTI1IEMgMS43MTg3NSwwLjcxODc1IDEuNjA5Mzc1LDEuNDA2MjUgMS4xNzE4NzUs +MS40MDYyNSBjIC0wLjAxNTYyNSwwIC0wLjE4NzUsMCAtMC4zMjgxMjUsLTAuMDkzNzUgMC4zNTkz +NzUsLTAuMDkzNzUgMC4zNTkzNzUsLTAuNDIxODc1IDAuMzU5Mzc1LC0wLjQzNzUgMCwtMC4xODc1 +IC0wLjE0MDYyNSwtMC4yOTY4NzUgLTAuMzEyNSwtMC4yOTY4NzUgLTAuMjE4NzUsMCAtMC40NTMx +MjUsMC4xODc1IC0wLjQ1MzEyNSwwLjQ4NDM3NSAwLDAuMzQzNzUgMC4zNDM3NSwwLjU2MjUgMC43 +MzQzNzUsMC41NjI1IDAuNSwwIDAuODI4MTI1LC0wLjUxNTYyNSAwLjkzNzUsLTAuNzAzMTI1IDAu +MjgxMjUsLTAuNTMxMjUgMC40Njg3NSwtMS41MzEyNSAwLjQ4NDM3NSwtMS42MDkzNzUgeiBtIDAs +MCIKICAgICAgICAgICBpZD0icGF0aDk3IiAvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8Zwog +ICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJnNjIi +PgogICAgICA8ZwogICAgICAgICBpZD0idXNlNjAiCiAgICAgICAgIHRyYW5zZm9ybT0idHJhbnNs +YXRlKDAuMDkxLDI1LjU1NDAwMSkiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgc3R5bGU9InN0 +cm9rZTpub25lIgogICAgICAgICAgIGQ9Im0gMy45NTMxMjUsLTIuOTM3NSBjIDAuMDMxMjUsLTAu +MTI1IDAuMDMxMjUsLTAuMTcxODc1IDAuMDMxMjUsLTAuMTcxODc1IDAsLTAuMTg3NSAtMC4xNTYy +NSwtMC4yNSAtMC4yNSwtMC4yNSAtMC4xODc1LDAgLTAuMzI4MTI1LDAuMTQwNjI1IC0wLjM1OTM3 +NSwwLjMxMjUgLTAuMDYyNSwtMC4xMjUgLTAuMzEyNSwtMC40Njg3NSAtMC43ODEyNSwtMC40Njg3 +NSAtMC45NTMxMjUsMCAtMS45ODQzNzUsMS4wNjI1IC0xLjk4NDM3NSwyLjIxODc1IEMgMC42MDkz +NzUsLTAuNDM3NSAxLjE3MTg3NSwwIDEuNzY1NjI1LDAgMi4xMjUsMCAyLjQ1MzEyNSwtMC4yMDMx +MjUgMi43MTg3NSwtMC40Mzc1IEwgMi41NDY4NzUsMC4yODEyNSBDIDIuNDUzMTI1LDAuNjI1IDIu +NDA2MjUsMC44NTkzNzUgMi4wOTM3NSwxLjEwOTM3NSAxLjc1LDEuNDA2MjUgMS40NTMxMjUsMS40 +MDYyNSAxLjI1LDEuNDA2MjUgYyAtMC4yMDMxMjUsMCAtMC4zOTA2MjUsLTAuMDE1NjI1IC0wLjU3 +ODEyNSwtMC4wNDY4NzUgMC4xNzE4NzUsLTAuMDkzNzUgMC4yNSwtMC4yNjU2MjUgMC4yNSwtMC40 +MDYyNSAwLC0wLjE4NzUgLTAuMTQwNjI1LC0wLjI5Njg3NSAtMC4zMTI1LC0wLjI5Njg3NSAtMC4x +ODc1LDAgLTAuNDM3NSwwLjE3MTg3NSAtMC40Mzc1LDAuNDg0Mzc1IDAsMC40NTMxMjUgMC42MDkz +NzUsMC40ODQzNzUgMS4wOTM3NSwwLjQ4NDM3NSAxLjE0MDYyNSwwIDEuNzAzMTI1LC0wLjYwOTM3 +NSAxLjgxMjUsLTEuMDkzNzUgeiBNIDIuODc1LC0xLjA0Njg3NSBjIC0wLjA0Njg3NSwwLjIxODc1 +IC0wLjIzNDM3NSwwLjM3NSAtMC4zOTA2MjUsMC41MzEyNSAtMC4wNzgxMjUsMC4wNDY4NzUgLTAu +Mzc1LDAuMjk2ODc1IC0wLjcwMzEyNSwwLjI5Njg3NSAtMC4zMjgxMjUsMCAtMC41NDY4NzUsLTAu +MjY1NjI1IC0wLjU0Njg3NSwtMC43NSAwLC0wLjMyODEyNSAwLjE4NzUsLTEuMjAzMTI1IDAuNDA2 +MjUsLTEuNjA5Mzc1IDAuMjUsLTAuNDUzMTI1IDAuNjI1LC0wLjcxODc1IDAuOTUzMTI1LC0wLjcx +ODc1IDAuNTMxMjUsMCAwLjY3MTg3NSwwLjU5Mzc1IDAuNjcxODc1LDAuNjcxODc1IEwgMy4yNSwt +Mi41MTU2MjUgWiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDEwMSIgLz4KICAgICAgPC9nPgog +ICAgPC9nPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEi +CiAgICAgICBpZD0iZzY2Ij4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTY0IgogICAgICAgICB0 +cmFuc2Zvcm09InRyYW5zbGF0ZSgxNC40NTc5MDIsMjUuNTU0MDAxKSI+CiAgICAgICAgPHBhdGgK +ICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAyLjMyODEyNSwt +NS4yOTY4NzUgYyAwLC0wLjAxNTYyNSAwLjAzMTI1LC0wLjEwOTM3NSAwLjAzMTI1LC0wLjEyNSAw +LC0wLjAzMTI1IC0wLjAzMTI1LC0wLjEwOTM3NSAtMC4xMjUsLTAuMTA5Mzc1IC0wLjAzMTI1LDAg +LTAuMjgxMjUsMC4wMzEyNSAtMC40Njg3NSwwLjA0Njg3NSBsIC0wLjQzNzUsMC4wMzEyNSBDIDEu +MTQwNjI1LC01LjQzNzUgMS4wNjI1LC01LjQzNzUgMS4wNjI1LC01LjI5Njg3NSBjIDAsMC4xMjUg +MC4xMDkzNzUsMC4xMjUgMC4yMTg3NSwwLjEyNSAwLjM3NSwwIDAuMzc1LDAuMDQ2ODc1IDAuMzc1 +LDAuMTA5Mzc1IDAsMC4wMzEyNSAwLDAuMDQ2ODc1IC0wLjAzMTI1LDAuMTg3NSBsIC0xLjE0MDYy +NSw0LjUzMTI1IGMgLTAuMDMxMjUsMC4xMjUgLTAuMDMxMjUsMC4xNzE4NzUgLTAuMDMxMjUsMC4x +NzE4NzUgMCwwLjE0MDYyNSAwLjEwOTM3NSwwLjI1IDAuMjY1NjI1LDAuMjUgMC4xMjUsMCAwLjIz +NDM3NSwtMC4wNzgxMjUgMC4yOTY4NzUsLTAuMTg3NSAwLjAzMTI1LC0wLjA0Njg3NSAwLjA5Mzc1 +LC0wLjI5Njg3NSAwLjEyNSwtMC40NTMxMjUgbCAwLjE4NzUsLTAuNzE4NzUgYyAwLjAzMTI1LC0w +LjEwOTM3NSAwLjEwOTM3NSwtMC40MjE4NzUgMC4xMjUsLTAuNTMxMjUgMC4xMjUsLTAuNDY4NzUg +MC4xMjUsLTAuNDg0Mzc1IDAuMjk2ODc1LC0wLjczNDM3NSAwLjI4MTI1LC0wLjM5MDYyNSAwLjY1 +NjI1LC0wLjc1IDEuMTg3NSwtMC43NSAwLjI4MTI1LDAgMC40NTMxMjUsMC4xNzE4NzUgMC40NTMx +MjUsMC41NDY4NzUgMCwwLjQzNzUgLTAuMzQzNzUsMS4zNDM3NSAtMC40ODQzNzUsMS43MzQzNzUg +LTAuMTA5Mzc1LDAuMjY1NjI1IC0wLjEwOTM3NSwwLjMxMjUgLTAuMTA5Mzc1LDAuNDIxODc1IDAs +MC40NTMxMjUgMC4zNzUsMC42NzE4NzUgMC43MTg3NSwwLjY3MTg3NSAwLjc4MTI1LDAgMS4xMDkz +NzUsLTEuMTA5Mzc1IDEuMTA5Mzc1LC0xLjIxODc1IEMgNC42MjUsLTEuMjE4NzUgNC41NjI1LC0x +LjI1IDQuNSwtMS4yNSBjIC0wLjA5Mzc1LDAgLTAuMTA5Mzc1LDAuMDYyNSAtMC4xNDA2MjUsMC4x +NDA2MjUgLTAuMTg3NSwwLjY1NjI1IC0wLjUxNTYyNSwwLjk2ODc1IC0wLjgyODEyNSwwLjk2ODc1 +IC0wLjEyNSwwIC0wLjE4NzUsLTAuMDc4MTI1IC0wLjE4NzUsLTAuMjY1NjI1IDAsLTAuMTg3NSAw +LjA2MjUsLTAuMzU5Mzc1IDAuMTQwNjI1LC0wLjU2MjUgMC4xMjUsLTAuMjk2ODc1IDAuNDY4NzUs +LTEuMjE4NzUgMC40Njg3NSwtMS42NTYyNSAwLC0wLjYwOTM3NSAtMC40MDYyNSwtMC44OTA2MjUg +LTAuOTg0Mzc1LC0wLjg5MDYyNSAtMC40Mzc1LDAgLTAuODU5Mzc1LDAuMTg3NSAtMS4yMzQzNzUs +MC42MDkzNzUgeiBtIDAsMCIKICAgICAgICAgICBpZD0icGF0aDEwNSIgLz4KICAgICAgPC9nPgog +ICAgPC9nPgogICAgPGcKICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjEi +CiAgICAgICBpZD0iZzcwIj4KICAgICAgPGcKICAgICAgICAgaWQ9InVzZTY4IgogICAgICAgICB0 +cmFuc2Zvcm09InRyYW5zbGF0ZSgzMC4zMzY3MzMsMjUuNTU0MDAxKSI+CiAgICAgICAgPHBhdGgK +ICAgICAgICAgICBzdHlsZT0ic3Ryb2tlOm5vbmUiCiAgICAgICAgICAgZD0ibSAyLjM3NSwtNC45 +Njg3NSBjIDAsLTAuMTcxODc1IC0wLjEyNSwtMC4zMTI1IC0wLjMxMjUsLTAuMzEyNSAtMC4yMDMx +MjUsMCAtMC40Mzc1LDAuMjAzMTI1IC0wLjQzNzUsMC40Mzc1IDAsMC4xNzE4NzUgMC4xMjUsMC4y +OTY4NzUgMC4zMTI1LDAuMjk2ODc1IDAuMjAzMTI1LDAgMC40Mzc1LC0wLjE4NzUgMC40Mzc1LC0w +LjQyMTg3NSB6IG0gLTEuMTU2MjUsMi45MjE4NzUgLTAuNDM3NSwxLjA5Mzc1IGMgLTAuMDQ2ODc1 +LDAuMTI1IC0wLjA3ODEyNSwwLjIxODc1IC0wLjA3ODEyNSwwLjM1OTM3NSAwLDAuMzkwNjI1IDAu +Mjk2ODc1LDAuNjcxODc1IDAuNzE4NzUsMC42NzE4NzUgMC43ODEyNSwwIDEuMTA5Mzc1LC0xLjEw +OTM3NSAxLjEwOTM3NSwtMS4yMTg3NSAwLC0wLjA3ODEyNSAtMC4wNjI1LC0wLjEwOTM3NSAtMC4x +MjUsLTAuMTA5Mzc1IC0wLjA5Mzc1LDAgLTAuMTA5Mzc1LDAuMDYyNSAtMC4xNDA2MjUsMC4xNDA2 +MjUgLTAuMTcxODc1LDAuNjQwNjI1IC0wLjUsMC45Njg3NSAtMC44MjgxMjUsMC45Njg3NSAtMC4w +OTM3NSwwIC0wLjE4NzUsLTAuMDQ2ODc1IC0wLjE4NzUsLTAuMjUgMCwtMC4yMDMxMjUgMC4wNjI1 +LC0wLjM0Mzc1IDAuMTU2MjUsLTAuNTkzNzUgQyAxLjQ4NDM3NSwtMS4xODc1IDEuNTYyNSwtMS40 +MDYyNSAxLjY1NjI1LC0xLjYyNSBsIDAuMjUsLTAuNjQwNjI1IGMgMC4wNjI1LC0wLjE4NzUgMC4x +NzE4NzUsLTAuNDM3NSAwLjE3MTg3NSwtMC41NzgxMjUgMCwtMC4zOTA2MjUgLTAuMzI4MTI1LC0w +LjY3MTg3NSAtMC43MzQzNzUsLTAuNjcxODc1IC0wLjc2NTYyNSwwIC0xLjEwOTM3NSwxLjEwOTM3 +NSAtMS4xMDkzNzUsMS4yMTg3NSAwLDAuMDc4MTI1IDAuMDYyNSwwLjEwOTM3NSAwLjEyNSwwLjEw +OTM3NSAwLjEwOTM3NSwwIDAuMTA5Mzc1LC0wLjA0Njg3NSAwLjE0MDYyNSwtMC4xMjUgMC4yMTg3 +NSwtMC43NjU2MjUgMC41NzgxMjUsLTAuOTg0Mzc1IDAuODI4MTI1LC0wLjk4NDM3NSAwLjEwOTM3 +NSwwIDAuMTg3NSwwLjA0Njg3NSAwLjE4NzUsMC4yNjU2MjUgMCwwLjA3ODEyNSAtMC4wMTU2MjUs +MC4xODc1IC0wLjA5Mzc1LDAuNDM3NSB6IG0gMCwwIgogICAgICAgICAgIGlkPSJwYXRoMTA5IiAv +PgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/96e4049adf5290ee08bfbcd580bd8dd1.msg b/share/extensions/tests/data/cmd/inkscape/96e4049adf5290ee08bfbcd580bd8dd1.msg new file mode 100644 index 0000000..8cb5321 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/96e4049adf5290ee08bfbcd580bd8dd1.msg @@ -0,0 +1,19 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-dpi=1 --export-filename=Slide2.png --export-type=png Slide2.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide2.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide2.png + +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAAnAAAAJwEqCZFPAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAJ9JREFUGJXN0C9uAnEQxfHPDxYW +QVqDRfFHEE5AQoLA7BF6ARwnwKynqgYFCRaD4hakSQ0cgJ5gL7AIFkIIeJ6Zl5mX72SG91BOlBOB +H7FU9TorXUq6yy8+QTKZqCwGfr/6tvegCGWEPZUbcSqWqj0Gl+iiVWxpF76DcEuOvjUQRhv1ohU8 +KMD6z/w/c2x+6J0yh9nQ6um1V9J44/PVR85E2xqRgxB1CAAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/994e3f169976a1af54f6590723d399ee.msg b/share/extensions/tests/data/cmd/inkscape/994e3f169976a1af54f6590723d399ee.msg new file mode 100644 index 0000000..7eff536 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/994e3f169976a1af54f6590723d399ee.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:951:953:1000 --export-filename=f7oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f7oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f7oo.png + +iVBORw0KGgoAAAANSUhEUgAAA4oAAAAxCAYAAACcaFfTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAMNJREFUeJztwTEBAAAAwqD1T20M +H6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAATga19wABjrwhtgAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/9f18b1246e864e6f3945f8cd64d6ca14.msg b/share/extensions/tests/data/cmd/inkscape/9f18b1246e864e6f3945f8cd64d6ca14.msg new file mode 100644 index 0000000..a569ec3 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/9f18b1246e864e6f3945f8cd64d6ca14.msg @@ -0,0 +1,603 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --actions=unlock-all;select-by-element:flowRoot;object-to-path;select-clear;select-by-element:rect;select-by-element:circle;select-by-element:ellipse;select-by-element:line;select-by-element:polyline;select-by-element:polygon;select-by-element:text;object-to-path;select-clear;select-by-element:use;object-unlink-clones;export-overwrite;export-do input.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjwh +LS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoK +PHN2ZwogICB3aWR0aD0iMTAwMCIKICAgaGVpZ2h0PSIxMDAwIgogICB2aWV3Qm94PSIwIDAgMTAw +MCAxMDAwIgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc4IgogICBpbmtzY2FwZTp2ZXJzaW9u +PSIwLjkyLjQgNWRhNjg5YzMxMywgMjAxOS0wMS0xNCIKICAgc29kaXBvZGk6ZG9jbmFtZT0iaW5w +dXQuc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNw +YWNlcy9pbmtzY2FwZSIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vm +b3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv +MjAwMC9zdmciCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHht +bG5zOm5zMT0iaHR0cHM6Ly9sYXVuY2hwYWQubmV0L2plc3N5aW5rIj4KICA8ZGVmcwogICAgIGlk +PSJkZWZzMzMiPgogICAgPG1hcmtlcgogICAgICAgaW5rc2NhcGU6c3RvY2tpZD0iQXJyb3cyTHN0 +YXJ0IgogICAgICAgb3JpZW50PSJhdXRvIgogICAgICAgcmVmWT0iMC4wIgogICAgICAgcmVmWD0i +MC4wIgogICAgICAgaWQ9IkFycm93MkxzdGFydCIKICAgICAgIHN0eWxlPSJvdmVyZmxvdzp2aXNp +YmxlIgogICAgICAgaW5rc2NhcGU6aXNzdG9jaz0idHJ1ZSI+CiAgICAgIDxwYXRoCiAgICAgICAg +IGlkPSJwYXRoODU5IgogICAgICAgICBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLXdp +ZHRoOjAuNjI1O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2U6IzAwMDAwMDtzdHJva2Utb3Bh +Y2l0eToxO2ZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MSIKICAgICAgICAgZD0iTSA4LjcxODU4 +NzgsNC4wMzM3MzUyIEwgLTIuMjA3Mjg5NSwwLjAxNjAxMzI1NiBMIDguNzE4NTg4NCwtNC4wMDE3 +MDc4IEMgNi45NzMwOTAwLC0xLjYyOTY0NjkgNi45ODMxNDc2LDEuNjE1NzQ0MSA4LjcxODU4Nzgs +NC4wMzM3MzUyIHogIgogICAgICAgICB0cmFuc2Zvcm09InNjYWxlKDEuMSkgdHJhbnNsYXRlKDEs +MCkiIC8+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAg +IHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3Jk +ZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5j +ZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5 +PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdp +ZHRoPSIxOTIwIgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMTciCiAgICAgaWQ9ImJh +c2UiCiAgICAgc2hvd2dyaWQ9InRydWUiCiAgICAgaW5rc2NhcGU6c25hcC10ZXh0LWJhc2VsaW5l +PSJ0cnVlIgogICAgIGlua3NjYXBlOnpvb209IjAuNjY3NTA4OCIKICAgICBpbmtzY2FwZTpjeD0i +MjAyLjczNDkiCiAgICAgaW5rc2NhcGU6Y3k9IjQ4MS4xNjk4NiIKICAgICBpbmtzY2FwZTp3aW5k +b3cteD0iMCIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMCIKICAgICBpbmtzY2FwZTp3aW5kb3ct +bWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9IndlYnNsaWNlci1sYXll +ciIKICAgICBpbmtzY2FwZTpwYWdlY2hlY2tlcmJvYXJkPSIwIgogICAgIGlua3NjYXBlOmRlc2tj +b2xvcj0iI2QxZDFkMSI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgdHlwZT0ieHlncmlkIgog +ICAgICAgaWQ9ImdyaWQyNyIKICAgICAgIHNwYWNpbmd4PSIxMCIKICAgICAgIHNwYWNpbmd5PSIx +MCIKICAgICAgIGVtcHNwYWNpbmc9IjEwIgogICAgICAgY29sb3I9IiM4MDgwZmYiCiAgICAgICBv +cGFjaXR5PSIwLjI1MDk4MDM5IgogICAgICAgZW1wY29sb3I9IiMwMDAwZmYiCiAgICAgICBlbXBv +cGFjaXR5PSIwLjI1MDk4MDM5IiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxnCiAgICAg +aW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0id2Vic2xpY2VyLWxheWVyIgogICAg +IGlua3NjYXBlOmxhYmVsPSJTbGlkZTMiCiAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5lIj4KICAg +IDxwYXRoCiAgICAgICBpZD0ic2xpY2VyZWN0MSIKICAgICAgIHN0eWxlPSJvcGFjaXR5OjAuNTtm +aWxsOiNmZjAwMDA7c3Ryb2tlLXdpZHRoOjEuMTE5MjciCiAgICAgICBkPSJtIDY1MS4zMDg5LDM1 +My45MjY2MSBoIDI0OC42OTExMiB2IDIwMS40OTgxIEggNjUxLjMwODkgWiI+CiAgICAgIDxkZXNj +CiAgICAgICAgIGlkPSJkZXNjNTEiPmZvcm1hdDogcG5nCmRwaTogOTYKbGF5b3V0LWRpc3Bvc2l0 +aW9uOiBiZy1lbC1ub3JlcGVhdApsYXlvdXQtcG9zaXRpb24tYW5jaG9yOiB0bDwvZGVzYz4KICAg +IDwvcGF0aD4KICA8L2c+CiAgPGcKICAgICBpbmtzY2FwZTpncm91cG1vZGU9ImxheWVyIgogICAg +IGlkPSJsYXllcjIiCiAgICAgaW5rc2NhcGU6bGFiZWw9IlNsaWRlMiIKICAgICBzdHlsZT0iZGlz +cGxheTppbmxpbmUiPgogICAgPHBhdGgKICAgICAgIGlkPSJjMSIKICAgICAgIHN0eWxlPSJkaXNw +bGF5OmlubGluZTtmaWxsOiMwMDAwODAiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3BhdGgzNzM2 +IgogICAgICAgZD0ibSAyMDAsNDUwIGEgNTAsNTAgMCAwIDEgLTUwLDUwIDUwLDUwIDAgMCAxIC01 +MCwtNTAgNTAsNTAgMCAwIDEgNTAsLTUwIDUwLDUwIDAgMCAxIDUwLDUwIHoiIC8+CiAgICA8cGF0 +aAogICAgICAgaWQ9ImMyIgogICAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5lO2ZpbGw6bm9uZTtz +dHJva2U6I2ZmMDAwMDtzdHJva2Utd2lkdGg6MTYiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3Bh +dGgzNzM4IgogICAgICAgZD0iTSA1MDAsNDUwIEEgMTAwLDUwIDAgMCAxIDQwMCw1MDAgMTAwLDUw +IDAgMCAxIDMwMCw0NTAgMTAwLDUwIDAgMCAxIDQwMCw0MDAgMTAwLDUwIDAgMCAxIDUwMCw0NTAg +WiIgLz4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmU7ZmlsbDojZmZmZjAw +O3N0cm9rZTojMDA4MDAwO3N0cm9rZS13aWR0aDoxNiIKICAgICAgIGlkPSJjMyIKICAgICAgIHNv +ZGlwb2RpOnR5cGU9ImFyYyIKICAgICAgIHNvZGlwb2RpOmN4PSI3MDAiCiAgICAgICBzb2RpcG9k +aTpjeT0iNDUwIgogICAgICAgc29kaXBvZGk6cng9IjEwMCIKICAgICAgIHNvZGlwb2RpOnJ5PSI1 +MCIKICAgICAgIHNvZGlwb2RpOnN0YXJ0PSIwLjU5MDEzODY1IgogICAgICAgc29kaXBvZGk6ZW5k +PSI1LjY0ODQ1MTEiCiAgICAgICBkPSJtIDc4My4wODYzNSw0NzcuODIzODEgYSAxMDAsNTAgMCAw +IDEgLTExMS4wOTg0OCwyMC4xNzQ0MiAxMDAsNTAgMCAwIDEgLTcxLjk2MzAxLC00Ni44ODM0MyAx +MDAsNTAgMCAwIDEgNjcuNzExMjcsLTQ4LjQ0MDkxIDEwMCw1MCAwIDAgMSAxMTIuNzg2OCwxNy42 +Nzc5MyBMIDcwMCw0NTAgWiIKICAgICAgIGlua3NjYXBlOmxhYmVsPSIjcGF0aDM3NDAiIC8+CiAg +ICA8cGF0aAogICAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5lO2ZpbGw6bm9uZTtzdHJva2U6IzAw +MDAwMDtzdHJva2Utd2lkdGg6MTA7bWFya2VyLXN0YXJ0OnVybCgjQXJyb3cyTHN0YXJ0KSIKICAg +ICAgIGQ9Ik0gMTAwLDYwMCAyMDAsNzAwIDMwMCw2MDAgNDAwLDcwMCIKICAgICAgIGlkPSJwMSIK +ICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICBpbmtzY2FwZTps +YWJlbD0iI3BhdGgzNzQ2IiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJkaXNwbGF5OmlubGlu +ZTtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEwIgogICAgICAgZD0ibSA1 +MDAsNjAwIGMgMCwwIDAsMTAwIDEwMCwxMDAgMTAwLDAgMCwtMTAwIDEwMCwtMTAwIDEwMCwwIDEw +MCwxMDAgMTAwLDEwMCIKICAgICAgIGlkPSJwMiIKICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1j +dXJ2YXR1cmU9IjAiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3BhdGgzNzQ4IiAvPgogICAgPHBh +dGgKICAgICAgIHNvZGlwb2RpOnR5cGU9InN0YXIiCiAgICAgICBzdHlsZT0iZGlzcGxheTppbmxp +bmU7ZmlsbDojZmZmZjAwO3N0cm9rZTojMDA4MDAwO3N0cm9rZS13aWR0aDoxMCIKICAgICAgIGlk +PSJzMSIKICAgICAgIHNvZGlwb2RpOnNpZGVzPSI1IgogICAgICAgc29kaXBvZGk6Y3g9IjE4OS4w +MzAwMSIKICAgICAgIHNvZGlwb2RpOmN5PSI4NDcuOTM5NDUiCiAgICAgICBzb2RpcG9kaTpyMT0i +NjkuMzY0ODY4IgogICAgICAgc29kaXBvZGk6cjI9IjM0LjY4MjQzNCIKICAgICAgIHNvZGlwb2Rp +OmFyZzE9IjAuNjM1OTgzNzMiCiAgICAgICBzb2RpcG9kaTphcmcyPSIxLjI2NDMwMjMiCiAgICAg +ICBpbmtzY2FwZTpmbGF0c2lkZWQ9ImZhbHNlIgogICAgICAgaW5rc2NhcGU6cm91bmRlZD0iMCIK +ICAgICAgIGlua3NjYXBlOnJhbmRvbWl6ZWQ9IjAiCiAgICAgICBkPSJtIDI0NC44MzMyLDg4OS4x +NDAwNSAtNDUuMzM4ODcsLTguMTM0NDYgLTMyLjQwNDI4LDMyLjczNzUzIC02LjI3NDE1LC00NS42 +MzM1MiAtNDEuMTQ4NzIsLTIwLjcwMTg0IDQxLjQ2MTI0LC0yMC4wNjg2MSA2Ljk3Mjk3LC00NS41 +MzE5NyAzMS44OTg2MSwzMy4yMzA0NCA0NS40NTgyNCwtNy40Mzg0NyAtMjEuNzQ2ODEsNDAuNjA2 +MTUgeiIKICAgICAgIGlua3NjYXBlOnRyYW5zZm9ybS1jZW50ZXIteD0iNi40NjczMDExIgogICAg +ICAgaW5rc2NhcGU6dHJhbnNmb3JtLWNlbnRlci15PSItMC4xNjQzMDEzNyIgLz4KICAgIDxwYXRo +CiAgICAgICBzb2RpcG9kaTp0eXBlPSJzdGFyIgogICAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5l +O2ZpbGw6I2ZmZmYwMDtzdHJva2U6IzAwODAwMDtzdHJva2Utd2lkdGg6MTAiCiAgICAgICBpZD0i +dTEiCiAgICAgICBzb2RpcG9kaTpzaWRlcz0iNSIKICAgICAgIHNvZGlwb2RpOmN4PSIzODkuMDMw +MDEiCiAgICAgICBzb2RpcG9kaTpjeT0iODUwLjkzNTY3IgogICAgICAgc29kaXBvZGk6cjE9IjY5 +LjM2NDg2OCIKICAgICAgIHNvZGlwb2RpOnIyPSIzNC42ODI0MzQiCiAgICAgICBzb2RpcG9kaTph +cmcxPSIwLjYzNTk4MzczIgogICAgICAgc29kaXBvZGk6YXJnMj0iMS4yNjQzMDIzIgogICAgICAg +aW5rc2NhcGU6ZmxhdHNpZGVkPSJmYWxzZSIKICAgICAgIGlua3NjYXBlOnJvdW5kZWQ9IjAiCiAg +ICAgICBpbmtzY2FwZTpyYW5kb21pemVkPSIwIgogICAgICAgZD0ibSA0NDQuODMzMTksODkyLjEz +NjI2IC00NS4zMzg4OCwtOC4xMzQ0NSAtMzIuNDA0MjcsMzIuNzM3NTMgLTYuMjc0MTYsLTQ1LjYz +MzUyIC00MS4xNDg3MSwtMjAuNzAxODQgNDEuNDYxMjQsLTIwLjA2ODYxIDYuOTcyOTYsLTQ1LjUz +MTk3IDMxLjg5ODYxLDMzLjIzMDQzIDQ1LjQ1ODI1LC03LjQzODQ2IC0yMS43NDY4Miw0MC42MDYx +NSB6IgogICAgICAgaW5rc2NhcGU6dHJhbnNmb3JtLWNlbnRlci14PSI2LjQ2NzMwMTEiCiAgICAg +ICBpbmtzY2FwZTp0cmFuc2Zvcm0tY2VudGVyLXk9Ii0wLjE2NDMwMTM3IiAvPgogIDwvZz4KICA8 +ZwogICAgIGlua3NjYXBlOmxhYmVsPSJTbGlkZTEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJs +YXllciIKICAgICBpZD0ibGF5ZXIxIgogICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZSI+CiAgICA8 +ZwogICAgICAgYXJpYS1sYWJlbD0iSGVsbG8gV29ybGQiCiAgICAgICBpZD0idDEiCiAgICAgICBz +dHlsZT0iZm9udC1zaXplOjE0LjY2NjdweDtsaW5lLWhlaWdodDoxLjI1IgogICAgICAgaW5rc2Nh +cGU6bGFiZWw9IiN0ZXh0MTIiPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDEwMS40Mzk0Niw4 +OS4zMDc5MTggaCAxLjQ0NjYxIHYgNC4zODI4MjMgaCA1LjI1NjUzIHYgLTQuMzgyODIzIGggMS40 +NDY2MSBWIDEwMCBoIC0xLjQ0NjYxIHYgLTUuMDkxODA5IGggLTUuMjU2NTMgViAxMDAgaCAtMS40 +NDY2MSB6IgogICAgICAgICBpZD0icGF0aDgzIiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJt +IDExOS4yNzE1Myw5NS42NjAxNDYgdiAwLjY0NDUzMyBoIC02LjA1ODYxIHEgMC4wODU5LDEuMzYw +NjggMC44MTY0MSwyLjA3NjgyOCAwLjczNzYzLDAuNzA4OTg2IDIuMDQ4MTgsMC43MDg5ODYgMC43 +NTkxMiwwIDEuNDY4MSwtMC4xODYxOTkgMC43MTYxNSwtMC4xODYxOTggMS40MTc5OCwtMC41NTg1 +OTUgdiAxLjI0NjA5NyBxIC0wLjcwODk5LDAuMzAwNzgyIC0xLjQ1Mzc4LDAuNDU4MzM0IC0wLjc0 +NDgsMC4xNTc1NSAtMS41MTEwOCwwLjE1NzU1IC0xLjkxOTI3LDAgLTMuMDQzNjIsLTEuMTE3MTg3 +IC0xLjExNzE5LC0xLjExNzE5IC0xLjExNzE5LC0zLjAyMjE0MyAwLC0xLjk2OTQwNSAxLjA1OTks +LTMuMTIyNDAzIDEuMDY3MDYsLTEuMTYwMTU5IDIuODcxNzUsLTEuMTYwMTU5IDEuNjE4NDksMCAy +LjU1NjY0LDEuMDQ1NTc2IDAuOTQ1MzIsMS4wMzg0MTQgMC45NDUzMiwyLjgyODc4MiB6IG0gLTEu +MzE3NzEsLTAuMzg2NzE5IHEgLTAuMDE0MywtMS4wODEzODMgLTAuNjA4NzMsLTEuNzI1OTE2IC0w +LjU4NzI0LC0wLjY0NDUzMyAtMS41NjEyLC0wLjY0NDUzMyAtMS4xMDI4NywwIC0xLjc2ODg4LDAu +NjIzMDQ5IC0wLjY1ODg2LDAuNjIzMDQ4IC0wLjc1OTEyLDEuNzU0NTYxIHoiCiAgICAgICAgIGlk +PSJwYXRoODUiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTIxLjQzNDI5LDg4Ljg1Njc0 +NSBoIDEuMzE3NzIgViAxMDAgaCAtMS4zMTc3MiB6IgogICAgICAgICBpZD0icGF0aDg3IiAvPgog +ICAgICA8cGF0aAogICAgICAgICBkPSJtIDEyNS41MDkxNyw4OC44NTY3NDUgaCAxLjMxNzcxIFYg +MTAwIGggLTEuMzE3NzEgeiIKICAgICAgICAgaWQ9InBhdGg4OSIgLz4KICAgICAgPHBhdGgKICAg +ICAgICAgZD0ibSAxMzIuNjkyMTMsOTIuOTAyOTc4IHEgLTEuMDU5ODksMCAtMS42NzU3OCwwLjgz +MDczMiAtMC42MTU4OSwwLjgyMzU2OSAtMC42MTU4OSwyLjI2MzAyNiAwLDEuNDM5NDU2IDAuNjA4 +NzMsMi4yNzAxODcgMC42MTU4OCwwLjgyMzU3IDEuNjgyOTQsMC44MjM1NyAxLjA1Mjc0LDAgMS42 +Njg2MywtMC44MzA3MzEgMC42MTU4OCwtMC44MzA3MzEgMC42MTU4OCwtMi4yNjMwMjYgMCwtMS40 +MjUxMzQgLTAuNjE1ODgsLTIuMjU1ODY1IC0wLjYxNTg5LC0wLjgzNzg5MyAtMS42Njg2MywtMC44 +Mzc4OTMgeiBtIDAsLTEuMTE3MTkgcSAxLjcxODc2LDAgMi42OTk4OCwxLjExNzE5IDAuOTgxMTIs +MS4xMTcxOTEgMC45ODExMiwzLjA5Mzc1OCAwLDEuOTY5NDA1IC0wLjk4MTEyLDMuMDkzNzU3IC0w +Ljk4MTEyLDEuMTE3MTg3IC0yLjY5OTg4LDEuMTE3MTg3IC0xLjcyNTkxLDAgLTIuNzA3MDMsLTEu +MTE3MTg3IC0wLjk3Mzk2LC0xLjEyNDM1MiAtMC45NzM5NiwtMy4wOTM3NTcgMCwtMS45NzY1Njcg +MC45NzM5NiwtMy4wOTM3NTggMC45ODExMiwtMS4xMTcxOSAyLjcwNzAzLC0xLjExNzE5IHoiCiAg +ICAgICAgIGlkPSJwYXRoOTEiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTQyLjMyNDMx +LDg5LjMwNzkxOCBoIDEuNDYwOTQgbCAyLjI0ODcxLDkuMDM3NzgxIDIuMjQxNTQsLTkuMDM3Nzgx +IGggMS42MjU2NSBsIDIuMjQ4NzEsOS4wMzc3ODEgMi4yNDE1NCwtOS4wMzc3ODEgaCAxLjQ2ODEg +TCAxNTMuMTczOTUsMTAwIGggLTEuODE5MDIgTCAxNDkuMDk5MDcsOTAuNzE4NzI5IDE0Ni44MjE3 +MiwxMDAgaCAtMS44MTkwMSB6IgogICAgICAgICBpZD0icGF0aDkzIiAvPgogICAgICA8cGF0aAog +ICAgICAgICBkPSJtIDE1OS45NzAxOSw5Mi45MDI5NzggcSAtMS4wNTk5LDAgLTEuNjc1NzgsMC44 +MzA3MzIgLTAuNjE1ODksMC44MjM1NjkgLTAuNjE1ODksMi4yNjMwMjYgMCwxLjQzOTQ1NiAwLjYw +ODcyLDIuMjcwMTg3IDAuNjE1ODksMC44MjM1NyAxLjY4Mjk1LDAuODIzNTcgMS4wNTI3NCwwIDEu +NjY4NjIsLTAuODMwNzMxIDAuNjE1ODksLTAuODMwNzMxIDAuNjE1ODksLTIuMjYzMDI2IDAsLTEu +NDI1MTM0IC0wLjYxNTg5LC0yLjI1NTg2NSAtMC42MTU4OCwtMC44Mzc4OTMgLTEuNjY4NjIsLTAu +ODM3ODkzIHogbSAwLC0xLjExNzE5IHEgMS43MTg3NSwwIDIuNjk5ODgsMS4xMTcxOSAwLjk4MTEy +LDEuMTE3MTkxIDAuOTgxMTIsMy4wOTM3NTggMCwxLjk2OTQwNSAtMC45ODExMiwzLjA5Mzc1NyAt +MC45ODExMywxLjExNzE4NyAtMi42OTk4OCwxLjExNzE4NyAtMS43MjU5MSwwIC0yLjcwNzA0LC0x +LjExNzE4NyAtMC45NzM5NiwtMS4xMjQzNTIgLTAuOTczOTYsLTMuMDkzNzU3IDAsLTEuOTc2NTY3 +IDAuOTczOTYsLTMuMDkzNzU4IDAuOTgxMTMsLTEuMTE3MTkgMi43MDcwNCwtMS4xMTcxOSB6Igog +ICAgICAgICBpZD0icGF0aDk1IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDE3MC40ODMy +Myw5My4yMTA5MjIgcSAtMC4yMjIsLTAuMTI4OTA3IC0wLjQ4Njk4LC0wLjE4NjE5OCAtMC4yNTc4 +MSwtMC4wNjQ0NSAtMC41NzI5MiwtMC4wNjQ0NSAtMS4xMTcxOSwwIC0xLjcxODc1LDAuNzMwNDcx +IC0wLjU5NDQsMC43MjMzMDkgLTAuNTk0NCwyLjA4Mzk4OSBWIDEwMCBoIC0xLjMyNDg4IHYgLTgu +MDIwODUyIGggMS4zMjQ4OCB2IDEuMjQ2MDk3IHEgMC40MTUzNiwtMC43MzA0NzEgMS4wODEzOCwt +MS4wODEzODMgMC42NjYwMiwtMC4zNTgwNzQgMS42MTg0OSwtMC4zNTgwNzQgMC4xMzYwNywwIDAu +MzAwNzksMC4wMjE0OCAwLjE2NDcxLDAuMDE0MzIgMC4zNjUyMywwLjA1MDEzIHoiCiAgICAgICAg +IGlkPSJwYXRoOTciIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTcxLjg2NTQsODguODU2 +NzQ1IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcxIHoiCiAgICAgICAgIGlkPSJwYXRoOTkiIC8+ +CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Ik0gMTgxLjIxODI4LDkzLjE5NjU5OSBWIDg4Ljg1Njc0 +NSBIIDE4Mi41MzYgViAxMDAgaCAtMS4zMTc3MiB2IC0xLjIwMzEyOCBxIC0wLjQxNTM2LDAuNzE2 +MTQ4IC0xLjA1MjczLDEuMDY3MDYgLTAuNjMwMjEsMC4zNDM3NDggLTEuNTE4MjMsMC4zNDM3NDgg +LTEuNDUzNzgsMCAtMi4zNzA0NSwtMS4xNjAxNTYgLTAuOTA5NTEsLTEuMTYwMTU5IC0wLjkwOTUx +LC0zLjA1MDc4OCAwLC0xLjg5MDYzIDAuOTA5NTEsLTMuMDUwNzg5IDAuOTE2NjcsLTEuMTYwMTU5 +IDIuMzcwNDUsLTEuMTYwMTU5IDAuODg4MDIsMCAxLjUxODIzLDAuMzUwOTEzIDAuNjM3MzcsMC4z +NDM3NSAxLjA1MjczLDEuMDU5ODk4IHogbSAtNC40OTAyNCwyLjgwMDEzNyBxIDAsMS40NTM3Nzkg +MC41OTQ0LDIuMjg0NTEgMC42MDE1NywwLjgyMzU3IDEuNjQ3MTQsMC44MjM1NyAxLjA0NTU4LDAg +MS42NDcxNCwtMC44MjM1NyAwLjYwMTU2LC0wLjgzMDczMSAwLjYwMTU2LC0yLjI4NDUxIDAsLTEu +NDUzNzggLTAuNjAxNTYsLTIuMjc3MzQ5IC0wLjYwMTU2LC0wLjgzMDczMSAtMS42NDcxNCwtMC44 +MzA3MzEgLTEuMDQ1NTcsMCAtMS42NDcxNCwwLjgzMDczMSAtMC41OTQ0LDAuODIzNTY5IC0wLjU5 +NDQsMi4yNzczNDkgeiIKICAgICAgICAgaWQ9InBhdGgxMDEiIC8+CiAgICA8L2c+CiAgICA8Zwog +ICAgICAgYXJpYS1sYWJlbD0iZmxvdyB0ZXh0IHdoaWNoIHdyYXBzIgogICAgICAgdHJhbnNmb3Jt +PSJtYXRyaXgoMC4yNjQ1ODMzMywwLDAsMC4yNjQ1ODMzMywzNzIuMDI5NjEsMjguOTA0NTA1KSIK +ICAgICAgIGlkPSJ0NCIKICAgICAgIHN0eWxlPSJmb250LXNpemU6NDBweDtsaW5lLWhlaWdodDox +LjI1IgogICAgICAgaW5rc2NhcGU6bGFiZWw9IiNmbG93Um9vdDE0Ij4KICAgICAgPHBhdGgKICAg +ICAgICAgZD0ibSAxMjEuNTc2MDcsMjI2LjU5MTI1IGggMTMuODU4MjggdiA0Mi4xMTYxNiBoIC01 +LjAwNzM5IHYgLTM3Ljk3NDkyIGggLTguOTA1MDIgcSAtMi42Nzk2MywwIC0zLjczNTI0LDEuMDgy +NjggLTEuMDI4NTQsMS4wODI2OCAtMS4wMjg1NCwzLjg5NzY0IHYgMi42Nzk2MiBoIDguMjAxMjgg +diAzLjg3MDU4IGggLTguMjAxMjggdiAyNi40NDQ0IGggLTUuMDA3MzkgdiAtMjYuNDQ0NCBoIC00 +Ljc2Mzc4IHYgLTMuODcwNTggaCA0Ljc2Mzc4IHYgLTIuMTExMjIgcSAwLC01LjA2MTUyIDIuMzU0 +ODMsLTcuMzYyMjEgMi4zNTQ4MiwtMi4zMjc3NSA3LjQ3MDQ3LC0yLjMyNzc1IHoiCiAgICAgICAg +IHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBpZD0icGF0aDQxIiAvPgogICAg +ICA8cGF0aAogICAgICAgICBkPSJtIDE1Ny42MDIxOCwyNDEuODg0MDcgcSAtNC4wMDU5MSwwIC02 +LjMzMzY3LDMuMTM5NzcgLTIuMzI3NzYsMy4xMTI2OSAtMi4zMjc3Niw4LjU1MzE1IDAsNS40NDA0 +NiAyLjMwMDY5LDguNTgwMjIgMi4zMjc3NiwzLjExMjcgNi4zNjA3NCwzLjExMjcgMy45Nzg4NCww +IDYuMzA2NTksLTMuMTM5NzcgMi4zMjc3NiwtMy4xMzk3NiAyLjMyNzc2LC04LjU1MzE1IDAsLTUu +Mzg2MzIgLTIuMzI3NzYsLTguNTI2MDkgLTIuMzI3NzUsLTMuMTY2ODMgLTYuMzA2NTksLTMuMTY2 +ODMgeiBtIDAsLTQuMjIyNDQgcSA2LjQ5NjA2LDAgMTAuMjA0MjMsNC4yMjI0NCAzLjcwODE4LDQu +MjIyNDQgMy43MDgxOCwxMS42OTI5MiAwLDcuNDQzNDEgLTMuNzA4MTgsMTEuNjkyOTIgLTMuNzA4 +MTcsNC4yMjI0NCAtMTAuMjA0MjMsNC4yMjI0NCAtNi41MjMxNCwwIC0xMC4yMzEzMSwtNC4yMjI0 +NCAtMy42ODExLC00LjI0OTUxIC0zLjY4MTEsLTExLjY5MjkyIDAsLTcuNDcwNDggMy42ODExLC0x +MS42OTI5MiAzLjcwODE3LC00LjIyMjQ0IDEwLjIzMTMxLC00LjIyMjQ0IHoiCiAgICAgICAgIHN0 +eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBpZD0icGF0aDQzIiAvPgogICAgICA8 +cGF0aAogICAgICAgICBkPSJtIDE3Ni44NzM4NCwyMzguMzkyNDMgaCA0Ljk4MDMyIGwgNi4yMjUz +OSwyMy42NTY1MSA2LjE5ODMzLC0yMy42NTY1MSBoIDUuODczNTMgbCA2LjIyNTQsMjMuNjU2NTEg +Ni4xOTgzMywtMjMuNjU2NTEgaCA0Ljk4MDMyIGwgLTcuOTMwNjIsMzAuMzE0OTggaCAtNS44NzM1 +MyBsIC02LjUyMzEzLC0yNC44NDc0NSAtNi41NTAyLDI0Ljg0NzQ1IGggLTUuODczNTMgeiIKICAg +ICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGlkPSJwYXRoNDUiIC8+ +CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMjQ3LjY1MzksMjI5Ljc4NTE1IHYgOC42MDcyOCBo +IDEwLjI1ODM4IHYgMy44NzA1OCBIIDI0Ny42NTM5IHYgMTYuNDU2NyBxIDAsMy43MDgxNyAxLjAw +MTQ4LDQuNzYzNzggMS4wMjg1NCwxLjA1NTYxIDQuMTQxMjQsMS4wNTU2MSBoIDUuMTE1NjYgdiA0 +LjE2ODMxIGggLTUuMTE1NjYgcSAtNS43NjUyNiwwIC03Ljk1NzY4LC0yLjEzODI5IC0yLjE5MjQy +LC0yLjE2NTM1IC0yLjE5MjQyLC03Ljg0OTQxIHYgLTE2LjQ1NjcgaCAtMy42NTQwNCB2IC0zLjg3 +MDU4IGggMy42NTQwNCB2IC04LjYwNzI4IHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUu +NDMzMXB4IgogICAgICAgICBpZD0icGF0aDQ3IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJt +IDI5MC4zOTI2MSwyNTIuMzA0ODQgdiAyLjQzNjAzIGggLTIyLjg5ODY0IHEgMC4zMjQ4MSw1LjE0 +MjcyIDMuMDg1NjQsNy44NDk0MSAyLjc4Nzg5LDIuNjc5NjMgNy43NDExNCwyLjY3OTYzIDIuODY5 +MSwwIDUuNTQ4NzMsLTAuNzAzNzQgMi43MDY2OSwtMC43MDM3NCA1LjM1OTI1LC0yLjExMTIyIHYg +NC43MDk2NSBxIC0yLjY3OTYzLDEuMTM2ODEgLTUuNDk0NTksMS43MzIyOCAtMi44MTQ5NiwwLjU5 +NTQ3IC01LjcxMTEyLDAuNTk1NDcgLTcuMjUzOTUsMCAtMTEuNTAzNDYsLTQuMjIyNDQgLTQuMjIy +NDQsLTQuMjIyNDQgLTQuMjIyNDQsLTExLjQyMjI1IDAsLTcuNDQzNDEgNC4wMDU5MSwtMTEuODAx +MTkgNC4wMzI5NywtNC4zODQ4NCAxMC44NTM4NCwtNC4zODQ4NCA2LjExNzEzLDAgOS42NjI5LDMu +OTUxNzcgMy41NzI4NCwzLjkyNDcxIDMuNTcyODQsMTAuNjkxNDQgeiBtIC00Ljk4MDMyLC0xLjQ2 +MTYxIHEgLTAuMDU0MSwtNC4wODcxMSAtMi4zMDA2OSwtNi41MjMxMyAtMi4yMTk0OSwtMi40MzYw +MyAtNS45MDA1OSwtMi40MzYwMyAtNC4xNjgzMSwwIC02LjY4NTU0LDIuMzU0ODIgLTIuNDkwMTYs +Mi4zNTQ4MyAtMi44NjkwOSw2LjYzMTQxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUu +NDMzMXB4IgogICAgICAgICBpZD0icGF0aDQ5IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJt +IDMyMi43OTE3NCwyMzguMzkyNDMgLTEwLjk2MjExLDE0Ljc1MTQ5IDExLjUzMDUyLDE1LjU2MzQ5 +IGggLTUuODczNTMgbCAtOC44MjM4MiwtMTEuOTA5NDUgLTguODIzODIsMTEuOTA5NDUgaCAtNS44 +NzM1MyBsIDExLjc3NDEyLC0xNS44NjEyMyAtMTAuNzcyNjQsLTE0LjQ1Mzc1IGggNS44NzM1MiBs +IDguMDM4ODksMTAuNzk5NzIgOC4wMzg4OCwtMTAuNzk5NzIgeiIKICAgICAgICAgc3R5bGU9ImZv +bnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGlkPSJwYXRoNTEiIC8+CiAgICAgIDxwYXRoCiAg +ICAgICAgIGQ9Im0gMzM1LjMyMzczLDIyOS43ODUxNSB2IDguNjA3MjggaCAxMC4yNTgzOCB2IDMu +ODcwNTggaCAtMTAuMjU4MzggdiAxNi40NTY3IHEgMCwzLjcwODE3IDEuMDAxNDgsNC43NjM3OCAx +LjAyODU0LDEuMDU1NjEgNC4xNDEyNCwxLjA1NTYxIGggNS4xMTU2NiB2IDQuMTY4MzEgaCAtNS4x +MTU2NiBxIC01Ljc2NTI2LDAgLTcuOTU3NjgsLTIuMTM4MjkgLTIuMTkyNDIsLTIuMTY1MzUgLTIu +MTkyNDIsLTcuODQ5NDEgdiAtMTYuNDU2NyBoIC0zLjY1NDA0IHYgLTMuODcwNTggaCAzLjY1NDA0 +IHYgLTguNjA3MjggeiIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAg +ICAgIGlkPSJwYXRoNTMiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTA4LjA0MjYsMzA3 +LjY4MzgyIGggNC45ODAzMiBsIDYuMjI1NCwyMy42NTY1MSA2LjE5ODMzLC0yMy42NTY1MSBoIDUu +ODczNTIgbCA2LjIyNTQsMjMuNjU2NTEgNi4xOTgzMywtMjMuNjU2NTEgaCA0Ljk4MDMyIGwgLTcu +OTMwNjIsMzAuMzE0OTcgaCAtNS44NzM1MiBsIC02LjUyMzE0LC0yNC44NDc0NSAtNi41NTAyLDI0 +Ljg0NzQ1IGggLTUuODczNTIgeiIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgi +CiAgICAgICAgIGlkPSJwYXRoNTUiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTgxLjQ3 +NTIyLDMxOS43MDE1NCB2IDE4LjI5NzI1IGggLTQuOTgwMzIgdiAtMTguMTM0ODUgcSAwLC00LjMw +MzY0IC0xLjY3ODE1LC02LjQ0MTkzIC0xLjY3ODE1LC0yLjEzODI5IC01LjAzNDQ1LC0yLjEzODI5 +IC00LjAzMjk3LDAgLTYuMzYwNzMsMi41NzEzNiAtMi4zMjc3NiwyLjU3MTM2IC0yLjMyNzc2LDcu +MDEwMzQgdiAxNy4xMzMzNyBoIC01LjAwNzM4IHYgLTQyLjExNjE2IGggNS4wMDczOCB2IDE2LjUx +MDgzIHEgMS43ODY0MiwtMi43MzM3NiA0LjE5NTM4LC00LjA4NzEgMi40MzYwMiwtMS4zNTMzNSA1 +LjYwMjg2LC0xLjM1MzM1IDUuMjIzOTIsMCA3LjkwMzU0LDMuMjQ4MDMgMi42Nzk2MywzLjIyMDk3 +IDIuNjc5NjMsOS41MDA1IHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4Igog +ICAgICAgICBpZD0icGF0aDU3IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDE5MS40MDg3 +OSwzMDcuNjgzODIgaCA0Ljk4MDMyIHYgMzAuMzE0OTcgaCAtNC45ODAzMiB6IG0gMCwtMTEuODAx +MTkgaCA0Ljk4MDMyIHYgNi4zMDY2IGggLTQuOTgwMzIgeiIKICAgICAgICAgc3R5bGU9ImZvbnQt +c2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGlkPSJwYXRoNTkiIC8+CiAgICAgIDxwYXRoCiAgICAg +ICAgIGQ9Im0gMjI4LjYyNTg0LDMwOC44NDc3IHYgNC42NTU1MSBxIC0yLjExMTIyLC0xLjE2Mzg4 +IC00LjI0OTUxLC0xLjczMjI4IC0yLjExMTIyLC0wLjU5NTQ4IC00LjI3NjU4LC0wLjU5NTQ4IC00 +Ljg0NDk4LDAgLTcuNTI0NjEsMy4wODU2MyAtMi42Nzk2MywzLjA1ODU3IC0yLjY3OTYzLDguNjA3 +MjkgMCw1LjU0ODczIDIuNjc5NjMsOC42MzQzNiAyLjY3OTYzLDMuMDU4NTYgNy41MjQ2MSwzLjA1 +ODU2IDIuMTY1MzYsMCA0LjI3NjU4LC0wLjU2ODQgMi4xMzgyOSwtMC41OTU0OCA0LjI0OTUxLC0x +Ljc1OTM2IHYgNC42MDEzOSBxIC0yLjA4NDE2LDAuOTc0NDEgLTQuMzMwNzEsMS40NjE2MSAtMi4y +MTk0OSwwLjQ4NzIxIC00LjczNjcyLDAuNDg3MjEgLTYuODQ3OTQsMCAtMTAuODgwOTEsLTQuMzAz +NjUgLTQuMDMyOTcsLTQuMzAzNjQgLTQuMDMyOTcsLTExLjYxMTcyIDAsLTcuNDE2MzQgNC4wNjAw +NCwtMTEuNjY1ODUgNC4wODcxMSwtNC4yNDk1MSAxMS4xNzg2NCwtNC4yNDk1MSAyLjMwMDY5LDAg +NC40OTMxMiwwLjQ4NzIgMi4xOTI0MiwwLjQ2MDE0IDQuMjQ5NTEsMS40MDc0OSB6IgogICAgICAg +ICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAgICAgaWQ9InBhdGg2MSIgLz4KICAg +ICAgPHBhdGgKICAgICAgICAgZD0ibSAyNjIuNDg2NTgsMzE5LjcwMTU0IHYgMTguMjk3MjUgaCAt +NC45ODAzMSB2IC0xOC4xMzQ4NSBxIDAsLTQuMzAzNjQgLTEuNjc4MTUsLTYuNDQxOTMgLTEuNjc4 +MTUsLTIuMTM4MjkgLTUuMDM0NDYsLTIuMTM4MjkgLTQuMDMyOTcsMCAtNi4zNjA3MywyLjU3MTM2 +IC0yLjMyNzc1LDIuNTcxMzYgLTIuMzI3NzUsNy4wMTAzNCB2IDE3LjEzMzM3IGggLTUuMDA3Mzkg +diAtNDIuMTE2MTYgaCA1LjAwNzM5IHYgMTYuNTEwODMgcSAxLjc4NjQxLC0yLjczMzc2IDQuMTk1 +MzcsLTQuMDg3MSAyLjQzNjAzLC0xLjM1MzM1IDUuNjAyODYsLTEuMzUzMzUgNS4yMjM5MiwwIDcu +OTAzNTUsMy4yNDgwMyAyLjY3OTYyLDMuMjIwOTcgMi42Nzk2Miw5LjUwMDUgeiIKICAgICAgICAg +c3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGlkPSJwYXRoNjMiIC8+CiAgICAg +IDxwYXRoCiAgICAgICAgIGQ9Im0gMTA4LjA0MjYsMzc2Ljk3NTIgaCA0Ljk4MDMyIGwgNi4yMjU0 +LDIzLjY1NjUxIDYuMTk4MzMsLTIzLjY1NjUxIGggNS44NzM1MiBsIDYuMjI1NCwyMy42NTY1MSA2 +LjE5ODMzLC0yMy42NTY1MSBoIDQuOTgwMzIgbCAtNy45MzA2MiwzMC4zMTQ5OCBoIC01Ljg3MzUy +IGwgLTYuNTIzMTQsLTI0Ljg0NzQ2IC02LjU1MDIsMjQuODQ3NDYgaCAtNS44NzM1MiB6IgogICAg +ICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAgICAgaWQ9InBhdGg2NSIgLz4K +ICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAxNzMuODQyMzQsMzgxLjYzMDcxIHEgLTAuODM5MDcs +LTAuNDg3MiAtMS44NDA1NSwtMC43MDM3NCAtMC45NzQ0MSwtMC4yNDM2IC0yLjE2NTM2LC0wLjI0 +MzYgLTQuMjIyNDQsMCAtNi40OTYwNiwyLjc2MDgzIC0yLjI0NjU2LDIuNzMzNzYgLTIuMjQ2NTYs +Ny44NzY0OCB2IDE1Ljk2OTUgaCAtNS4wMDczOCBWIDM3Ni45NzUyIGggNS4wMDczOCB2IDQuNzA5 +NjUgcSAxLjU2OTg4LC0yLjc2MDgzIDQuMDg3MTEsLTQuMDg3MTEgMi41MTcyMywtMS4zNTMzNSA2 +LjExNzEzLC0xLjM1MzM1IDAuNTE0MjcsMCAxLjEzNjgxLDAuMDgxMiAwLjYyMjU0LDAuMDU0MSAx +LjM4MDQyLDAuMTg5NDcgeiIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAg +ICAgICAgIGlkPSJwYXRoNjciIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMTkyLjg0MzM0 +LDM5Mi4wNTE0OSBxIC02LjAzNTkzLDAgLTguMzYzNjgsMS4zODA0MSAtMi4zMjc3NiwxLjM4MDQx +IC0yLjMyNzc2LDQuNzA5NjUgMCwyLjY1MjU2IDEuNzMyMjgsNC4yMjI0NCAxLjc1OTM1LDEuNTQy +ODIgNC43NjM3OCwxLjU0MjgyIDQuMTQxMjUsMCA2LjYzMTQxLC0yLjkyMzIzIDIuNTE3MjIsLTIu +OTUwMyAyLjUxNzIyLC03LjgyMjM1IHYgLTEuMTA5NzQgeiBtIDkuOTMzNTcsLTIuMDU3MDkgdiAx +Ny4yOTU3OCBoIC00Ljk4MDMyIHYgLTQuNjAxMzggcSAtMS43MDUyMiwyLjc2MDgyIC00LjI0OTUx +LDQuMDg3MSAtMi41NDQyOSwxLjI5OTIyIC02LjIyNTQsMS4yOTkyMiAtNC42NTU1MSwwIC03LjQx +NjM0LC0yLjU5ODQzIC0yLjczMzc2LC0yLjYyNTQ5IC0yLjczMzc2LC03LjAxMDM0IDAsLTUuMTE1 +NjUgMy40MTA0NCwtNy43MTQwOCAzLjQzNzUsLTIuNTk4NDIgMTAuMjMxMywtMi41OTg0MiBoIDYu +OTgzMjcgdiAtMC40ODcyMSBxIDAsLTMuNDM3NSAtMi4yNzM2MiwtNS4zMDUxMiAtMi4yNDY1Niwt +MS44OTQ2OSAtNi4zMzM2NywtMS44OTQ2OSAtMi41OTg0MiwwIC01LjA2MTUyLDAuNjIyNTQgLTIu +NDYzMDksMC42MjI1NCAtNC43MzY3MSwxLjg2NzYyIHYgLTQuNjAxMzggcSAyLjczMzc2LC0xLjA1 +NTYxIDUuMzA1MTIsLTEuNTY5ODggMi41NzEzNiwtMC41NDEzNCA1LjAwNzM5LC0wLjU0MTM0IDYu +NTc3MjYsMCA5LjgyNTMsMy40MTA0NCAzLjI0ODAzLDMuNDEwNDMgMy4yNDgwMywxMC4zMzk1NyB6 +IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAgICAgaWQ9InBhdGg2 +OSIgLz4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAyMTcuODUzMTksNDAyLjc0MjkzIHYgMTYu +MDc3NzYgaCAtNS4wMDczOCBWIDM3Ni45NzUyIGggNS4wMDczOCB2IDQuNjAxMzggcSAxLjU2OTg4 +LC0yLjcwNjcgMy45NTE3OCwtNC4wMDU5MSAyLjQwODk1LC0xLjMyNjI4IDUuNzM4MTksLTEuMzI2 +MjggNS41MjE2NSwwIDguOTU5MTYsNC4zODQ4NSAzLjQ2NDU3LDQuMzg0ODQgMy40NjQ1NywxMS41 +MzA1MSAwLDcuMTQ1NjggLTMuNDY0NTcsMTEuNTMwNTIgLTMuNDM3NTEsNC4zODQ4NSAtOC45NTkx +Niw0LjM4NDg1IC0zLjMyOTI0LDAgLTUuNzM4MTksLTEuMjk5MjIgLTIuMzgxOSwtMS4zMjYyOCAt +My45NTE3OCwtNC4wMzI5NyB6IG0gMTYuOTQzOTEsLTEwLjU4MzE4IHEgMCwtNS40OTQ1OSAtMi4y +NzM2MiwtOC42MDcyOCAtMi4yNDY1NiwtMy4xMzk3NyAtNi4xOTgzMywtMy4xMzk3NyAtMy45NTE3 +OCwwIC02LjIyNTQsMy4xMzk3NyAtMi4yNDY1NiwzLjExMjY5IC0yLjI0NjU2LDguNjA3MjggMCw1 +LjQ5NDU5IDIuMjQ2NTYsOC42MzQzNiAyLjI3MzYyLDMuMTEyNyA2LjIyNTQsMy4xMTI3IDMuOTUx +NzcsMCA2LjE5ODMzLC0zLjExMjcgMi4yNzM2MiwtMy4xMzk3NyAyLjI3MzYyLC04LjYzNDM2IHoi +CiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBpZD0icGF0aDcx +IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDI2Ny41NDgxLDM3Ny44Njg0MSB2IDQuNzA5 +NjUgcSAtMi4xMTEyMiwtMS4wODI2OCAtNC4zODQ4NCwtMS42MjQwMiAtMi4yNzM2MywtMC41NDEz +NCAtNC43MDk2NSwtMC41NDEzNCAtMy43MDgxNywwIC01LjU3NTc5LDEuMTM2ODEgLTEuODQwNTYs +MS4xMzY4MSAtMS44NDA1NiwzLjQxMDQ0IDAsMS43MzIyOCAxLjMyNjI5LDIuNzMzNzYgMS4zMjYy +OCwwLjk3NDQxIDUuMzMyMTgsMS44Njc2MiBsIDEuNzA1MjIsMC4zNzg5MyBxIDUuMzA1MTIsMS4x +MzY4MiA3LjUyNDYxLDMuMjIwOTcgMi4yNDY1NiwyLjA1NzA5IDIuMjQ2NTYsNS43NjUyNiAwLDQu +MjIyNDQgLTMuMzU2Myw2LjY4NTU0IC0zLjMyOTI0LDIuNDYzMDkgLTkuMTc1NywyLjQ2MzA5IC0y +LjQzNjAyLDAgLTUuMDg4NTgsLTAuNDg3MjEgLTIuNjI1NSwtMC40NjAxNCAtNS41NDg3MywtMS40 +MDc0OCB2IC01LjE0MjcyIHEgMi43NjA4MywxLjQzNDU1IDUuNDQwNDYsMi4xNjUzNiAyLjY3OTYz +LDAuNzAzNzQgNS4zMDUxMiwwLjcwMzc0IDMuNTE4NywwIDUuNDEzMzksLTEuMTkwOTUgMS44OTQ2 +OSwtMS4yMTgwMSAxLjg5NDY5LC0zLjQxMDQzIDAsLTIuMDMwMDIgLTEuMzgwNDIsLTMuMTEyNyAt +MS4zNTMzNSwtMS4wODI2OCAtNS45ODE3OSwtMi4wODQxNiBsIC0xLjczMjI5LC0wLjQwNiBxIC00 +LjYyODQ1LC0wLjk3NDQxIC02LjY4NTUzLC0yLjk3NzM2IC0yLjA1NzA5LC0yLjAzMDAyIC0yLjA1 +NzA5LC01LjU0ODczIDAsLTQuMjc2NTcgMy4wMzE1LC02LjYwNDMzIDMuMDMxNDksLTIuMzI3NzYg +OC42MDcyOCwtMi4zMjc3NiAyLjc2MDgzLDAgNS4xOTY4NiwwLjQwNjAxIDIuNDM2MDIsMC40MDYg +NC40OTMxMSwxLjIxODAxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4Igog +ICAgICAgICBpZD0icGF0aDczIiAvPgogICAgPC9nPgogICAgPGcKICAgICAgIGFyaWEtbGFiZWw9 +IlVQUEVSIgogICAgICAgaWQ9InQyIgogICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHg7 +bGluZS1oZWlnaHQ6MS4yNSIKICAgICAgIGlua3NjYXBlOmxhYmVsPSIjdGV4dDM3MjciPgogICAg +ICA8cGF0aAogICAgICAgICBkPSJtIDIwMS4yNzQ3NCw4OS4zMDc5MTggaCAxLjQ1Mzc4IHYgNi40 +OTU0NTggcSAwLDEuNzE4NzU0IDAuNjIzMDUsMi40Nzc4NyAwLjYyMzA1LDAuNzUxOTU1IDIuMDE5 +NTQsMC43NTE5NTUgMS4zODkzMiwwIDIuMDEyMzcsLTAuNzUxOTU1IDAuNjIzMDUsLTAuNzU5MTE2 +IDAuNjIzMDUsLTIuNDc3ODcgdiAtNi40OTU0NTggaCAxLjQ1Mzc4IHYgNi42NzQ0OTUgcSAwLDIu +MDkxMTUgLTEuMDM4NDIsMy4xNTgyMSAtMS4wMzEyNSwxLjA2NzA1NyAtMy4wNTA3OCwxLjA2NzA1 +NyAtMi4wMjY3LDAgLTMuMDY1MTIsLTEuMDY3MDU3IC0xLjAzMTI1LC0xLjA2NzA2IC0xLjAzMTI1 +LC0zLjE1ODIxIHoiCiAgICAgICAgIGlkPSJwYXRoMTA0IiAvPgogICAgICA8cGF0aAogICAgICAg +ICBkPSJtIDIxMy42MjExMyw5MC40OTY3MjMgdiA0LjAxNzU4NyBoIDEuODE5MDEgcSAxLjAwOTc3 +LDAgMS41NjEyLC0wLjUyMjc4NyAwLjU1MTQ0LC0wLjUyMjc4OCAwLjU1MTQ0LC0xLjQ4OTU4NyAw +LC0wLjk1OTYzOCAtMC41NTE0NCwtMS40ODI0MjUgLTAuNTUxNDMsLTAuNTIyNzg4IC0xLjU2MTIs +LTAuNTIyNzg4IHogbSAtMS40NDY2MiwtMS4xODg4MDUgaCAzLjI2NTYzIHEgMS43OTc1MywwIDIu +NzE0MiwwLjgxNjQwOCAwLjkyMzgzLDAuODA5MjQ3IDAuOTIzODMsMi4zNzc2MSAwLDEuNTgyNjg2 +IC0wLjkyMzgzLDIuMzkxOTMyIC0wLjkxNjY3LDAuODA5MjQ3IC0yLjcxNDIsMC44MDkyNDcgaCAt +MS44MTkwMSBWIDEwMCBoIC0xLjQ0NjYyIHoiCiAgICAgICAgIGlkPSJwYXRoMTA2IiAvPgogICAg +ICA8cGF0aAogICAgICAgICBkPSJtIDIyMi40NjU1NSw5MC40OTY3MjMgdiA0LjAxNzU4NyBoIDEu +ODE5MDEgcSAxLjAwOTc3LDAgMS41NjEyLC0wLjUyMjc4NyAwLjU1MTQ0LC0wLjUyMjc4OCAwLjU1 +MTQ0LC0xLjQ4OTU4NyAwLC0wLjk1OTYzOCAtMC41NTE0NCwtMS40ODI0MjUgLTAuNTUxNDMsLTAu +NTIyNzg4IC0xLjU2MTIsLTAuNTIyNzg4IHogbSAtMS40NDY2MiwtMS4xODg4MDUgaCAzLjI2NTYz +IHEgMS43OTc1MywwIDIuNzE0MiwwLjgxNjQwOCAwLjkyMzgzLDAuODA5MjQ3IDAuOTIzODMsMi4z +Nzc2MSAwLDEuNTgyNjg2IC0wLjkyMzgzLDIuMzkxOTMyIC0wLjkxNjY3LDAuODA5MjQ3IC0yLjcx +NDIsMC44MDkyNDcgaCAtMS44MTkwMSBWIDEwMCBoIC0xLjQ0NjYyIHoiCiAgICAgICAgIGlkPSJw +YXRoMTA4IiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDIyOS44NjMzNSw4OS4zMDc5MTgg +aCA2Ljc2MDQzIHYgMS4yMTc0NTEgaCAtNS4zMTM4MSB2IDMuMTY1MzcyIGggNS4wOTE4MSB2IDEu +MjE3NDUgaCAtNS4wOTE4MSB2IDMuODc0MzU4IGggNS40NDI3MiBWIDEwMCBoIC02Ljg4OTM0IHoi +CiAgICAgICAgIGlkPSJwYXRoMTEwIiAvPgogICAgICA8cGF0aAogICAgICAgICBkPSJtIDI0NC4y +MDA2Miw5NC45ODY5NjggcSAwLjQ2NTUsMC4xNTc1NTIgMC45MDIzNSwwLjY3MzE3OCAwLjQ0NDAx +LDAuNTE1NjI2IDAuODg4MDIsMS40MTc5NzIgTCAyNDcuNDU5MDksMTAwIGggLTEuNTU0MDQgbCAt +MS4zNjc4NCwtMi43NDI4NDUgcSAtMC41Mjk5NSwtMS4wNzQyMjEgLTEuMDMxMjUsLTEuNDI1MTMz +IC0wLjQ5NDE0LC0wLjM1MDkxMyAtMS4zNTM1MiwtMC4zNTA5MTMgaCAtMS41NzU1MiBWIDEwMCBI +IDIzOS4xMzAzIFYgODkuMzA3OTE4IGggMy4yNjU2MyBxIDEuODMzMzQsMCAyLjczNTY4LDAuNzY2 +Mjc4IDAuOTAyMzUsMC43NjYyNzggMC45MDIzNSwyLjMxMzE1NiAwLDEuMDA5NzY4IC0wLjQ3MjY2 +LDEuNjc1Nzg1IC0wLjQ2NTQ5LDAuNjY2MDE4IC0xLjM2MDY4LDAuOTIzODMxIHogbSAtMy42MjM3 +LC00LjQ5MDI0NSB2IDMuNzk1NTgyIGggMS44MTkwMSBxIDEuMDQ1NTgsMCAxLjU3NTUzLC0wLjQ3 +OTgxOSAwLjUzNzExLC0wLjQ4Njk4MSAwLjUzNzExLC0xLjQyNTEzNCAwLC0wLjkzODE1MyAtMC41 +MzcxMSwtMS40MTA4MSAtMC41Mjk5NSwtMC40Nzk4MTkgLTEuNTc1NTMsLTAuNDc5ODE5IHoiCiAg +ICAgICAgIGlkPSJwYXRoMTEyIiAvPgogICAgPC9nPgogICAgPGcKICAgICAgIGFyaWEtbGFiZWw9 +Ik11bHRpIGxpbmUKdGV4dApGT08iCiAgICAgICBpZD0idDMiCiAgICAgICBzdHlsZT0iZm9udC1z +aXplOjEwLjU4MzNweDtsaW5lLWhlaWdodDoxLjI1IgogICAgICAgaW5rc2NhcGU6bGFiZWw9IiN0 +ZXh0MzczNSI+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMzAxLjQzOTQ2LDg5LjMwNzkxOCBo +IDIuMTU1NiBsIDIuNzI4NTIsNy4yNzYwNTkgMi43NDI4NSwtNy4yNzYwNTkgaCAyLjE1NTYgViAx +MDAgaCAtMS40MTA4MSB2IC05LjM4ODY5MyBsIC0yLjc1NzE3LDcuMzMzMzUgaCAtMS40NTM3OCBs +IC0yLjc1NzE2LC03LjMzMzM1IFYgMTAwIGggLTEuNDAzNjUgeiIKICAgICAgICAgc3R5bGU9ImZv +bnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGlkPSJwYXRoMTE1IiAvPgogICAgICA8cGF0aAog +ICAgICAgICBkPSJtIDMxMy45MDA0Miw5Ni44MzQ2MjggdiAtNC44NTU0OCBoIDEuMzE3NzEgdiA0 +LjgwNTM1IHEgMCwxLjEzODY3NCAwLjQ0NDAxLDEuNzExNTkyIDAuNDQ0MDIsMC41NjU3NTcgMS4z +MzIwNCwwLjU2NTc1NyAxLjA2NzA2LDAgMS42ODI5NSwtMC42ODAzNCAwLjYyMzA0LC0wLjY4MDM0 +IDAuNjIzMDQsLTEuODU0ODIyIHYgLTQuNTQ3NTM3IGggMS4zMTc3MiBWIDEwMCBoIC0xLjMxNzcy +IHYgLTEuMjMxNzc0IHEgLTAuNDc5ODEsMC43MzA0NzEgLTEuMTE3MTksMS4wODg1NDUgLTAuNjMw +MjEsMC4zNTA5MDkgLTEuNDY4MSwwLjM1MDkwOSAtMS4zODIxNiwwIC0yLjA5ODMxLC0wLjg1OTM3 +NCAtMC43MTYxNSwtMC44NTkzNzcgLTAuNzE2MTUsLTIuNTEzNjc4IHogbSAzLjMxNTc2LC01LjA0 +ODg0IHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBpZD0i +cGF0aDExNyIgLz4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAzMjMuMzMyMDksODguODU2NzQ1 +IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6 +MTQuNjY2N3B4IgogICAgICAgICBpZD0icGF0aDExOSIgLz4KICAgICAgPHBhdGgKICAgICAgICAg +ZD0ibSAzMjguNzEwMzUsODkuNzAxNzk5IHYgMi4yNzczNDkgaCAyLjcxNDIgdiAxLjAyNDA5MSBo +IC0yLjcxNDIgdiA0LjM1NDE3NyBxIDAsMC45ODExMjIgMC4yNjQ5OCwxLjI2MDQxOSAwLjI3MjEz +LDAuMjc5Mjk4IDEuMDk1NywwLjI3OTI5OCBoIDEuMzUzNTIgViAxMDAgaCAtMS4zNTM1MiBxIC0x +LjUyNTM5LDAgLTIuMTA1NDcsLTAuNTY1NzU3IC0wLjU4MDA4LC0wLjU3MjkxNyAtMC41ODAwOCwt +Mi4wNzY4MjcgdiAtNC4zNTQxNzcgaCAtMC45NjY4IHYgLTEuMDI0MDkxIGggMC45NjY4IHYgLTIu +Mjc3MzQ5IHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBp +ZD0icGF0aDEyMSIgLz4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAzMzMuMTU3NjMsOTEuOTc5 +MTQ4IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcxIHogbSAwLC0zLjEyMjQwMyBoIDEuMzE3NzEg +diAxLjY2ODYyNCBoIC0xLjMxNzcxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2 +N3B4IgogICAgICAgICBpZD0icGF0aDEyMyIgLz4KICAgICAgPHBhdGgKICAgICAgICAgZD0ibSAz +NDEuODk0NjMsODguODU2NzQ1IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcxIHoiCiAgICAgICAg +IHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBpZD0icGF0aDEyNSIgLz4KICAg +ICAgPHBhdGgKICAgICAgICAgZD0ibSAzNDUuOTY5NTEsOTEuOTc5MTQ4IGggMS4zMTc3MSBWIDEw +MCBoIC0xLjMxNzcxIHogbSAwLC0zLjEyMjQwMyBoIDEuMzE3NzEgdiAxLjY2ODYyNCBoIC0xLjMx +NzcxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBpZD0i +cGF0aDEyNyIgLz4KICAgICAgPHBhdGgKICAgICAgICAgZD0iTSAzNTYuNzExNzIsOTUuMTU4ODQz +IFYgMTAwIGggLTEuMzE3NzEgdiAtNC43OTgxODggcSAwLC0xLjEzODY3NSAtMC40NDQwMiwtMS43 +MDQ0MzEgLTAuNDQ0MDEsLTAuNTY1NzU3IC0xLjMzMjAzLC0wLjU2NTc1NyAtMS4wNjcwNiwwIC0x +LjY4Mjk1LDAuNjgwMzQgLTAuNjE1ODgsMC42ODAzNDEgLTAuNjE1ODgsMS44NTQ4MjIgViAxMDAg +aCAtMS4zMjQ4OCB2IC04LjAyMDg1MiBoIDEuMzI0ODggdiAxLjI0NjA5NyBxIDAuNDcyNjUsLTAu +NzIzMzA5IDEuMTEwMDMsLTEuMDgxMzgzIDAuNjQ0NTMsLTAuMzU4MDc0IDEuNDgyNDIsLTAuMzU4 +MDc0IDEuMzgyMTcsMCAyLjA5MTE1LDAuODU5Mzc3IDAuNzA4OTksMC44NTIyMTYgMC43MDg5OSwy +LjUxMzY3OCB6IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAg +aWQ9InBhdGgxMjkiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMzY2LjIwMDY3LDk1LjY2 +MDE0NiB2IDAuNjQ0NTMzIGggLTYuMDU4NjEgcSAwLjA4NTksMS4zNjA2OCAwLjgxNjQxLDIuMDc2 +ODI4IDAuNzM3NjMsMC43MDg5ODYgMi4wNDgxOCwwLjcwODk4NiAwLjc1OTEyLDAgMS40NjgxMSwt +MC4xODYxOTkgMC43MTYxNCwtMC4xODYxOTggMS40MTc5NywtMC41NTg1OTUgdiAxLjI0NjA5NyBx +IC0wLjcwODk5LDAuMzAwNzgyIC0xLjQ1Mzc4LDAuNDU4MzM0IC0wLjc0NDgsMC4xNTc1NSAtMS41 +MTEwNywwLjE1NzU1IC0xLjkxOTI4LDAgLTMuMDQzNjMsLTEuMTE3MTg3IC0xLjExNzE5LC0xLjEx +NzE5IC0xLjExNzE5LC0zLjAyMjE0MyAwLC0xLjk2OTQwNSAxLjA1OTksLTMuMTIyNDAzIDEuMDY3 +MDYsLTEuMTYwMTU5IDIuODcxNzUsLTEuMTYwMTU5IDEuNjE4NDksMCAyLjU1NjY1LDEuMDQ1NTc2 +IDAuOTQ1MzEsMS4wMzg0MTQgMC45NDUzMSwyLjgyODc4MiB6IG0gLTEuMzE3NzEsLTAuMzg2NzE5 +IHEgLTAuMDE0MywtMS4wODEzODMgLTAuNjA4NzMsLTEuNzI1OTE2IC0wLjU4NzI0LC0wLjY0NDUz +MyAtMS41NjEyLC0wLjY0NDUzMyAtMS4xMDI4NiwwIC0xLjc2ODg4LDAuNjIzMDQ5IC0wLjY1ODg2 +LDAuNjIzMDQ4IC0wLjc1OTEyLDEuNzU0NTYxIHoiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6 +MTQuNjY2N3B4IgogICAgICAgICBpZD0icGF0aDEzMSIgLz4KICAgICAgPHBhdGgKICAgICAgICAg +ZD0ibSAzMDIuNjg1NTUsMTA4LjAzNTE3IHYgMi4yNzczNSBoIDIuNzE0MiB2IDEuMDI0MDkgaCAt +Mi43MTQyIHYgNC4zNTQxOCBxIDAsMC45ODExMiAwLjI2NDk4LDEuMjYwNDIgMC4yNzIxMywwLjI3 +OTMgMS4wOTU3LDAuMjc5MyBoIDEuMzUzNTIgdiAxLjEwMjg3IGggLTEuMzUzNTIgcSAtMS41MjUz +OSwwIC0yLjEwNTQ3LC0wLjU2NTc2IC0wLjU4MDA4LC0wLjU3MjkyIC0wLjU4MDA4LC0yLjA3Njgz +IHYgLTQuMzU0MTggaCAtMC45NjY4IHYgLTEuMDI0MDkgaCAwLjk2NjggdiAtMi4yNzczNSB6Igog +ICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgaWQ9InBhdGgxMzMi +IC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMzEzLjk5MzUyLDExMy45OTM1MiB2IDAuNjQ0 +NTMgaCAtNi4wNTg2MSBxIDAuMDg1OSwxLjM2MDY4IDAuODE2NDEsMi4wNzY4MyAwLjczNzYzLDAu +NzA4OTkgMi4wNDgxOCwwLjcwODk5IDAuNzU5MTIsMCAxLjQ2ODExLC0wLjE4NjIgMC43MTYxNCwt +MC4xODYyIDEuNDE3OTcsLTAuNTU4NiB2IDEuMjQ2MSBxIC0wLjcwODk5LDAuMzAwNzggLTEuNDUz +NzgsMC40NTgzNCAtMC43NDQ3OSwwLjE1NzU1IC0xLjUxMTA3LDAuMTU3NTUgLTEuOTE5MjgsMCAt +My4wNDM2MywtMS4xMTcxOSAtMS4xMTcxOSwtMS4xMTcxOSAtMS4xMTcxOSwtMy4wMjIxNCAwLC0x +Ljk2OTQxIDEuMDU5OSwtMy4xMjI0MSAxLjA2NzA2LC0xLjE2MDE2IDIuODcxNzUsLTEuMTYwMTYg +MS42MTg0OSwwIDIuNTU2NjUsMS4wNDU1OCAwLjk0NTMxLDEuMDM4NDEgMC45NDUzMSwyLjgyODc4 +IHogbSAtMS4zMTc3MSwtMC4zODY3MiBxIC0wLjAxNDMsLTEuMDgxMzggLTAuNjA4NzMsLTEuNzI1 +OTEgLTAuNTg3MjQsLTAuNjQ0NTQgLTEuNTYxMiwtMC42NDQ1NCAtMS4xMDI4NiwwIC0xLjc2ODg4 +LDAuNjIzMDUgLTAuNjU4ODYsMC42MjMwNSAtMC43NTkxMiwxLjc1NDU2IHoiCiAgICAgICAgIHN0 +eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBpZD0icGF0aDEzNSIgLz4KICAgICAg +PHBhdGgKICAgICAgICAgZD0ibSAzMjIuNTY1ODEsMTEwLjMxMjUyIC0yLjkwMDQsMy45MDMwMSAz +LjA1MDc5LDQuMTE3ODUgaCAtMS41NTQwNCBsIC0yLjMzNDY0LC0zLjE1MTA1IC0yLjMzNDY0LDMu +MTUxMDUgaCAtMS41NTQwNCBsIDMuMTE1MjQsLTQuMTk2NjMgLTIuODUwMjcsLTMuODI0MjMgaCAx +LjU1NDA0IGwgMi4xMjY5NiwyLjg1NzQzIDIuMTI2OTYsLTIuODU3NDMgeiIKICAgICAgICAgc3R5 +bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGlkPSJwYXRoMTM3IiAvPgogICAgICA8 +cGF0aAogICAgICAgICBkPSJtIDMyNS44ODE1NywxMDguMDM1MTcgdiAyLjI3NzM1IGggMi43MTQy +IHYgMS4wMjQwOSBoIC0yLjcxNDIgdiA0LjM1NDE4IHEgMCwwLjk4MTEyIDAuMjY0OTcsMS4yNjA0 +MiAwLjI3MjE0LDAuMjc5MyAxLjA5NTcxLDAuMjc5MyBoIDEuMzUzNTIgdiAxLjEwMjg3IGggLTEu +MzUzNTIgcSAtMS41MjUzOSwwIC0yLjEwNTQ3LC0wLjU2NTc2IC0wLjU4MDA4LC0wLjU3MjkyIC0w +LjU4MDA4LC0yLjA3NjgzIHYgLTQuMzU0MTggaCAtMC45NjY4IHYgLTEuMDI0MDkgaCAwLjk2Njgg +diAtMi4yNzczNSB6IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAg +ICAgaWQ9InBhdGgxMzkiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGQ9Im0gMzAxLjQzOTQ2LDEy +NS45NzQ2NyBoIDYuMTQ0NTQgdiAxLjIxNzQ1IGggLTQuNjk3OTMgdiAzLjE1MTA1IGggNC4yMzk2 +IHYgMS4yMTc0NSBoIC00LjIzOTYgdiA1LjEwNjEzIGggLTEuNDQ2NjEgeiIKICAgICAgICAgc3R5 +bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGlkPSJwYXRoMTQxIiAvPgogICAgICA8 +cGF0aAogICAgICAgICBkPSJtIDMxNC4yMTU1MywxMjYuOTU1NzkgcSAtMS41NzU1MywwIC0yLjUw +NjUyLDEuMTc0NDggLTAuOTIzODMsMS4xNzQ0OCAtMC45MjM4MywzLjIwMTE4IDAsMi4wMTk1NCAw +LjkyMzgzLDMuMTk0MDIgMC45MzA5OSwxLjE3NDQ4IDIuNTA2NTIsMS4xNzQ0OCAxLjU3NTUyLDAg +Mi40OTIxOSwtMS4xNzQ0OCAwLjkyMzgzLC0xLjE3NDQ4IDAuOTIzODMsLTMuMTk0MDIgMCwtMi4w +MjY3IC0wLjkyMzgzLC0zLjIwMTE4IC0wLjkxNjY3LC0xLjE3NDQ4IC0yLjQ5MjE5LC0xLjE3NDQ4 +IHogbSAwLC0xLjE3NDQ4IHEgMi4yNDg3LDAgMy41OTUwNiwxLjUxMTA3IDEuMzQ2MzYsMS41MDM5 +MSAxLjM0NjM2LDQuMDM5MDcgMCwyLjUyOCAtMS4zNDYzNiw0LjAzOTA3IC0xLjM0NjM2LDEuNTAz +OTEgLTMuNTk1MDYsMS41MDM5MSAtMi4yNTU4NywwIC0zLjYwOTM5LC0xLjUwMzkxIC0xLjM0NjM1 +LC0xLjUwMzkxIC0xLjM0NjM1LC00LjAzOTA3IDAsLTIuNTM1MTYgMS4zNDYzNSwtNC4wMzkwNyAx +LjM1MzUyLC0xLjUxMTA3IDMuNjA5MzksLTEuNTExMDcgeiIKICAgICAgICAgc3R5bGU9ImZvbnQt +c2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGlkPSJwYXRoMTQzIiAvPgogICAgICA8cGF0aAogICAg +ICAgICBkPSJtIDMyNS43NTk4MiwxMjYuOTU1NzkgcSAtMS41NzU1MiwwIC0yLjUwNjUxLDEuMTc0 +NDggLTAuOTIzODMsMS4xNzQ0OCAtMC45MjM4MywzLjIwMTE4IDAsMi4wMTk1NCAwLjkyMzgzLDMu +MTk0MDIgMC45MzA5OSwxLjE3NDQ4IDIuNTA2NTEsMS4xNzQ0OCAxLjU3NTUzLDAgMi40OTIyLC0x +LjE3NDQ4IDAuOTIzODMsLTEuMTc0NDggMC45MjM4MywtMy4xOTQwMiAwLC0yLjAyNjcgLTAuOTIz +ODMsLTMuMjAxMTggLTAuOTE2NjcsLTEuMTc0NDggLTIuNDkyMiwtMS4xNzQ0OCB6IG0gMCwtMS4x +NzQ0OCBxIDIuMjQ4NzEsMCAzLjU5NTA3LDEuNTExMDcgMS4zNDYzNSwxLjUwMzkxIDEuMzQ2MzUs +NC4wMzkwNyAwLDIuNTI4IC0xLjM0NjM1LDQuMDM5MDcgLTEuMzQ2MzYsMS41MDM5MSAtMy41OTUw +NywxLjUwMzkxIC0yLjI1NTg2LDAgLTMuNjA5MzgsLTEuNTAzOTEgLTEuMzQ2MzYsLTEuNTAzOTEg +LTEuMzQ2MzYsLTQuMDM5MDcgMCwtMi41MzUxNiAxLjM0NjM2LC00LjAzOTA3IDEuMzUzNTIsLTEu +NTExMDcgMy42MDkzOCwtMS41MTEwNyB6IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2 +NjdweCIKICAgICAgICAgaWQ9InBhdGgxNDUiIC8+CiAgICA8L2c+CiAgICA8ZwogICAgICAgaWQ9 +InQ1IgogICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDQ1LjcxMDM4LC0xMjkuNjQ4MDcpIgog +ICAgICAgaW5rc2NhcGU6bGFiZWw9IiNnMzc3MiI+CiAgICAgIDxnCiAgICAgICAgIGFyaWEtbGFi +ZWw9Ikdyb3VwZWQiCiAgICAgICAgIGlkPSJ0ZXh0Mzc2MiIKICAgICAgICAgc3R5bGU9ImZvbnQt +c2l6ZToxMC41ODMzcHg7bGluZS1oZWlnaHQ6MS4yNSI+CiAgICAgICAgPHBhdGgKICAgICAgICAg +ICBkPSJtIDYzLjAxOTQ1MywyMjguMTIyNjggdiAtMi44NzE3NSBoIC0yLjM2MzI4NiB2IC0xLjE4 +ODgxIGggMy43OTU1ODEgdiA0LjU5MDUxIHEgLTAuODM3ODkyLDAuNTk0NCAtMS44NDc2NiwwLjkw +MjM0IC0xLjAwOTc2OCwwLjMwMDc4IC0yLjE1NTYwNCwwLjMwMDc4IC0yLjUwNjUxNiwwIC0zLjky +NDQ4OCwtMS40NjA5NCAtMS40MTA4MTEsLTEuNDY4MSAtMS40MTA4MTEsLTQuMDgyMDQgMCwtMi42 +MjExIDEuNDEwODExLC00LjA4MjA0IDEuNDE3OTcyLC0xLjQ2ODEgMy45MjQ0ODgsLTEuNDY4MSAx +LjA0NTU3NSwwIDEuOTgzNzI4LDAuMjU3ODEgMC45NDUzMTUsMC4yNTc4MiAxLjc0MDIzOSwwLjc1 +OTEyIHYgMS41Mzk3MiBxIC0wLjgwMjA4NSwtMC42ODAzNCAtMS43MDQ0MzEsLTEuMDI0MDkgLTAu +OTAyMzQ2LC0wLjM0Mzc2IC0xLjg5Nzc5MSwtMC4zNDM3NiAtMS45NjIyNDQsMCAtMi45NTA1Mjgs +MS4wOTU3MSAtMC45ODExMjIsMS4wOTU3MSAtMC45ODExMjIsMy4yNjU2MyAwLDIuMTYyNzcgMC45 +ODExMjIsMy4yNTg0NyAwLjk4ODI4NCwxLjA5NTcxIDIuOTUwNTI4LDEuMDk1NzEgMC43NjYyNzgs +MCAxLjM2Nzg0MiwtMC4xMjg5MSAwLjYwMTU2NCwtMC4xMzYwNyAxLjA4MTM4MiwtMC40MTUzNiB6 +IgogICAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICAgIGlkPSJw +YXRoMTQ4IiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgZD0ibSA3MS42ODQ4MzgsMjIyLjg1 +ODk5IHEgLTAuMjIyMDA2LC0wLjEyODkgLTAuNDg2OTgxLC0wLjE4NjIgLTAuMjU3ODEzLC0wLjA2 +NDQgLTAuNTcyOTE4LC0wLjA2NDQgLTEuMTE3MTksMCAtMS43MTg3NTQsMC43MzA0NyAtMC41OTQ0 +MDIsMC43MjMzMSAtMC41OTQ0MDIsMi4wODM5OSB2IDQuMjI1MjcgSCA2Ni45ODY5MSB2IC04LjAy +MDg1IGggMS4zMjQ4NzMgdiAxLjI0NjEgcSAwLjQxNTM2NSwtMC43MzA0NyAxLjA4MTM4MywtMS4w +ODEzOSAwLjY2NjAxNywtMC4zNTgwNyAxLjYxODQ5MywtMC4zNTgwNyAwLjEzNjA2OCwwIDAuMzAw +NzgyLDAuMDIxNSAwLjE2NDcxNCwwLjAxNDMgMC4zNjUyMzUsMC4wNTAxIHoiCiAgICAgICAgICAg +c3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgICAgaWQ9InBhdGgxNTAiIC8+CiAg +ICAgICAgPHBhdGgKICAgICAgICAgICBkPSJtIDc1Ljg1MjgxNiwyMjIuNTUxMDUgcSAtMS4wNTk4 +OTgsMCAtMS42NzU3ODUsMC44MzA3MyAtMC42MTU4ODcsMC44MjM1NyAtMC42MTU4ODcsMi4yNjMw +MyAwLDEuNDM5NDUgMC42MDg3MjYsMi4yNzAxOCAwLjYxNTg4NywwLjgyMzU3IDEuNjgyOTQ2LDAu +ODIzNTcgMS4wNTI3MzcsMCAxLjY2ODYyNCwtMC44MzA3MyAwLjYxNTg4NywtMC44MzA3MyAwLjYx +NTg4NywtMi4yNjMwMiAwLC0xLjQyNTE0IC0wLjYxNTg4NywtMi4yNTU4NyAtMC42MTU4ODcsLTAu +ODM3ODkgLTEuNjY4NjI0LC0wLjgzNzg5IHogbSAwLC0xLjExNzE5IHEgMS43MTg3NTQsMCAyLjY5 +OTg3NiwxLjExNzE5IDAuOTgxMTIyLDEuMTE3MTkgMC45ODExMjIsMy4wOTM3NiAwLDEuOTY5NCAt +MC45ODExMjIsMy4wOTM3NSAtMC45ODExMjIsMS4xMTcxOSAtMi42OTk4NzYsMS4xMTcxOSAtMS43 +MjU5MTUsMCAtMi43MDcwMzcsLTEuMTE3MTkgLTAuOTczOTYxLC0xLjEyNDM1IC0wLjk3Mzk2MSwt +My4wOTM3NSAwLC0xLjk3NjU3IDAuOTczOTYxLC0zLjA5Mzc2IDAuOTgxMTIyLC0xLjExNzE5IDIu +NzA3MDM3LC0xLjExNzE5IHoiCiAgICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgi +CiAgICAgICAgICAgaWQ9InBhdGgxNTIiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBkPSJt +IDgxLjU4MTk5NiwyMjYuNDgyNyB2IC00Ljg1NTQ4IGggMS4zMTc3MTEgdiA0LjgwNTM1IHEgMCwx +LjEzODY3IDAuNDQ0MDEyLDEuNzExNTkgMC40NDQwMTEsMC41NjU3NiAxLjMzMjAzNCwwLjU2NTc2 +IDEuMDY3MDYsMCAxLjY4Mjk0NywtMC42ODAzNCAwLjYyMzA0OCwtMC42ODAzNCAwLjYyMzA0OCwt +MS44NTQ4MiB2IC00LjU0NzU0IGggMS4zMTc3MTEgdiA4LjAyMDg1IGggLTEuMzE3NzExIHYgLTEu +MjMxNzcgcSAtMC40Nzk4MTksMC43MzA0NyAtMS4xMTcxOSwxLjA4ODU0IC0wLjYzMDIxLDAuMzUw +OTEgLTEuNDY4MTAyLDAuMzUwOTEgLTEuMzgyMTY1LDAgLTIuMDk4MzEzLC0wLjg1OTM3IC0wLjcx +NjE0NywtMC44NTkzOCAtMC43MTYxNDcsLTIuNTEzNjggeiBtIDMuMzE1NzYzLC01LjA0ODg0IHoi +CiAgICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgICAgaWQ9InBh +dGgxNTQiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBkPSJtIDkyLjI4ODQsMjI4LjQ0NDk0 +IHYgNC4yNTM5MiBIIDkwLjk2MzUyNyBWIDIyMS42MjcyMiBIIDkyLjI4ODQgdiAxLjIxNzQ1IHEg +MC40MTUzNjUsLTAuNzE2MTUgMS4wNDU1NzUsLTEuMDU5OSAwLjYzNzM3MSwtMC4zNTA5MSAxLjUx +ODIzMywtMC4zNTA5MSAxLjQ2MDk0MSwwIDIuMzcwNDQ4LDEuMTYwMTYgMC45MTY2NjksMS4xNjAx +NiAwLjkxNjY2OSwzLjA1MDc5IDAsMS44OTA2MyAtMC45MTY2NjksMy4wNTA3OSAtMC45MDk1MDcs +MS4xNjAxNSAtMi4zNzA0NDgsMS4xNjAxNSAtMC44ODA4NjIsMCAtMS41MTgyMzMsLTAuMzQzNzUg +LTAuNjMwMjEsLTAuMzUwOTEgLTEuMDQ1NTc1LC0xLjA2NzA2IHogbSA0LjQ4MzA4MywtMi44MDAx +MyBxIDAsLTEuNDUzNzggLTAuNjAxNTY0LC0yLjI3NzM1IC0wLjU5NDQwMiwtMC44MzA3MyAtMS42 +Mzk5NzgsLTAuODMwNzMgLTEuMDQ1NTc1LDAgLTEuNjQ3MTM5LDAuODMwNzMgLTAuNTk0NDAyLDAu +ODIzNTcgLTAuNTk0NDAyLDIuMjc3MzUgMCwxLjQ1Mzc4IDAuNTk0NDAyLDIuMjg0NTEgMC42MDE1 +NjQsMC44MjM1NyAxLjY0NzEzOSwwLjgyMzU3IDEuMDQ1NTc2LDAgMS42Mzk5NzgsLTAuODIzNTcg +MC42MDE1NjQsLTAuODMwNzMgMC42MDE1NjQsLTIuMjg0NTEgeiIKICAgICAgICAgICBzdHlsZT0i +Zm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgICBpZD0icGF0aDE1NiIgLz4KICAgICAgICA8 +cGF0aAogICAgICAgICAgIGQ9Im0gMTA3LjE4NDI3LDIyNS4zMDgyMiB2IDAuNjQ0NTMgaCAtNi4w +NTg2MSBxIDAuMDg1OSwxLjM2MDY4IDAuODE2NDEsMi4wNzY4MyAwLjczNzYzLDAuNzA4OTggMi4w +NDgxOCwwLjcwODk4IDAuNzU5MTIsMCAxLjQ2ODEsLTAuMTg2MTkgMC43MTYxNSwtMC4xODYyIDEu +NDE3OTcsLTAuNTU4NiB2IDEuMjQ2MSBxIC0wLjcwODk4LDAuMzAwNzggLTEuNDUzNzgsMC40NTgz +MyAtMC43NDQ3OSwwLjE1NzU1IC0xLjUxMTA3LDAuMTU3NTUgLTEuOTE5MjcsMCAtMy4wNDM2Miwt +MS4xMTcxOSAtMS4xMTcxOTMsLTEuMTE3MTkgLTEuMTE3MTkzLC0zLjAyMjE0IDAsLTEuOTY5NCAx +LjA1OTg5MywtMy4xMjI0IDEuMDY3MDYsLTEuMTYwMTYgMi44NzE3NiwtMS4xNjAxNiAxLjYxODQ5 +LDAgMi41NTY2NCwxLjA0NTU4IDAuOTQ1MzIsMS4wMzg0MSAwLjk0NTMyLDIuODI4NzggeiBtIC0x +LjMxNzcxLC0wLjM4NjcyIHEgLTAuMDE0MywtMS4wODEzOCAtMC42MDg3MywtMS43MjU5MiAtMC41 +ODcyNCwtMC42NDQ1MyAtMS41NjEyLC0wLjY0NDUzIC0xLjEwMjg3LDAgLTEuNzY4ODgsMC42MjMw +NSAtMC42NTg4NiwwLjYyMzA1IC0wLjc1OTEyLDEuNzU0NTYgeiIKICAgICAgICAgICBzdHlsZT0i +Zm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgICBpZD0icGF0aDE1OCIgLz4KICAgICAgICA8 +cGF0aAogICAgICAgICAgIGQ9Im0gMTE0LjYyNTA0LDIyMi44NDQ2NyB2IC00LjMzOTg1IGggMS4z +MTc3MSB2IDExLjE0MzI1IGggLTEuMzE3NzEgdiAtMS4yMDMxMyBxIC0wLjQxNTM2LDAuNzE2MTUg +LTEuMDUyNzMsMS4wNjcwNiAtMC42MzAyMSwwLjM0Mzc1IC0xLjUxODI0LDAuMzQzNzUgLTEuNDUz +NzgsMCAtMi4zNzA0NSwtMS4xNjAxNSAtMC45MDk1LC0xLjE2MDE2IC0wLjkwOTUsLTMuMDUwNzkg +MCwtMS44OTA2MyAwLjkwOTUsLTMuMDUwNzkgMC45MTY2NywtMS4xNjAxNiAyLjM3MDQ1LC0xLjE2 +MDE2IDAuODg4MDMsMCAxLjUxODI0LDAuMzUwOTEgMC42MzczNywwLjM0Mzc1IDEuMDUyNzMsMS4w +NTk5IHogbSAtNC40OTAyNCwyLjgwMDE0IHEgMCwxLjQ1Mzc4IDAuNTk0NCwyLjI4NDUxIDAuNjAx +NTYsMC44MjM1NyAxLjY0NzE0LDAuODIzNTcgMS4wNDU1NywwIDEuNjQ3MTQsLTAuODIzNTcgMC42 +MDE1NiwtMC44MzA3MyAwLjYwMTU2LC0yLjI4NDUxIDAsLTEuNDUzNzggLTAuNjAxNTYsLTIuMjc3 +MzUgLTAuNjAxNTcsLTAuODMwNzMgLTEuNjQ3MTQsLTAuODMwNzMgLTEuMDQ1NTgsMCAtMS42NDcx +NCwwLjgzMDczIC0wLjU5NDQsMC44MjM1NyAtMC41OTQ0LDIuMjc3MzUgeiIKICAgICAgICAgICBz +dHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgICBpZD0icGF0aDE2MCIgLz4KICAg +ICAgPC9nPgogICAgICA8ZwogICAgICAgICBhcmlhLWxhYmVsPSJ0ZXh0IgogICAgICAgICBpZD0i +dGV4dDM3NjYiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4O2xpbmUtaGVpZ2h0 +OjEuMjUiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgZD0ibSA1Ni45NzUxNzIsMjQ5LjM0OTg3 +IHYgMi4yNzczNSBoIDIuNzE0MTk5IHYgMS4wMjQwOSBoIC0yLjcxNDE5OSB2IDQuMzU0MTggcSAw +LDAuOTgxMTIgMC4yNjQ5NzUsMS4yNjA0MiAwLjI3MjEzNiwwLjI3OTI5IDEuMDk1NzA2LDAuMjc5 +MjkgaCAxLjM1MzUxOCB2IDEuMTAyODcgaCAtMS4zNTM1MTggcSAtMS41MjUzOTQsMCAtMi4xMDU0 +NzQsLTAuNTY1NzYgUSA1NS42NTAzLDI1OC41MDk0IDU1LjY1MDMsMjU3LjAwNTQ5IHYgLTQuMzU0 +MTggaCAtMC45NjY3OTkgdiAtMS4wMjQwOSBIIDU1LjY1MDMgdiAtMi4yNzczNSB6IgogICAgICAg +ICAgIGlkPSJwYXRoMTYzIiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgZD0ibSA2OC4yODMx +NDEsMjU1LjMwODIyIHYgMC42NDQ1MyBoIC02LjA1ODYwOCBxIDAuMDg1OTQsMS4zNjA2OCAwLjgx +NjQwOSwyLjA3NjgzIDAuNzM3NjMyLDAuNzA4OTggMi4wNDgxODEsMC43MDg5OCAwLjc1OTExNyww +IDEuNDY4MTAzLC0wLjE4NjE5IDAuNzE2MTQ3LC0wLjE4NjIgMS40MTc5NzIsLTAuNTU4NiB2IDEu +MjQ2MSBxIC0wLjcwODk4NiwwLjMwMDc4IC0xLjQ1Mzc4LDAuNDU4MzMgLTAuNzQ0NzkzLDAuMTU3 +NTUgLTEuNTExMDcxLDAuMTU3NTUgLTEuOTE5Mjc1LDAgLTMuMDQzNjI3LC0xLjExNzE5IC0xLjEx +NzE5LC0xLjExNzE5IC0xLjExNzE5LC0zLjAyMjE0IDAsLTEuOTY5NCAxLjA1OTg5OSwtMy4xMjI0 +IDEuMDY3MDU5LC0xLjE2MDE2IDIuODcxNzUxLC0xLjE2MDE2IDEuNjE4NDkzLDAgMi41NTY2NDYs +MS4wNDU1OCAwLjk0NTMxNSwxLjAzODQxIDAuOTQ1MzE1LDIuODI4NzggeiBNIDY2Ljk2NTQzLDI1 +NC45MjE1IHEgLTAuMDE0MzIsLTEuMDgxMzggLTAuNjA4NzI2LC0xLjcyNTkyIC0wLjU4NzI0LC0w +LjY0NDUzIC0xLjU2MTIwMSwtMC42NDQ1MyAtMS4xMDI4NjcsMCAtMS43Njg4ODQsMC42MjMwNSAt +MC42NTg4NTYsMC42MjMwNSAtMC43NTkxMTcsMS43NTQ1NiB6IgogICAgICAgICAgIGlkPSJwYXRo +MTY1IiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgZD0ibSA3Ni44NTU0MjcsMjUxLjYyNzIy +IC0yLjkwMDM5NywzLjkwMyAzLjA1MDc4OCw0LjExNzg1IGggLTEuNTU0MDQgbCAtMi4zMzQ2NDEs +LTMuMTUxMDUgLTIuMzM0NjQxLDMuMTUxMDUgaCAtMS41NTQwNCBsIDMuMTE1MjQyLC00LjE5NjYy +IC0yLjg1MDI2NywtMy44MjQyMyBoIDEuNTU0MDQgbCAyLjEyNjk1OCwyLjg1NzQzIDIuMTI2OTU4 +LC0yLjg1NzQzIHoiCiAgICAgICAgICAgaWQ9InBhdGgxNjciIC8+CiAgICAgICAgPHBhdGgKICAg +ICAgICAgICBkPSJtIDgwLjE3MTE4OSwyNDkuMzQ5ODcgdiAyLjI3NzM1IGggMi43MTQxOTkgdiAx +LjAyNDA5IGggLTIuNzE0MTk5IHYgNC4zNTQxOCBxIDAsMC45ODExMiAwLjI2NDk3NCwxLjI2MDQy +IDAuMjcyMTM2LDAuMjc5MjkgMS4wOTU3MDYsMC4yNzkyOSBoIDEuMzUzNTE5IHYgMS4xMDI4NyBo +IC0xLjM1MzUxOSBxIC0xLjUyNTM5NCwwIC0yLjEwNTQ3NCwtMC41NjU3NiAtMC41ODAwNzksLTAu +NTcyOTEgLTAuNTgwMDc5LC0yLjA3NjgyIHYgLTQuMzU0MTggaCAtMC45NjY3OTkgdiAtMS4wMjQw +OSBoIDAuOTY2Nzk5IHYgLTIuMjc3MzUgeiIKICAgICAgICAgICBpZD0icGF0aDE2OSIgLz4KICAg +ICAgPC9nPgogICAgPC9nPgogICAgPHBhdGgKICAgICAgIGlkPSJyMSIKICAgICAgIHN0eWxlPSJm +aWxsOiMwMDAwODAiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3JlY3QzNzMyIgogICAgICAgZD0i +TSAxMDAsMjAwIEggMjAwIFYgMzAwIEggMTAwIFoiIC8+CiAgICA8cGF0aAogICAgICAgaWQ9InIy +IgogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I2ZmMDAwMDtzdHJva2Utd2lkdGg6MTYi +CiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3JlY3QzNzM0IgogICAgICAgZD0iTSAzMDAsMjAwIEgg +NTAwIFYgMzAwIEggMzAwIFoiIC8+CiAgICA8cGF0aAogICAgICAgaWQ9InIzIgogICAgICAgc3R5 +bGU9ImZpbGw6I2ZmZmYwMDtzdHJva2U6IzAwODAwMDtzdHJva2Utd2lkdGg6MTYiCiAgICAgICBp +bmtzY2FwZTpsYWJlbD0iI3JlY3QzNzQ0IgogICAgICAgZD0iTSA2NDQuOTQzMjMsMjAwIEggNzU1 +LjA1Njc3IEMgNzc5Ljk1NTMyLDIwMCA4MDAsMjE3LjM3MjA2IDgwMCwyMzguOTUwOCB2IDIyLjA5 +ODQgQyA4MDAsMjgyLjYyNzk0IDc3OS45NTUzMiwzMDAgNzU1LjA1Njc3LDMwMCBIIDY0NC45NDMy +MyBDIDYyMC4wNDQ2OCwzMDAgNjAwLDI4Mi42Mjc5NCA2MDAsMjYxLjA0OTIgViAyMzguOTUwOCBD +IDYwMCwyMTcuMzcyMDYgNjIwLjA0NDY4LDIwMCA2NDQuOTQzMjMsMjAwIFoiIC8+CiAgPC9nPgog +IDxzY3JpcHQKICAgICBuczE6dmVyc2lvbj0iMS41LjUiCiAgICAgaWQ9Ikplc3N5SW5rIj4vLyBk +dW1teQo8L3NjcmlwdD4KPC9zdmc+Cg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/a274e3a1c2d893233fa49b8ad9850098.msg b/share/extensions/tests/data/cmd/inkscape/a274e3a1c2d893233fa49b8ad9850098.msg new file mode 100644 index 0000000..ae8c52e --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/a274e3a1c2d893233fa49b8ad9850098.msg @@ -0,0 +1,18 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-dpi=1 --export-filename=Slide1.png --export-type=png Slide1.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide1.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide1.png + +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAAnAAAAJwEqCZFPAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAGFJREFUGJXlyrEJg1AYhdHzLIKg +VRBS2DuDpaO93nFSSkYxC7hBEvgtfIXOkAOX23zJ4VY+yuDnpCr/Cb5v7i8eE2StWeMqR9AFYzA+ +B/2y2pbVJqsvaZBK3AXJrJG1/toOYHQZ6KZhWDQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/b493ad11b50db40a61c857109f083621.msg b/share/extensions/tests/data/cmd/inkscape/b493ad11b50db40a61c857109f083621.msg new file mode 100644 index 0000000..84695b2 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/b493ad11b50db40a61c857109f083621.msg @@ -0,0 +1,604 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --batch-process --verb=EditSelectAllInAllLayers;EditUnlinkClone;ObjectToPath;FileSave;FileQuit input.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.svg" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.svg + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxz +dmcKICAgeG1sbnM6bnMxPSJodHRwczovL2xhdW5jaHBhZC5uZXQvamVzc3lpbmsiCiAgIHhtbG5z +OmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6 +Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9y +Zy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMu +b3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHht +bG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9k +aS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVz +cGFjZXMvaW5rc2NhcGUiCiAgIHNvZGlwb2RpOmRvY25hbWU9ImlucHV0LnN2ZyIKICAgaW5rc2Nh +cGU6dmVyc2lvbj0iMS4xLWRldiAoMmNkMzE5ZWQ3MywgMjAyMC0wMy0zMSwgY3VzdG9tKSIKICAg +aWQ9InN2ZzgiCiAgIHZlcnNpb249IjEuMSIKICAgdmlld0JveD0iMCAwIDEwMDAgMTAwMCIKICAg +aGVpZ2h0PSIxMDAwIgogICB3aWR0aD0iMTAwMCI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFk +YXRhNDEiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0i +Ij4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8 +ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0 +eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21l +dGFkYXRhPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMzMyI+CiAgICA8bWFya2VyCiAgICAgICBpbmtz +Y2FwZTppc3N0b2NrPSJ0cnVlIgogICAgICAgc3R5bGU9Im92ZXJmbG93OnZpc2libGUiCiAgICAg +ICBpZD0iQXJyb3cyTHN0YXJ0IgogICAgICAgcmVmWD0iMC4wIgogICAgICAgcmVmWT0iMC4wIgog +ICAgICAgb3JpZW50PSJhdXRvIgogICAgICAgaW5rc2NhcGU6c3RvY2tpZD0iQXJyb3cyTHN0YXJ0 +Ij4KICAgICAgPHBhdGgKICAgICAgICAgdHJhbnNmb3JtPSJzY2FsZSgxLjEpIHRyYW5zbGF0ZSgx +LDApIgogICAgICAgICBkPSJNIDguNzE4NTg3OCw0LjAzMzczNTIgTCAtMi4yMDcyODk1LDAuMDE2 +MDEzMjU2IEwgOC43MTg1ODg0LC00LjAwMTcwNzggQyA2Ljk3MzA5MDAsLTEuNjI5NjQ2OSA2Ljk4 +MzE0NzYsMS42MTU3NDQxIDguNzE4NTg3OCw0LjAzMzczNTIgeiAiCiAgICAgICAgIHN0eWxlPSJm +aWxsLXJ1bGU6ZXZlbm9kZDtzdHJva2Utd2lkdGg6MC42MjU7c3Ryb2tlLWxpbmVqb2luOnJvdW5k +O3N0cm9rZTojMDAwMDAwO3N0cm9rZS1vcGFjaXR5OjE7ZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0 +eToxIgogICAgICAgICBpZD0icGF0aDg1OSIgLz4KICAgIDwvbWFya2VyPgogIDwvZGVmcz4KICA8 +c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0id2Vic2xpY2Vy +LWxheWVyIgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiCiAgICAgaW5rc2NhcGU6 +d2luZG93LXk9IjIwIgogICAgIGlua3NjYXBlOndpbmRvdy14PSI2NyIKICAgICBpbmtzY2FwZTpj +eT0iNDgxLjE2OTg2IgogICAgIGlua3NjYXBlOmN4PSIyMDIuNzM0OSIKICAgICBpbmtzY2FwZTp6 +b29tPSIwLjY2NzUwODgiCiAgICAgaW5rc2NhcGU6c25hcC10ZXh0LWJhc2VsaW5lPSJ0cnVlIgog +ICAgIHNob3dncmlkPSJ0cnVlIgogICAgIGlkPSJiYXNlIgogICAgIGlua3NjYXBlOndpbmRvdy1o +ZWlnaHQ9Ijg3OSIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjExODgiCiAgICAgaW5rc2Nh +cGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBndWlk +ZXRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgb2JqZWN0dG9sZXJh +bmNlPSIxMCIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2 +IgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgZW1w +b3BhY2l0eT0iMC4yNTA5ODAzOSIKICAgICAgIGVtcGNvbG9yPSIjMDAwMGZmIgogICAgICAgb3Bh +Y2l0eT0iMC4yNTA5ODAzOSIKICAgICAgIGNvbG9yPSIjODA4MGZmIgogICAgICAgZW1wc3BhY2lu +Zz0iMTAiCiAgICAgICBzcGFjaW5neT0iMTAiCiAgICAgICBzcGFjaW5neD0iMTAiCiAgICAgICBp +ZD0iZ3JpZDI3IgogICAgICAgdHlwZT0ieHlncmlkIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3 +PgogIDxnCiAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5lIgogICAgIGlua3NjYXBlOmxhYmVsPSJT +bGlkZTMiCiAgICAgaWQ9IndlYnNsaWNlci1sYXllciIKICAgICBpbmtzY2FwZTpncm91cG1vZGU9 +ImxheWVyIj4KICAgIDxwYXRoCiAgICAgICBkPSJtIDY1MS4zMDg5LDM1My45MjY2MSBoIDI0OC42 +OTExMiB2IDIwMS40OTgxIEggNjUxLjMwODkgWiIKICAgICAgIHN0eWxlPSJvcGFjaXR5OjAuNTtm +aWxsOiNmZjAwMDA7c3Ryb2tlLXdpZHRoOjEuMTE5MjciCiAgICAgICBpZD0ic2xpY2VyZWN0MSI+ +CiAgICAgIDxkZXNjCiAgICAgICAgIGlkPSJkZXNjNTEiPmZvcm1hdDogcG5nCmRwaTogOTYKbGF5 +b3V0LWRpc3Bvc2l0aW9uOiBiZy1lbC1ub3JlcGVhdApsYXlvdXQtcG9zaXRpb24tYW5jaG9yOiB0 +bDwvZGVzYz4KICAgIDwvcGF0aD4KICA8L2c+CiAgPGcKICAgICBzdHlsZT0iZGlzcGxheTppbmxp +bmUiCiAgICAgaW5rc2NhcGU6bGFiZWw9IlNsaWRlMiIKICAgICBpZD0ibGF5ZXIyIgogICAgIGlu +a3NjYXBlOmdyb3VwbW9kZT0ibGF5ZXIiPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMjAwLDQ1MCBh +IDUwLDUwIDAgMCAxIC01MCw1MCA1MCw1MCAwIDAgMSAtNTAsLTUwIDUwLDUwIDAgMCAxIDUwLC01 +MCA1MCw1MCAwIDAgMSA1MCw1MCIKICAgICAgIGlua3NjYXBlOmxhYmVsPSIjcGF0aDM3MzYiCiAg +ICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmU7ZmlsbDojMDAwMDgwO3N0cm9rZTpub25lIgogICAg +ICAgaWQ9ImMxIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Ik0gNTAwLDQ1MCBBIDEwMCw1MCAwIDAg +MSA0MDAsNTAwIDEwMCw1MCAwIDAgMSAzMDAsNDUwIDEwMCw1MCAwIDAgMSA0MDAsNDAwIDEwMCw1 +MCAwIDAgMSA1MDAsNDUwIgogICAgICAgaW5rc2NhcGU6bGFiZWw9IiNwYXRoMzczOCIKICAgICAg +IHN0eWxlPSJkaXNwbGF5OmlubGluZTtmaWxsOm5vbmU7c3Ryb2tlOiNmZjAwMDA7c3Ryb2tlLXdp +ZHRoOjE2IgogICAgICAgaWQ9ImMyIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gNzgzLjA4NjM1 +LDQ3Ny44MjM4MSBhIDEwMCw1MCAwIDAgMSAtMTExLjA5ODQ4LDIwLjE3NDQyIDEwMCw1MCAwIDAg +MSAtNzEuOTYzMDEsLTQ2Ljg4MzQzIDEwMCw1MCAwIDAgMSA2Ny43MTEyNywtNDguNDQwOTEgMTAw +LDUwIDAgMCAxIDExMi43ODY4LDE3LjY3NzkzIEwgNzAwLDQ1MCBaIgogICAgICAgaW5rc2NhcGU6 +bGFiZWw9IiNwYXRoMzc0MCIKICAgICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZTtmaWxsOiNmZmZm +MDA7c3Ryb2tlOiMwMDgwMDA7c3Ryb2tlLXdpZHRoOjE2IgogICAgICAgaWQ9ImMzIiAvPgogICAg +PHBhdGgKICAgICAgIGlua3NjYXBlOmxhYmVsPSIjcGF0aDM3NDYiCiAgICAgICBpbmtzY2FwZTpj +b25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgaWQ9InAxIgogICAgICAgZD0iTSAxMDAsNjAw +IDIwMCw3MDAgMzAwLDYwMCA0MDAsNzAwIgogICAgICAgc3R5bGU9ImRpc3BsYXk6aW5saW5lO2Zp +bGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MTA7bWFya2VyLXN0YXJ0OnVybCgj +QXJyb3cyTHN0YXJ0KSIgLz4KICAgIDxwYXRoCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3BhdGgz +NzQ4IgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIGlkPSJw +MiIKICAgICAgIGQ9Im0gNTAwLDYwMCBjIDAsMCAwLDEwMCAxMDAsMTAwIDEwMCwwIDAsLTEwMCAx +MDAsLTEwMCAxMDAsMCAxMDAsMTAwIDEwMCwxMDAiCiAgICAgICBzdHlsZT0iZGlzcGxheTppbmxp +bmU7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoxMCIgLz4KICAgIDxwYXRo +CiAgICAgICBkPSJtIDI0NC44MzMyLDg4OS4xNDAwNSAtNDUuMzM4ODcsLTguMTM0NDYgLTMyLjQw +NDI4LDMyLjczNzUzIC02LjI3NDE1LC00NS42MzM1MiAtNDEuMTQ4NzIsLTIwLjcwMTg0IDQxLjQ2 +MTI0LC0yMC4wNjg2MSA2Ljk3Mjk3LC00NS41MzE5NyAzMS44OTg2MSwzMy4yMzA0NCA0NS40NTgy +NCwtNy40Mzg0NyAtMjEuNzQ2ODEsNDAuNjA2MTUgeiIKICAgICAgIGlua3NjYXBlOnRyYW5zZm9y +bS1jZW50ZXIteT0iLTAuMTY0MzAxMzciCiAgICAgICBpbmtzY2FwZTp0cmFuc2Zvcm0tY2VudGVy +LXg9IjYuNDY3MzAxMSIKICAgICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZTtmaWxsOiNmZmZmMDA7 +c3Ryb2tlOiMwMDgwMDA7c3Ryb2tlLXdpZHRoOjEwIgogICAgICAgaWQ9InMxIiAvPgogICAgPHBh +dGgKICAgICAgIGQ9Im0gNDQ0LjgzMzE5LDg5Mi4xMzYyNiAtNDUuMzM4ODgsLTguMTM0NDUgLTMy +LjQwNDI3LDMyLjczNzUzIC02LjI3NDE2LC00NS42MzM1MiAtNDEuMTQ4NzEsLTIwLjcwMTg0IDQx +LjQ2MTI0LC0yMC4wNjg2MSA2Ljk3Mjk2LC00NS41MzE5NyAzMS44OTg2MSwzMy4yMzA0MyA0NS40 +NTgyNSwtNy40Mzg0NiAtMjEuNzQ2ODIsNDAuNjA2MTUgeiIKICAgICAgIGlua3NjYXBlOnRyYW5z +Zm9ybS1jZW50ZXIteT0iLTAuMTY0MzAxMzciCiAgICAgICBpbmtzY2FwZTp0cmFuc2Zvcm0tY2Vu +dGVyLXg9IjYuNDY3MzAxMSIKICAgICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZTtmaWxsOiNmZmZm +MDA7c3Ryb2tlOiMwMDgwMDA7c3Ryb2tlLXdpZHRoOjEwIgogICAgICAgaWQ9InUxIiAvPgogIDwv +Zz4KICA8ZwogICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZSIKICAgICBpZD0ibGF5ZXIxIgogICAg +IGlua3NjYXBlOmdyb3VwbW9kZT0ibGF5ZXIiCiAgICAgaW5rc2NhcGU6bGFiZWw9IlNsaWRlMSI+ +CiAgICA8ZwogICAgICAgaW5rc2NhcGU6bGFiZWw9IiN0ZXh0MTIiCiAgICAgICBzdHlsZT0iZm9u +dC1zaXplOjE0LjY2NjdweDtsaW5lLWhlaWdodDoxLjI1O2ZvbnQtZmFtaWx5OnNhbnMtc2VyaWY7 +ZmlsbDojMDAwMDAwO3N0cm9rZTpub25lIgogICAgICAgaWQ9InQxIgogICAgICAgYXJpYS1sYWJl +bD0iSGVsbG8gV29ybGQiPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0aDUyIgogICAgICAg +ICBkPSJtIDEwMS40Mzk0Niw4OS4zMDc5MTggaCAxLjQ0NjYxIHYgNC4zODI4MjMgaCA1LjI1NjUz +IHYgLTQuMzgyODIzIGggMS40NDY2MSBWIDEwMCBoIC0xLjQ0NjYxIHYgLTUuMDkxODA5IGggLTUu +MjU2NTMgViAxMDAgaCAtMS40NDY2MSB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0 +aDU0IgogICAgICAgICBkPSJtIDExOS4yNzE1Myw5NS42NjAxNDYgdiAwLjY0NDUzMyBoIC02LjA1 +ODYxIHEgMC4wODU5LDEuMzYwNjggMC44MTY0MSwyLjA3NjgyOCAwLjczNzYzLDAuNzA4OTg2IDIu +MDQ4MTgsMC43MDg5ODYgMC43NTkxMiwwIDEuNDY4MSwtMC4xODYxOTkgMC43MTYxNSwtMC4xODYx +OTggMS40MTc5OCwtMC41NTg1OTUgdiAxLjI0NjA5NyBxIC0wLjcwODk5LDAuMzAwNzgyIC0xLjQ1 +Mzc4LDAuNDU4MzM0IC0wLjc0NDgsMC4xNTc1NSAtMS41MTEwOCwwLjE1NzU1IC0xLjkxOTI3LDAg +LTMuMDQzNjIsLTEuMTE3MTg3IC0xLjExNzE5LC0xLjExNzE5IC0xLjExNzE5LC0zLjAyMjE0MyAw +LC0xLjk2OTQwNSAxLjA1OTksLTMuMTIyNDAzIDEuMDY3MDYsLTEuMTYwMTU5IDIuODcxNzUsLTEu +MTYwMTU5IDEuNjE4NDksMCAyLjU1NjY0LDEuMDQ1NTc2IDAuOTQ1MzIsMS4wMzg0MTQgMC45NDUz +MiwyLjgyODc4MiB6IG0gLTEuMzE3NzEsLTAuMzg2NzE5IHEgLTAuMDE0MywtMS4wODEzODMgLTAu +NjA4NzMsLTEuNzI1OTE2IC0wLjU4NzI0LC0wLjY0NDUzMyAtMS41NjEyLC0wLjY0NDUzMyAtMS4x +MDI4NywwIC0xLjc2ODg4LDAuNjIzMDQ5IC0wLjY1ODg2LDAuNjIzMDQ4IC0wLjc1OTEyLDEuNzU0 +NTYxIHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgIGQ9Im0g +MTIxLjQzNDI5LDg4Ljg1Njc0NSBoIDEuMzE3NzIgViAxMDAgaCAtMS4zMTc3MiB6IiAvPgogICAg +ICA8cGF0aAogICAgICAgICBpZD0icGF0aDU4IgogICAgICAgICBkPSJtIDEyNS41MDIwMSw4OC44 +NTY3NDUgaCAxLjMxNzcxIFYgMTAwIGggLTEuMzE3NzEgeiIgLz4KICAgICAgPHBhdGgKICAgICAg +ICAgaWQ9InBhdGg2MCIKICAgICAgICAgZD0ibSAxMzIuNjc3ODEsOTIuOTAyOTc4IHEgLTEuMDU5 +OSwwIC0xLjY3NTc5LDAuODMwNzMyIC0wLjYxNTg4LDAuODIzNTY5IC0wLjYxNTg4LDIuMjYzMDI2 +IDAsMS40Mzk0NTYgMC42MDg3MiwyLjI3MDE4NyAwLjYxNTg5LDAuODIzNTcgMS42ODI5NSwwLjgy +MzU3IDEuMDUyNzQsMCAxLjY2ODYyLC0wLjgzMDczMSAwLjYxNTg5LC0wLjgzMDczMSAwLjYxNTg5 +LC0yLjI2MzAyNiAwLC0xLjQyNTEzNCAtMC42MTU4OSwtMi4yNTU4NjUgLTAuNjE1ODgsLTAuODM3 +ODkzIC0xLjY2ODYyLC0wLjgzNzg5MyB6IG0gMCwtMS4xMTcxOSBxIDEuNzE4NzUsMCAyLjY5OTg4 +LDEuMTE3MTkgMC45ODExMiwxLjExNzE5MSAwLjk4MTEyLDMuMDkzNzU4IDAsMS45Njk0MDUgLTAu +OTgxMTIsMy4wOTM3NTcgLTAuOTgxMTMsMS4xMTcxODcgLTIuNjk5ODgsMS4xMTcxODcgLTEuNzI1 +OTIsMCAtMi43MDcwNCwtMS4xMTcxODcgLTAuOTczOTYsLTEuMTI0MzUyIC0wLjk3Mzk2LC0zLjA5 +Mzc1NyAwLC0xLjk3NjU2NyAwLjk3Mzk2LC0zLjA5Mzc1OCAwLjk4MTEyLC0xLjExNzE5IDIuNzA3 +MDQsLTEuMTE3MTkgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg2MiIKICAgICAg +ICAgZD0ibSAxNDIuMzA5OTksODkuMzA3OTE4IGggMS40NjA5NCBsIDIuMjQ4NzEsOS4wMzc3ODEg +Mi4yNDE1NCwtOS4wMzc3ODEgaCAxLjYyNTY1IGwgMi4yNDg3MSw5LjAzNzc4MSAyLjI0MTU0LC05 +LjAzNzc4MSBoIDEuNDY4MSBMIDE1My4xNTk2MywxMDAgaCAtMS44MTkwMiBMIDE0OS4wODQ3NSw5 +MC43MTg3MjkgMTQ2LjgwNzQsMTAwIGggLTEuODE5MDEgeiIgLz4KICAgICAgPHBhdGgKICAgICAg +ICAgaWQ9InBhdGg2NCIKICAgICAgICAgZD0ibSAxNTkuOTQ4NzEsOTIuOTAyOTc4IHEgLTEuMDU5 +OSwwIC0xLjY3NTc5LDAuODMwNzMyIC0wLjYxNTg5LDAuODIzNTY5IC0wLjYxNTg5LDIuMjYzMDI2 +IDAsMS40Mzk0NTYgMC42MDg3MywyLjI3MDE4NyAwLjYxNTg5LDAuODIzNTcgMS42ODI5NSwwLjgy +MzU3IDEuMDUyNzMsMCAxLjY2ODYyLC0wLjgzMDczMSAwLjYxNTg5LC0wLjgzMDczMSAwLjYxNTg5 +LC0yLjI2MzAyNiAwLC0xLjQyNTEzNCAtMC42MTU4OSwtMi4yNTU4NjUgLTAuNjE1ODksLTAuODM3 +ODkzIC0xLjY2ODYyLC0wLjgzNzg5MyB6IG0gMCwtMS4xMTcxOSBxIDEuNzE4NzUsMCAyLjY5OTg3 +LDEuMTE3MTkgMC45ODExMiwxLjExNzE5MSAwLjk4MTEyLDMuMDkzNzU4IDAsMS45Njk0MDUgLTAu +OTgxMTIsMy4wOTM3NTcgLTAuOTgxMTIsMS4xMTcxODcgLTIuNjk5ODcsMS4xMTcxODcgLTEuNzI1 +OTIsMCAtMi43MDcwNCwtMS4xMTcxODcgLTAuOTczOTYsLTEuMTI0MzUyIC0wLjk3Mzk2LC0zLjA5 +Mzc1NyAwLC0xLjk3NjU2NyAwLjk3Mzk2LC0zLjA5Mzc1OCAwLjk4MTEyLC0xLjExNzE5IDIuNzA3 +MDQsLTEuMTE3MTkgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg2NiIKICAgICAg +ICAgZD0ibSAxNzAuNDU0NTksOTMuMjEwOTIyIHEgLTAuMjIyLC0wLjEyODkwNyAtMC40ODY5OCwt +MC4xODYxOTggLTAuMjU3ODEsLTAuMDY0NDUgLTAuNTcyOTIsLTAuMDY0NDUgLTEuMTE3MTksMCAt +MS43MTg3NSwwLjczMDQ3MSAtMC41OTQ0LDAuNzIzMzA5IC0wLjU5NDQsMi4wODM5ODkgViAxMDAg +aCAtMS4zMjQ4OCB2IC04LjAyMDg1MiBoIDEuMzI0ODggdiAxLjI0NjA5NyBxIDAuNDE1MzYsLTAu +NzMwNDcxIDEuMDgxMzgsLTEuMDgxMzgzIDAuNjY2MDIsLTAuMzU4MDc0IDEuNjE4NDksLTAuMzU4 +MDc0IDAuMTM2MDcsMCAwLjMwMDc4LDAuMDIxNDggMC4xNjQ3MiwwLjAxNDMyIDAuMzY1MjQsMC4w +NTAxMyB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0aDY4IgogICAgICAgICBkPSJt +IDE3MS44NTEwNyw4OC44NTY3NDUgaCAxLjMxNzcyIFYgMTAwIGggLTEuMzE3NzIgeiIgLz4KICAg +ICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg3MCIKICAgICAgICAgZD0ibSAxODEuMTk2OCw5My4x +OTY1OTkgdiAtNC4zMzk4NTQgaCAxLjMxNzcxIFYgMTAwIGggLTEuMzE3NzEgdiAtMS4yMDMxMjgg +cSAtMC40MTUzNywwLjcxNjE0OCAtMS4wNTI3NCwxLjA2NzA2IC0wLjYzMDIxLDAuMzQzNzQ4IC0x +LjUxODIzLDAuMzQzNzQ4IC0xLjQ1Mzc4LDAgLTIuMzcwNDUsLTEuMTYwMTU2IC0wLjkwOTUsLTEu +MTYwMTU5IC0wLjkwOTUsLTMuMDUwNzg4IDAsLTEuODkwNjMgMC45MDk1LC0zLjA1MDc4OSAwLjkx +NjY3LC0xLjE2MDE1OSAyLjM3MDQ1LC0xLjE2MDE1OSAwLjg4ODAyLDAgMS41MTgyMywwLjM1MDkx +MyAwLjYzNzM3LDAuMzQzNzUgMS4wNTI3NCwxLjA1OTg5OCB6IG0gLTQuNDkwMjQsMi44MDAxMzcg +cSAwLDEuNDUzNzc5IDAuNTk0NCwyLjI4NDUxIDAuNjAxNTYsMC44MjM1NyAxLjY0NzE0LDAuODIz +NTcgMS4wNDU1NywwIDEuNjQ3MTQsLTAuODIzNTcgMC42MDE1NiwtMC44MzA3MzEgMC42MDE1Niwt +Mi4yODQ1MSAwLC0xLjQ1Mzc4IC0wLjYwMTU2LC0yLjI3NzM0OSAtMC42MDE1NywtMC44MzA3MzEg +LTEuNjQ3MTQsLTAuODMwNzMxIC0xLjA0NTU4LDAgLTEuNjQ3MTQsMC44MzA3MzEgLTAuNTk0NCww +LjgyMzU2OSAtMC41OTQ0LDIuMjc3MzQ5IHoiIC8+CiAgICA8L2c+CiAgICA8ZwogICAgICAgaW5r +c2NhcGU6bGFiZWw9IiNmbG93Um9vdDE0IgogICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo0MHB4O2xp +bmUtaGVpZ2h0OjEuMjU7Zm9udC1mYW1pbHk6c2Fucy1zZXJpZjtmaWxsOiMwMDAwMDA7c3Ryb2tl +Om5vbmUiCiAgICAgICBpZD0idDQiCiAgICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjI2NDU4MzMz +LDAsMCwwLjI2NDU4MzMzLDM3Mi4wMjk2MSwyOC45MDQ1MDUpIgogICAgICAgYXJpYS1sYWJlbD0i +ZmxvdyB0ZXh0IHdoaWNoIHdyYXBzIj4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg3MyIK +ICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9Im0gMTIxLjU3 +NjA3LDIyNi41OTEyNSBoIDEzLjg1ODI4IHYgNDIuMTE2MTYgaCAtNS4wMDczOSB2IC0zNy45NzQ5 +MiBoIC04LjkwNTAyIHEgLTIuNjc5NjMsMCAtMy43MzUyNCwxLjA4MjY4IC0xLjAyODU0LDEuMDgy +NjggLTEuMDI4NTQsMy44OTc2NCB2IDIuNjc5NjIgaCA4LjIwMTI4IHYgMy44NzA1OCBoIC04LjIw +MTI4IHYgMjYuNDQ0NCBoIC01LjAwNzM5IHYgLTI2LjQ0NDQgaCAtNC43NjM3OCB2IC0zLjg3MDU4 +IGggNC43NjM3OCB2IC0yLjExMTIyIHEgMCwtNS4wNjE1MiAyLjM1NDgzLC03LjM2MjIxIDIuMzU0 +ODIsLTIuMzI3NzUgNy40NzA0NywtMi4zMjc3NSB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBp +ZD0icGF0aDc1IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAgICAg +ZD0ibSAxNTcuNjU2MzEsMjQxLjg4NDA3IHEgLTQuMDA1OTEsMCAtNi4zMzM2NiwzLjEzOTc3IC0y +LjMyNzc2LDMuMTEyNjkgLTIuMzI3NzYsOC41NTMxNSAwLDUuNDQwNDYgMi4zMDA2OSw4LjU4MDIy +IDIuMzI3NzYsMy4xMTI3IDYuMzYwNzMsMy4xMTI3IDMuOTc4ODQsMCA2LjMwNjYsLTMuMTM5Nzcg +Mi4zMjc3NiwtMy4xMzk3NiAyLjMyNzc2LC04LjU1MzE1IDAsLTUuMzg2MzIgLTIuMzI3NzYsLTgu +NTI2MDkgLTIuMzI3NzYsLTMuMTY2ODMgLTYuMzA2NiwtMy4xNjY4MyB6IG0gMCwtNC4yMjI0NCBx +IDYuNDk2MDcsMCAxMC4yMDQyNCw0LjIyMjQ0IDMuNzA4MTcsNC4yMjI0NCAzLjcwODE3LDExLjY5 +MjkyIDAsNy40NDM0MSAtMy43MDgxNywxMS42OTI5MiAtMy43MDgxNyw0LjIyMjQ0IC0xMC4yMDQy +NCw0LjIyMjQ0IC02LjUyMzEzLDAgLTEwLjIzMTMsLTQuMjIyNDQgLTMuNjgxMTEsLTQuMjQ5NTEg +LTMuNjgxMTEsLTExLjY5MjkyIDAsLTcuNDcwNDggMy42ODExMSwtMTEuNjkyOTIgMy43MDgxNywt +NC4yMjI0NCAxMC4yMzEzLC00LjIyMjQ0IHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJw +YXRoNzciCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBkPSJt +IDE3Ni45MDA5MSwyMzguMzkyNDMgaCA0Ljk4MDMyIGwgNi4yMjUzOSwyMy42NTY1MSA2LjE5ODMz +LC0yMy42NTY1MSBoIDUuODczNTMgbCA2LjIyNTQsMjMuNjU2NTEgNi4xOTgzMywtMjMuNjU2NTEg +aCA0Ljk4MDMxIGwgLTcuOTMwNjEsMzAuMzE0OTggaCAtNS44NzM1MyBsIC02LjUyMzEzLC0yNC44 +NDc0NSAtNi41NTAyLDI0Ljg0NzQ1IGggLTUuODczNTMgeiIgLz4KICAgICAgPHBhdGgKICAgICAg +ICAgaWQ9InBhdGg3OSIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAg +ICAgIGQ9Im0gMjQ3LjczNTEsMjI5Ljc4NTE1IHYgOC42MDcyOCBoIDEwLjI1ODM3IHYgMy44NzA1 +OCBIIDI0Ny43MzUxIHYgMTYuNDU2NyBxIDAsMy43MDgxNyAxLjAwMTQ3LDQuNzYzNzggMS4wMjg1 +NSwxLjA1NTYxIDQuMTQxMjQsMS4wNTU2MSBoIDUuMTE1NjYgdiA0LjE2ODMxIGggLTUuMTE1NjYg +cSAtNS43NjUyNSwwIC03Ljk1NzY4LC0yLjEzODI5IC0yLjE5MjQyLC0yLjE2NTM1IC0yLjE5MjQy +LC03Ljg0OTQxIHYgLTE2LjQ1NjcgaCAtMy42NTQwNCB2IC0zLjg3MDU4IGggMy42NTQwNCB2IC04 +LjYwNzI4IHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoODEiCiAgICAgICAgIHN0 +eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBkPSJtIDI5MC41MDA4NywyNTIuMzA0 +ODQgdiAyLjQzNjAzIGggLTIyLjg5ODY0IHEgMC4zMjQ4MSw1LjE0MjcyIDMuMDg1NjQsNy44NDk0 +MSAyLjc4Nzg5LDIuNjc5NjMgNy43NDExNCwyLjY3OTYzIDIuODY5MSwwIDUuNTQ4NzMsLTAuNzAz +NzQgMi43MDY2OSwtMC43MDM3NCA1LjM1OTI1LC0yLjExMTIyIHYgNC43MDk2NSBxIC0yLjY3OTYz +LDEuMTM2ODEgLTUuNDk0NTksMS43MzIyOCAtMi44MTQ5NiwwLjU5NTQ3IC01LjcxMTEyLDAuNTk1 +NDcgLTcuMjUzOTQsMCAtMTEuNTAzNDYsLTQuMjIyNDQgLTQuMjIyNDQsLTQuMjIyNDQgLTQuMjIy +NDQsLTExLjQyMjI1IDAsLTcuNDQzNDEgNC4wMDU5MSwtMTEuODAxMTkgNC4wMzI5NywtNC4zODQ4 +NCAxMC44NTM4NCwtNC4zODQ4NCA2LjExNzEzLDAgOS42NjI5LDMuOTUxNzcgMy41NzI4NCwzLjky +NDcxIDMuNTcyODQsMTAuNjkxNDQgeiBtIC00Ljk4MDMyLC0xLjQ2MTYxIHEgLTAuMDU0MSwtNC4w +ODcxMSAtMi4zMDA2OSwtNi41MjMxMyAtMi4yMTk0OSwtMi40MzYwMyAtNS45MDA1OSwtMi40MzYw +MyAtNC4xNjgzMSwwIC02LjY4NTU0LDIuMzU0ODIgLTIuNDkwMTYsMi4zNTQ4MyAtMi44NjkwOSw2 +LjYzMTQxIHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoODMiCiAgICAgICAgIHN0 +eWxlPSJmb250LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBkPSJtIDMyMi45MDAwMSwyMzguMzky +NDMgLTEwLjk2MjEyLDE0Ljc1MTQ5IDExLjUzMDUyLDE1LjU2MzQ5IGggLTUuODczNTIgbCAtOC44 +MjM4MywtMTEuOTA5NDUgLTguODIzODIsMTEuOTA5NDUgaCAtNS44NzM1MyBsIDExLjc3NDEyLC0x +NS44NjEyMyAtMTAuNzcyNjQsLTE0LjQ1Mzc1IGggNS44NzM1MiBsIDguMDM4ODksMTAuNzk5NzIg +OC4wMzg4OCwtMTAuNzk5NzIgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg4NSIK +ICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9Im0gMzM1LjQz +MTk5LDIyOS43ODUxNSB2IDguNjA3MjggaCAxMC4yNTgzOCB2IDMuODcwNTggaCAtMTAuMjU4Mzgg +diAxNi40NTY3IHEgMCwzLjcwODE3IDEuMDAxNDgsNC43NjM3OCAxLjAyODU1LDEuMDU1NjEgNC4x +NDEyNCwxLjA1NTYxIGggNS4xMTU2NiB2IDQuMTY4MzEgaCAtNS4xMTU2NiBxIC01Ljc2NTI1LDAg +LTcuOTU3NjgsLTIuMTM4MjkgLTIuMTkyNDIsLTIuMTY1MzUgLTIuMTkyNDIsLTcuODQ5NDEgdiAt +MTYuNDU2NyBoIC0zLjY1NDA0IHYgLTMuODcwNTggaCAzLjY1NDA0IHYgLTguNjA3MjggeiIgLz4K +ICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg4NyIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6 +ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9Im0gMTA4LjA0MjYsMzA3LjY4MzgyIGggNC45ODAzMiBs +IDYuMjI1NCwyMy42NTY1MSA2LjE5ODMzLC0yMy42NTY1MSBoIDUuODczNTIgbCA2LjIyNTQsMjMu +NjU2NTEgNi4xOTgzMywtMjMuNjU2NTEgaCA0Ljk4MDMyIGwgLTcuOTMwNjIsMzAuMzE0OTcgaCAt +NS44NzM1MiBsIC02LjUyMzE0LC0yNC44NDc0NSAtNi41NTAyLDI0Ljg0NzQ1IGggLTUuODczNTIg +eiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg4OSIKICAgICAgICAgc3R5bGU9ImZv +bnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9Im0gMTgxLjUwMjI5LDMxOS43MDE1NCB2IDE4 +LjI5NzI1IGggLTQuOTgwMzIgdiAtMTguMTM0ODUgcSAwLC00LjMwMzY0IC0xLjY3ODE1LC02LjQ0 +MTkzIC0xLjY3ODE1LC0yLjEzODI5IC01LjAzNDQ1LC0yLjEzODI5IC00LjAzMjk4LDAgLTYuMzYw +NzQsMi41NzEzNiAtMi4zMjc3NSwyLjU3MTM2IC0yLjMyNzc1LDcuMDEwMzQgdiAxNy4xMzMzNyBo +IC01LjAwNzM5IHYgLTQyLjExNjE2IGggNS4wMDczOSB2IDE2LjUxMDgzIHEgMS43ODY0MiwtMi43 +MzM3NiA0LjE5NTM3LC00LjA4NzEgMi40MzYwMywtMS4zNTMzNSA1LjYwMjg2LC0xLjM1MzM1IDUu +MjIzOTIsMCA3LjkwMzU1LDMuMjQ4MDMgMi42Nzk2MywzLjIyMDk3IDIuNjc5NjMsOS41MDA1IHoi +IC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoOTEiCiAgICAgICAgIHN0eWxlPSJmb250 +LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBkPSJtIDE5MS40ODk5OSwzMDcuNjgzODIgaCA0Ljk4 +MDMyIHYgMzAuMzE0OTcgaCAtNC45ODAzMiB6IG0gMCwtMTEuODAxMTkgaCA0Ljk4MDMyIHYgNi4z +MDY2IGggLTQuOTgwMzIgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGg5MyIKICAg +ICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9Im0gMjI4LjY3OTk3 +LDMwOC44NDc3IHYgNC42NTU1MSBxIC0yLjExMTIyLC0xLjE2Mzg4IC00LjI0OTUxLC0xLjczMjI4 +IC0yLjExMTIyLC0wLjU5NTQ4IC00LjI3NjU4LC0wLjU5NTQ4IC00Ljg0NDk4LDAgLTcuNTI0NjEs +My4wODU2MyAtMi42Nzk2MywzLjA1ODU3IC0yLjY3OTYzLDguNjA3MjkgMCw1LjU0ODczIDIuNjc5 +NjMsOC42MzQzNiAyLjY3OTYzLDMuMDU4NTYgNy41MjQ2MSwzLjA1ODU2IDIuMTY1MzYsMCA0LjI3 +NjU4LC0wLjU2ODQgMi4xMzgyOSwtMC41OTU0OCA0LjI0OTUxLC0xLjc1OTM2IHYgNC42MDEzOSBx +IC0yLjA4NDE2LDAuOTc0NDEgLTQuMzMwNzEsMS40NjE2MSAtMi4yMTk0OSwwLjQ4NzIxIC00Ljcz +NjcyLDAuNDg3MjEgLTYuODQ3OTQsMCAtMTAuODgwOTEsLTQuMzAzNjUgLTQuMDMyOTcsLTQuMzAz +NjQgLTQuMDMyOTcsLTExLjYxMTcyIDAsLTcuNDE2MzQgNC4wNjAwNCwtMTEuNjY1ODUgNC4wODcx +MSwtNC4yNDk1MSAxMS4xNzg2NSwtNC4yNDk1MSAyLjMwMDY5LDAgNC40OTMxMSwwLjQ4NzIgMi4x +OTI0MiwwLjQ2MDE0IDQuMjQ5NTEsMS40MDc0OSB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBp +ZD0icGF0aDk1IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAgICAg +ZD0ibSAyNjIuNTk0ODUsMzE5LjcwMTU0IHYgMTguMjk3MjUgaCAtNC45ODAzMSB2IC0xOC4xMzQ4 +NSBxIDAsLTQuMzAzNjQgLTEuNjc4MTYsLTYuNDQxOTMgLTEuNjc4MTUsLTIuMTM4MjkgLTUuMDM0 +NDUsLTIuMTM4MjkgLTQuMDMyOTcsMCAtNi4zNjA3MywyLjU3MTM2IC0yLjMyNzc2LDIuNTcxMzYg +LTIuMzI3NzYsNy4wMTAzNCB2IDE3LjEzMzM3IGggLTUuMDA3MzggdiAtNDIuMTE2MTYgaCA1LjAw +NzM4IHYgMTYuNTEwODMgcSAxLjc4NjQyLC0yLjczMzc2IDQuMTk1MzgsLTQuMDg3MSAyLjQzNjAz +LC0xLjM1MzM1IDUuNjAyODYsLTEuMzUzMzUgNS4yMjM5MiwwIDcuOTAzNTUsMy4yNDgwMyAyLjY3 +OTYyLDMuMjIwOTcgMi42Nzk2Miw5LjUwMDUgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9 +InBhdGg5NyIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTo1NS40MzMxcHgiCiAgICAgICAgIGQ9 +Im0gMTA4LjA0MjYsMzc2Ljk3NTIgaCA0Ljk4MDMyIGwgNi4yMjU0LDIzLjY1NjUxIDYuMTk4MzMs +LTIzLjY1NjUxIGggNS44NzM1MiBsIDYuMjI1NCwyMy42NTY1MSA2LjE5ODMzLC0yMy42NTY1MSBo +IDQuOTgwMzIgbCAtNy45MzA2MiwzMC4zMTQ5OCBoIC01Ljg3MzUyIGwgLTYuNTIzMTQsLTI0Ljg0 +NzQ2IC02LjU1MDIsMjQuODQ3NDYgaCAtNS44NzM1MiB6IiAvPgogICAgICA8cGF0aAogICAgICAg +ICBpZD0icGF0aDk5IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFweCIKICAgICAg +ICAgZD0ibSAxNzMuODY5NDEsMzgxLjYzMDcxIHEgLTAuODM5MDgsLTAuNDg3MiAtMS44NDA1NSwt +MC43MDM3NCAtMC45NzQ0MSwtMC4yNDM2IC0yLjE2NTM2LC0wLjI0MzYgLTQuMjIyNDQsMCAtNi40 +OTYwNywyLjc2MDgzIC0yLjI0NjU1LDIuNzMzNzYgLTIuMjQ2NTUsNy44NzY0OCB2IDE1Ljk2OTUg +aCAtNS4wMDczOSBWIDM3Ni45NzUyIGggNS4wMDczOSB2IDQuNzA5NjUgcSAxLjU2OTg4LC0yLjc2 +MDgzIDQuMDg3MTEsLTQuMDg3MTEgMi41MTcyMiwtMS4zNTMzNSA2LjExNzEyLC0xLjM1MzM1IDAu +NTE0MjgsMCAxLjEzNjgyLDAuMDgxMiAwLjYyMjU0LDAuMDU0MSAxLjM4MDQxLDAuMTg5NDcgeiIg +Lz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgxMDEiCiAgICAgICAgIHN0eWxlPSJmb250 +LXNpemU6NTUuNDMzMXB4IgogICAgICAgICBkPSJtIDE5Mi45MjQ1MywzOTIuMDUxNDkgcSAtNi4w +MzU5MywwIC04LjM2MzY4LDEuMzgwNDEgLTIuMzI3NzYsMS4zODA0MSAtMi4zMjc3Niw0LjcwOTY1 +IDAsMi42NTI1NiAxLjczMjI4LDQuMjIyNDQgMS43NTkzNiwxLjU0MjgyIDQuNzYzNzksMS41NDI4 +MiA0LjE0MTI0LDAgNi42MzE0LC0yLjkyMzIzIDIuNTE3MjIsLTIuOTUwMyAyLjUxNzIyLC03Ljgy +MjM1IHYgLTEuMTA5NzQgeiBtIDkuOTMzNTcsLTIuMDU3MDkgdiAxNy4yOTU3OCBoIC00Ljk4MDMy +IHYgLTQuNjAxMzggcSAtMS43MDUyMSwyLjc2MDgyIC00LjI0OTUxLDQuMDg3MSAtMi41NDQyOSwx +LjI5OTIyIC02LjIyNTM5LDEuMjk5MjIgLTQuNjU1NTIsMCAtNy40MTYzNSwtMi41OTg0MyAtMi43 +MzM3NiwtMi42MjU0OSAtMi43MzM3NiwtNy4wMTAzNCAwLC01LjExNTY1IDMuNDEwNDQsLTcuNzE0 +MDggMy40Mzc1LC0yLjU5ODQyIDEwLjIzMTMsLTIuNTk4NDIgaCA2Ljk4MzI3IHYgLTAuNDg3MjEg +cSAwLC0zLjQzNzUgLTIuMjczNjIsLTUuMzA1MTIgLTIuMjQ2NTYsLTEuODk0NjkgLTYuMzMzNjYs +LTEuODk0NjkgLTIuNTk4NDMsMCAtNS4wNjE1MiwwLjYyMjU0IC0yLjQ2MzA5LDAuNjIyNTQgLTQu +NzM2NzIsMS44Njc2MiB2IC00LjYwMTM4IHEgMi43MzM3NiwtMS4wNTU2MSA1LjMwNTEyLC0xLjU2 +OTg4IDIuNTcxMzYsLTAuNTQxMzQgNS4wMDczOSwtMC41NDEzNCA2LjU3NzI2LDAgOS44MjUzLDMu +NDEwNDQgMy4yNDgwMywzLjQxMDQzIDMuMjQ4MDMsMTAuMzM5NTcgeiIgLz4KICAgICAgPHBhdGgK +ICAgICAgICAgaWQ9InBhdGgxMDMiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6NTUuNDMzMXB4 +IgogICAgICAgICBkPSJtIDIxNy45NjE0Niw0MDIuNzQyOTMgdiAxNi4wNzc3NiBoIC01LjAwNzM4 +IFYgMzc2Ljk3NTIgaCA1LjAwNzM4IHYgNC42MDEzOCBxIDEuNTY5ODgsLTIuNzA2NyAzLjk1MTc3 +LC00LjAwNTkxIDIuNDA4OTYsLTEuMzI2MjggNS43MzgyLC0xLjMyNjI4IDUuNTIxNjUsMCA4Ljk1 +OTE2LDQuMzg0ODUgMy40NjQ1Niw0LjM4NDg0IDMuNDY0NTYsMTEuNTMwNTEgMCw3LjE0NTY4IC0z +LjQ2NDU2LDExLjUzMDUyIC0zLjQzNzUxLDQuMzg0ODUgLTguOTU5MTYsNC4zODQ4NSAtMy4zMjky +NCwwIC01LjczODIsLTEuMjk5MjIgLTIuMzgxODksLTEuMzI2MjggLTMuOTUxNzcsLTQuMDMyOTcg +eiBtIDE2Ljk0MzkxLC0xMC41ODMxOCBxIDAsLTUuNDk0NTkgLTIuMjczNjMsLTguNjA3MjggLTIu +MjQ2NTUsLTMuMTM5NzcgLTYuMTk4MzMsLTMuMTM5NzcgLTMuOTUxNzcsMCAtNi4yMjUzOSwzLjEz +OTc3IC0yLjI0NjU2LDMuMTEyNjkgLTIuMjQ2NTYsOC42MDcyOCAwLDUuNDk0NTkgMi4yNDY1Niw4 +LjYzNDM2IDIuMjczNjIsMy4xMTI3IDYuMjI1MzksMy4xMTI3IDMuOTUxNzgsMCA2LjE5ODMzLC0z +LjExMjcgMi4yNzM2MywtMy4xMzk3NyAyLjI3MzYzLC04LjYzNDM2IHoiIC8+CiAgICAgIDxwYXRo +CiAgICAgICAgIGlkPSJwYXRoMTA1IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjU1LjQzMzFw +eCIKICAgICAgICAgZD0ibSAyNjcuNjU2MzgsMzc3Ljg2ODQxIHYgNC43MDk2NSBxIC0yLjExMTIy +LC0xLjA4MjY4IC00LjM4NDg1LC0xLjYyNDAyIC0yLjI3MzYyLC0wLjU0MTM0IC00LjcwOTY1LC0w +LjU0MTM0IC0zLjcwODE3LDAgLTUuNTc1NzksMS4xMzY4MSAtMS44NDA1NSwxLjEzNjgxIC0xLjg0 +MDU1LDMuNDEwNDQgMCwxLjczMjI4IDEuMzI2MjgsMi43MzM3NiAxLjMyNjI4LDAuOTc0NDEgNS4z +MzIxOSwxLjg2NzYyIGwgMS43MDUyMiwwLjM3ODkzIHEgNS4zMDUxMiwxLjEzNjgyIDcuNTI0NjEs +My4yMjA5NyAyLjI0NjU1LDIuMDU3MDkgMi4yNDY1NSw1Ljc2NTI2IDAsNC4yMjI0NCAtMy4zNTYz +LDYuNjg1NTQgLTMuMzI5MjMsMi40NjMwOSAtOS4xNzU2OSwyLjQ2MzA5IC0yLjQzNjAzLDAgLTUu +MDg4NTksLTAuNDg3MjEgLTIuNjI1NDksLTAuNDYwMTQgLTUuNTQ4NzIsLTEuNDA3NDggdiAtNS4x +NDI3MiBxIDIuNzYwODMsMS40MzQ1NSA1LjQ0MDQ2LDIuMTY1MzYgMi42Nzk2MiwwLjcwMzc0IDUu +MzA1MTIsMC43MDM3NCAzLjUxODcsMCA1LjQxMzM5LC0xLjE5MDk1IDEuODk0NjgsLTEuMjE4MDEg +MS44OTQ2OCwtMy40MTA0MyAwLC0yLjAzMDAyIC0xLjM4MDQxLC0zLjExMjcgLTEuMzUzMzUsLTEu +MDgyNjggLTUuOTgxOCwtMi4wODQxNiBsIC0xLjczMjI4LC0wLjQwNiBxIC00LjYyODQ1LC0wLjk3 +NDQxIC02LjY4NTU0LC0yLjk3NzM2IC0yLjA1NzA4LC0yLjAzMDAyIC0yLjA1NzA4LC01LjU0ODcz +IDAsLTQuMjc2NTcgMy4wMzE0OSwtNi42MDQzMyAzLjAzMTUsLTIuMzI3NzYgOC42MDcyOSwtMi4z +Mjc3NiAyLjc2MDgzLDAgNS4xOTY4NSwwLjQwNjAxIDIuNDM2MDMsMC40MDYgNC40OTMxMiwxLjIx +ODAxIHoiIC8+CiAgICA8L2c+CiAgICA8ZwogICAgICAgaW5rc2NhcGU6bGFiZWw9IiN0ZXh0Mzcy +NyIKICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4O2xpbmUtaGVpZ2h0OjEuMjU7Zm9u +dC1mYW1pbHk6c2Fucy1zZXJpZjtmaWxsOiMwMDAwMDA7c3Ryb2tlOm5vbmUiCiAgICAgICBpZD0i +dDIiCiAgICAgICBhcmlhLWxhYmVsPSJVUFBFUiI+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJw +YXRoMTA4IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgZD0i +bSAyMDEuMjc0NzQsODkuMzA3OTE4IGggMS40NTM3OCB2IDYuNDk1NDU4IHEgMCwxLjcxODc1NCAw +LjYyMzA1LDIuNDc3ODcgMC42MjMwNSwwLjc1MTk1NSAyLjAxOTU0LDAuNzUxOTU1IDEuMzg5MzIs +MCAyLjAxMjM3LC0wLjc1MTk1NSAwLjYyMzA1LC0wLjc1OTExNiAwLjYyMzA1LC0yLjQ3Nzg3IHYg +LTYuNDk1NDU4IGggMS40NTM3OCB2IDYuNjc0NDk1IHEgMCwyLjA5MTE1IC0xLjAzODQyLDMuMTU4 +MjEgLTEuMDMxMjUsMS4wNjcwNTcgLTMuMDUwNzgsMS4wNjcwNTcgLTIuMDI2NywwIC0zLjA2NTEy +LC0xLjA2NzA1NyAtMS4wMzEyNSwtMS4wNjcwNiAtMS4wMzEyNSwtMy4xNTgyMSB6IiAvPgogICAg +ICA8cGF0aAogICAgICAgICBpZD0icGF0aDExMCIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZTox +NC42NjY3cHgiCiAgICAgICAgIGQ9Im0gMjEzLjYyODI5LDkwLjQ5NjcyMyB2IDQuMDE3NTg3IGgg +MS44MTkwMSBxIDEuMDA5NzcsMCAxLjU2MTIsLTAuNTIyNzg3IDAuNTUxNDQsLTAuNTIyNzg4IDAu +NTUxNDQsLTEuNDg5NTg3IDAsLTAuOTU5NjM4IC0wLjU1MTQ0LC0xLjQ4MjQyNSAtMC41NTE0Mywt +MC41MjI3ODggLTEuNTYxMiwtMC41MjI3ODggeiBtIC0xLjQ0NjYyLC0xLjE4ODgwNSBoIDMuMjY1 +NjMgcSAxLjc5NzUzLDAgMi43MTQyLDAuODE2NDA4IDAuOTIzODMsMC44MDkyNDcgMC45MjM4Mywy +LjM3NzYxIDAsMS41ODI2ODYgLTAuOTIzODMsMi4zOTE5MzIgLTAuOTE2NjcsMC44MDkyNDcgLTIu +NzE0MiwwLjgwOTI0NyBoIC0xLjgxOTAxIFYgMTAwIGggLTEuNDQ2NjIgeiIgLz4KICAgICAgPHBh +dGgKICAgICAgICAgaWQ9InBhdGgxMTIiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2 +N3B4IgogICAgICAgICBkPSJtIDIyMi40Nzk4Nyw5MC40OTY3MjMgdiA0LjAxNzU4NyBoIDEuODE5 +MDEgcSAxLjAwOTc3LDAgMS41NjEyMSwtMC41MjI3ODcgMC41NTE0MywtMC41MjI3ODggMC41NTE0 +MywtMS40ODk1ODcgMCwtMC45NTk2MzggLTAuNTUxNDMsLTEuNDgyNDI1IC0wLjU1MTQ0LC0wLjUy +Mjc4OCAtMS41NjEyMSwtMC41MjI3ODggeiBtIC0xLjQ0NjYyLC0xLjE4ODgwNSBoIDMuMjY1NjMg +cSAxLjc5NzUzLDAgMi43MTQyLDAuODE2NDA4IDAuOTIzODMsMC44MDkyNDcgMC45MjM4MywyLjM3 +NzYxIDAsMS41ODI2ODYgLTAuOTIzODMsMi4zOTE5MzIgLTAuOTE2NjcsMC44MDkyNDcgLTIuNzE0 +MiwwLjgwOTI0NyBoIC0xLjgxOTAxIFYgMTAwIGggLTEuNDQ2NjIgeiIgLz4KICAgICAgPHBhdGgK +ICAgICAgICAgaWQ9InBhdGgxMTQiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4 +IgogICAgICAgICBkPSJtIDIyOS44ODQ4Myw4OS4zMDc5MTggaCA2Ljc2MDQ0IHYgMS4yMTc0NTEg +aCAtNS4zMTM4MiB2IDMuMTY1MzcyIGggNS4wOTE4MSB2IDEuMjE3NDUgaCAtNS4wOTE4MSB2IDMu +ODc0MzU4IGggNS40NDI3MiBWIDEwMCBoIC02Ljg4OTM0IHoiIC8+CiAgICAgIDxwYXRoCiAgICAg +ICAgIGlkPSJwYXRoMTE2IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAg +ICAgICAgZD0ibSAyNDQuMjM2NDMsOTQuOTg2OTY4IHEgMC40NjU0OSwwLjE1NzU1MiAwLjkwMjM0 +LDAuNjczMTc4IDAuNDQ0MDEsMC41MTU2MjYgMC44ODgwMywxLjQxNzk3MiBMIDI0Ny40OTQ5LDEw +MCBoIC0xLjU1NDA0IGwgLTEuMzY3ODQsLTIuNzQyODQ1IHEgLTAuNTI5OTUsLTEuMDc0MjIxIC0x +LjAzMTI2LC0xLjQyNTEzMyAtMC40OTQxNCwtMC4zNTA5MTMgLTEuMzUzNTEsLTAuMzUwOTEzIGgg +LTEuNTc1NTMgViAxMDAgSCAyMzkuMTY2MSBWIDg5LjMwNzkxOCBoIDMuMjY1NjQgcSAxLjgzMzMz +LDAgMi43MzU2OCwwLjc2NjI3OCAwLjkwMjM0LDAuNzY2Mjc4IDAuOTAyMzQsMi4zMTMxNTYgMCwx +LjAwOTc2OCAtMC40NzI2NSwxLjY3NTc4NSAtMC40NjU1LDAuNjY2MDE4IC0xLjM2MDY4LDAuOTIz +ODMxIHogbSAtMy42MjM3MSwtNC40OTAyNDUgdiAzLjc5NTU4MiBoIDEuODE5MDIgcSAxLjA0NTU3 +LDAgMS41NzU1MiwtMC40Nzk4MTkgMC41MzcxMSwtMC40ODY5ODEgMC41MzcxMSwtMS40MjUxMzQg +MCwtMC45MzgxNTMgLTAuNTM3MTEsLTEuNDEwODEgLTAuNTI5OTUsLTAuNDc5ODE5IC0xLjU3NTUy +LC0wLjQ3OTgxOSB6IiAvPgogICAgPC9nPgogICAgPGcKICAgICAgIGlua3NjYXBlOmxhYmVsPSIj +dGV4dDM3MzUiCiAgICAgICBzdHlsZT0iZm9udC1zaXplOjEwLjU4MzNweDtsaW5lLWhlaWdodDox +LjI1O2ZvbnQtZmFtaWx5OnNhbnMtc2VyaWY7ZmlsbDojMDAwMDAwO3N0cm9rZTpub25lIgogICAg +ICAgaWQ9InQzIgogICAgICAgYXJpYS1sYWJlbD0iTXVsdGkgbGluZQp0ZXh0CkZPTyI+CiAgICAg +IDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTE5IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0 +LjY2NjdweCIKICAgICAgICAgZD0ibSAzMDEuNDM5NDYsODkuMzA3OTE4IGggMi4xNTU2IGwgMi43 +Mjg1Miw3LjI3NjA1OSAyLjc0Mjg1LC03LjI3NjA1OSBoIDIuMTU1NiBWIDEwMCBoIC0xLjQxMDgx +IHYgLTkuMzg4NjkzIGwgLTIuNzU3MTcsNy4zMzMzNSBoIC0xLjQ1Mzc4IGwgLTIuNzU3MTYsLTcu +MzMzMzUgViAxMDAgaCAtMS40MDM2NSB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0 +aDEyMSIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGQ9Im0g +MzEzLjkwNzU4LDk2LjgzNDYyOCB2IC00Ljg1NTQ4IGggMS4zMTc3MiB2IDQuODA1MzUgcSAwLDEu +MTM4Njc0IDAuNDQ0MDEsMS43MTE1OTIgMC40NDQwMSwwLjU2NTc1NyAxLjMzMjAzLDAuNTY1NzU3 +IDEuMDY3MDYsMCAxLjY4Mjk1LC0wLjY4MDM0IDAuNjIzMDUsLTAuNjgwMzQgMC42MjMwNSwtMS44 +NTQ4MjIgdiAtNC41NDc1MzcgaCAxLjMxNzcxIFYgMTAwIGggLTEuMzE3NzEgdiAtMS4yMzE3NzQg +cSAtMC40Nzk4MiwwLjczMDQ3MSAtMS4xMTcxOSwxLjA4ODU0NSAtMC42MzAyMSwwLjM1MDkwOSAt +MS40NjgxMSwwLjM1MDkwOSAtMS4zODIxNiwwIC0yLjA5ODMxLC0wLjg1OTM3NCAtMC43MTYxNSwt +MC44NTkzNzcgLTAuNzE2MTUsLTIuNTEzNjc4IHogbSAzLjMxNTc3LC01LjA0ODg0IHoiIC8+CiAg +ICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTIzIgogICAgICAgICBzdHlsZT0iZm9udC1zaXpl +OjE0LjY2NjdweCIKICAgICAgICAgZD0ibSAzMjMuMzUzNTcsODguODU2NzQ1IGggMS4zMTc3MSBW +IDEwMCBoIC0xLjMxNzcxIHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTI1Igog +ICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgZD0ibSAzMjguNzI0 +NjgsODkuNzAxNzk5IHYgMi4yNzczNDkgaCAyLjcxNDIgdiAxLjAyNDA5MSBoIC0yLjcxNDIgdiA0 +LjM1NDE3NyBxIDAsMC45ODExMjIgMC4yNjQ5NywxLjI2MDQxOSAwLjI3MjE0LDAuMjc5Mjk4IDEu +MDk1NzEsMC4yNzkyOTggaCAxLjM1MzUyIFYgMTAwIGggLTEuMzUzNTIgcSAtMS41MjU0LDAgLTIu +MTA1NDgsLTAuNTY1NzU3IC0wLjU4MDA4LC0wLjU3MjkxNyAtMC41ODAwOCwtMi4wNzY4MjcgdiAt +NC4zNTQxNzcgaCAtMC45NjY4IHYgLTEuMDI0MDkxIGggMC45NjY4IHYgLTIuMjc3MzQ5IHoiIC8+ +CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTI3IgogICAgICAgICBzdHlsZT0iZm9udC1z +aXplOjE0LjY2NjdweCIKICAgICAgICAgZD0ibSAzMzMuMTc5MTEsOTEuOTc5MTQ4IGggMS4zMTc3 +MSBWIDEwMCBoIC0xLjMxNzcxIHogbSAwLC0zLjEyMjQwMyBoIDEuMzE3NzEgdiAxLjY2ODYyNCBo +IC0xLjMxNzcxIHoiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTI5IgogICAgICAg +ICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgZD0ibSAzNDEuOTE2MTEsODgu +ODU2NzQ1IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcxIHoiIC8+CiAgICAgIDxwYXRoCiAgICAg +ICAgIGlkPSJwYXRoMTMxIgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAg +ICAgICAgZD0ibSAzNDUuOTgzODMsOTEuOTc5MTQ4IGggMS4zMTc3MSBWIDEwMCBoIC0xLjMxNzcx +IHogbSAwLC0zLjEyMjQwMyBoIDEuMzE3NzEgdiAxLjY2ODYyNCBoIC0xLjMxNzcxIHoiIC8+CiAg +ICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTMzIgogICAgICAgICBzdHlsZT0iZm9udC1zaXpl +OjE0LjY2NjdweCIKICAgICAgICAgZD0iTSAzNTYuNzE4ODgsOTUuMTU4ODQzIFYgMTAwIGggLTEu +MzE3NzEgdiAtNC43OTgxODggcSAwLC0xLjEzODY3NSAtMC40NDQwMSwtMS43MDQ0MzEgLTAuNDQ0 +MDEsLTAuNTY1NzU3IC0xLjMzMjA0LC0wLjU2NTc1NyAtMS4wNjcwNiwwIC0xLjY4Mjk0LDAuNjgw +MzQgLTAuNjE1ODksMC42ODAzNDEgLTAuNjE1ODksMS44NTQ4MjIgViAxMDAgaCAtMS4zMjQ4NyB2 +IC04LjAyMDg1MiBoIDEuMzI0ODcgdiAxLjI0NjA5NyBxIDAuNDcyNjYsLTAuNzIzMzA5IDEuMTEw +MDMsLTEuMDgxMzgzIDAuNjQ0NTMsLTAuMzU4MDc0IDEuNDgyNDMsLTAuMzU4MDc0IDEuMzgyMTYs +MCAyLjA5MTE1LDAuODU5Mzc3IDAuNzA4OTgsMC44NTIyMTYgMC43MDg5OCwyLjUxMzY3OCB6IiAv +PgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0aDEzNSIKICAgICAgICAgc3R5bGU9ImZvbnQt +c2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGQ9Im0gMzY2LjIyMjE2LDk1LjY2MDE0NiB2IDAuNjQ0 +NTMzIGggLTYuMDU4NjEgcSAwLjA4NTksMS4zNjA2OCAwLjgxNjQxLDIuMDc2ODI4IDAuNzM3NjMs +MC43MDg5ODYgMi4wNDgxOCwwLjcwODk4NiAwLjc1OTEyLDAgMS40NjgxLC0wLjE4NjE5OSAwLjcx +NjE1LC0wLjE4NjE5OCAxLjQxNzk4LC0wLjU1ODU5NSB2IDEuMjQ2MDk3IHEgLTAuNzA4OTksMC4z +MDA3ODIgLTEuNDUzNzgsMC40NTgzMzQgLTAuNzQ0OCwwLjE1NzU1IC0xLjUxMTA4LDAuMTU3NTUg +LTEuOTE5MjcsMCAtMy4wNDM2MiwtMS4xMTcxODcgLTEuMTE3MTksLTEuMTE3MTkgLTEuMTE3MTks +LTMuMDIyMTQzIDAsLTEuOTY5NDA1IDEuMDU5OSwtMy4xMjI0MDMgMS4wNjcwNiwtMS4xNjAxNTkg +Mi44NzE3NSwtMS4xNjAxNTkgMS42MTg0OSwwIDIuNTU2NjQsMS4wNDU1NzYgMC45NDUzMiwxLjAz +ODQxNCAwLjk0NTMyLDIuODI4NzgyIHogbSAtMS4zMTc3MSwtMC4zODY3MTkgcSAtMC4wMTQzLC0x +LjA4MTM4MyAtMC42MDg3MywtMS43MjU5MTYgLTAuNTg3MjQsLTAuNjQ0NTMzIC0xLjU2MTIsLTAu +NjQ0NTMzIC0xLjEwMjg3LDAgLTEuNzY4ODgsMC42MjMwNDkgLTAuNjU4ODYsMC42MjMwNDggLTAu +NzU5MTIsMS43NTQ1NjEgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgxMzciCiAg +ICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBkPSJtIDMwMi42ODU1 +NSwxMDguMDM1MTcgdiAyLjI3NzM1IGggMi43MTQyIHYgMS4wMjQwOSBoIC0yLjcxNDIgdiA0LjM1 +NDE4IHEgMCwwLjk4MTEyIDAuMjY0OTgsMS4yNjA0MiAwLjI3MjEzLDAuMjc5MyAxLjA5NTcsMC4y +NzkzIGggMS4zNTM1MiB2IDEuMTAyODcgaCAtMS4zNTM1MiBxIC0xLjUyNTM5LDAgLTIuMTA1NDcs +LTAuNTY1NzYgLTAuNTgwMDgsLTAuNTcyOTIgLTAuNTgwMDgsLTIuMDc2ODMgdiAtNC4zNTQxOCBo +IC0wLjk2NjggdiAtMS4wMjQwOSBoIDAuOTY2OCB2IC0yLjI3NzM1IHoiIC8+CiAgICAgIDxwYXRo +CiAgICAgICAgIGlkPSJwYXRoMTM5IgogICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2Njdw +eCIKICAgICAgICAgZD0ibSAzMTQuMDAwNjgsMTEzLjk5MzUyIHYgMC42NDQ1MyBoIC02LjA1ODYg +cSAwLjA4NTksMS4zNjA2OCAwLjgxNjQsMi4wNzY4MyAwLjczNzY0LDAuNzA4OTkgMi4wNDgxOSww +LjcwODk5IDAuNzU5MTEsMCAxLjQ2ODEsLTAuMTg2MiAwLjcxNjE1LC0wLjE4NjIgMS40MTc5Nywt +MC41NTg2IHYgMS4yNDYxIHEgLTAuNzA4OTksMC4zMDA3OCAtMS40NTM3OCwwLjQ1ODM0IC0wLjc0 +NDc5LDAuMTU3NTUgLTEuNTExMDcsMC4xNTc1NSAtMS45MTkyOCwwIC0zLjA0MzYzLC0xLjExNzE5 +IC0xLjExNzE5LC0xLjExNzE5IC0xLjExNzE5LC0zLjAyMjE0IDAsLTEuOTY5NDEgMS4wNTk5LC0z +LjEyMjQxIDEuMDY3MDYsLTEuMTYwMTYgMi44NzE3NSwtMS4xNjAxNiAxLjYxODUsMCAyLjU1NjY1 +LDEuMDQ1NTggMC45NDUzMSwxLjAzODQxIDAuOTQ1MzEsMi44Mjg3OCB6IG0gLTEuMzE3NzEsLTAu +Mzg2NzIgcSAtMC4wMTQzLC0xLjA4MTM4IC0wLjYwODcyLC0xLjcyNTkxIC0wLjU4NzI0LC0wLjY0 +NDU0IC0xLjU2MTIsLTAuNjQ0NTQgLTEuMTAyODcsMCAtMS43Njg4OSwwLjYyMzA1IC0wLjY1ODg1 +LDAuNjIzMDUgLTAuNzU5MTIsMS43NTQ1NiB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBpZD0i +cGF0aDE0MSIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGQ9 +Im0gMzIyLjU3Mjk3LDExMC4zMTI1MiAtMi45MDA0LDMuOTAzMDEgMy4wNTA3OSw0LjExNzg1IGgg +LTEuNTU0MDQgbCAtMi4zMzQ2NCwtMy4xNTEwNSAtMi4zMzQ2NCwzLjE1MTA1IEggMzE0Ljk0NiBs +IDMuMTE1MjQsLTQuMTk2NjMgLTIuODUwMjcsLTMuODI0MjMgaCAxLjU1NDA0IGwgMi4xMjY5Niwy +Ljg1NzQzIDIuMTI2OTYsLTIuODU3NDMgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBh +dGgxNDMiCiAgICAgICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBkPSJt +IDMyNS44ODg3MywxMDguMDM1MTcgdiAyLjI3NzM1IGggMi43MTQyIHYgMS4wMjQwOSBoIC0yLjcx +NDIgdiA0LjM1NDE4IHEgMCwwLjk4MTEyIDAuMjY0OTgsMS4yNjA0MiAwLjI3MjEzLDAuMjc5MyAx +LjA5NTcsMC4yNzkzIGggMS4zNTM1MiB2IDEuMTAyODcgaCAtMS4zNTM1MiBxIC0xLjUyNTM5LDAg +LTIuMTA1NDcsLTAuNTY1NzYgLTAuNTgwMDgsLTAuNTcyOTIgLTAuNTgwMDgsLTIuMDc2ODMgdiAt +NC4zNTQxOCBoIC0wLjk2NjggdiAtMS4wMjQwOSBoIDAuOTY2OCB2IC0yLjI3NzM1IHoiIC8+CiAg +ICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQ1IgogICAgICAgICBzdHlsZT0iZm9udC1zaXpl +OjE0LjY2NjdweCIKICAgICAgICAgZD0ibSAzMDEuNDM5NDYsMTI1Ljk3NDY3IGggNi4xNDQ1NCB2 +IDEuMjE3NDUgaCAtNC42OTc5MyB2IDMuMTUxMDUgaCA0LjIzOTYgdiAxLjIxNzQ1IGggLTQuMjM5 +NiB2IDUuMTA2MTMgaCAtMS40NDY2MSB6IiAvPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0 +aDE0NyIKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgIGQ9Im0g +MzE0LjIyOTg1LDEyNi45NTU3OSBxIC0xLjU3NTUyLDAgLTIuNTA2NTIsMS4xNzQ0OCAtMC45MjM4 +MywxLjE3NDQ4IC0wLjkyMzgzLDMuMjAxMTggMCwyLjAxOTU0IDAuOTIzODMsMy4xOTQwMiAwLjkz +MSwxLjE3NDQ4IDIuNTA2NTIsMS4xNzQ0OCAxLjU3NTUzLDAgMi40OTIxOSwtMS4xNzQ0OCAwLjky +MzgzLC0xLjE3NDQ4IDAuOTIzODMsLTMuMTk0MDIgMCwtMi4wMjY3IC0wLjkyMzgzLC0zLjIwMTE4 +IC0wLjkxNjY2LC0xLjE3NDQ4IC0yLjQ5MjE5LC0xLjE3NDQ4IHogbSAwLC0xLjE3NDQ4IHEgMi4y +NDg3LDAgMy41OTUwNiwxLjUxMTA3IDEuMzQ2MzYsMS41MDM5MSAxLjM0NjM2LDQuMDM5MDcgMCwy +LjUyOCAtMS4zNDYzNiw0LjAzOTA3IC0xLjM0NjM2LDEuNTAzOTEgLTMuNTk1MDYsMS41MDM5MSAt +Mi4yNTU4NiwwIC0zLjYwOTM4LC0xLjUwMzkxIC0xLjM0NjM2LC0xLjUwMzkxIC0xLjM0NjM2LC00 +LjAzOTA3IDAsLTIuNTM1MTYgMS4zNDYzNiwtNC4wMzkwNyAxLjM1MzUyLC0xLjUxMTA3IDMuNjA5 +MzgsLTEuNTExMDcgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgxNDkiCiAgICAg +ICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICBkPSJtIDMyNS43NzQxNSwx +MjYuOTU1NzkgcSAtMS41NzU1MywwIC0yLjUwNjUyLDEuMTc0NDggLTAuOTIzODMsMS4xNzQ0OCAt +MC45MjM4MywzLjIwMTE4IDAsMi4wMTk1NCAwLjkyMzgzLDMuMTk0MDIgMC45MzA5OSwxLjE3NDQ4 +IDIuNTA2NTIsMS4xNzQ0OCAxLjU3NTUyLDAgMi40OTIxOSwtMS4xNzQ0OCAwLjkyMzgzLC0xLjE3 +NDQ4IDAuOTIzODMsLTMuMTk0MDIgMCwtMi4wMjY3IC0wLjkyMzgzLC0zLjIwMTE4IC0wLjkxNjY3 +LC0xLjE3NDQ4IC0yLjQ5MjE5LC0xLjE3NDQ4IHogbSAwLC0xLjE3NDQ4IHEgMi4yNDg3LDAgMy41 +OTUwNiwxLjUxMTA3IDEuMzQ2MzYsMS41MDM5MSAxLjM0NjM2LDQuMDM5MDcgMCwyLjUyOCAtMS4z +NDYzNiw0LjAzOTA3IC0xLjM0NjM2LDEuNTAzOTEgLTMuNTk1MDYsMS41MDM5MSAtMi4yNTU4Nyww +IC0zLjYwOTM4LC0xLjUwMzkxIC0xLjM0NjM2LC0xLjUwMzkxIC0xLjM0NjM2LC00LjAzOTA3IDAs +LTIuNTM1MTYgMS4zNDYzNiwtNC4wMzkwNyAxLjM1MzUxLC0xLjUxMTA3IDMuNjA5MzgsLTEuNTEx +MDcgeiIgLz4KICAgIDwvZz4KICAgIDxnCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI2czNzcyIgog +ICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDQ1LjcxMDM4LC0xMjkuNjQ4MDcpIgogICAgICAg +aWQ9InQ1Ij4KICAgICAgPGcKICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxMC41ODMzcHg7bGlu +ZS1oZWlnaHQ6MS4yNTtmb250LWZhbWlseTpzYW5zLXNlcmlmO2ZpbGw6IzAwMDAwMDtzdHJva2U6 +bm9uZSIKICAgICAgICAgaWQ9InRleHQzNzYyIgogICAgICAgICBhcmlhLWxhYmVsPSJHcm91cGVk +Ij4KICAgICAgICA8cGF0aAogICAgICAgICAgIGlkPSJwYXRoMTUyIgogICAgICAgICAgIHN0eWxl +PSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICAgIGQ9Im0gNjMuMDE5NDUzLDIyOC4xMjI2 +OCB2IC0yLjg3MTc1IGggLTIuMzYzMjg2IHYgLTEuMTg4ODEgaCAzLjc5NTU4MSB2IDQuNTkwNTEg +cSAtMC44Mzc4OTIsMC41OTQ0IC0xLjg0NzY2LDAuOTAyMzQgLTEuMDA5NzY4LDAuMzAwNzggLTIu +MTU1NjA0LDAuMzAwNzggLTIuNTA2NTE2LDAgLTMuOTI0NDg4LC0xLjQ2MDk0IC0xLjQxMDgxMSwt +MS40NjgxIC0xLjQxMDgxMSwtNC4wODIwNCAwLC0yLjYyMTEgMS40MTA4MTEsLTQuMDgyMDQgMS40 +MTc5NzIsLTEuNDY4MSAzLjkyNDQ4OCwtMS40NjgxIDEuMDQ1NTc1LDAgMS45ODM3MjgsMC4yNTc4 +MSAwLjk0NTMxNSwwLjI1NzgyIDEuNzQwMjM5LDAuNzU5MTIgdiAxLjUzOTcyIHEgLTAuODAyMDg1 +LC0wLjY4MDM0IC0xLjcwNDQzMSwtMS4wMjQwOSAtMC45MDIzNDYsLTAuMzQzNzYgLTEuODk3Nzkx +LC0wLjM0Mzc2IC0xLjk2MjI0NCwwIC0yLjk1MDUyOCwxLjA5NTcxIC0wLjk4MTEyMiwxLjA5NTcx +IC0wLjk4MTEyMiwzLjI2NTYzIDAsMi4xNjI3NyAwLjk4MTEyMiwzLjI1ODQ3IDAuOTg4Mjg0LDEu +MDk1NzEgMi45NTA1MjgsMS4wOTU3MSAwLjc2NjI3OCwwIDEuMzY3ODQyLC0wLjEyODkxIDAuNjAx +NTY0LC0wLjEzNjA3IDEuMDgxMzgyLC0wLjQxNTM2IHoiIC8+CiAgICAgICAgPHBhdGgKICAgICAg +ICAgICBpZD0icGF0aDE1NCIKICAgICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIK +ICAgICAgICAgICBkPSJtIDcxLjY5MiwyMjIuODU4OTkgcSAtMC4yMjIwMDYsLTAuMTI4OSAtMC40 +ODY5ODEsLTAuMTg2MiAtMC4yNTc4MTMsLTAuMDY0NCAtMC41NzI5MTgsLTAuMDY0NCAtMS4xMTcx +OSwwIC0xLjcxODc1NCwwLjczMDQ3IC0wLjU5NDQwMiwwLjcyMzMxIC0wLjU5NDQwMiwyLjA4Mzk5 +IHYgNC4yMjUyNyBoIC0xLjMyNDg3MyB2IC04LjAyMDg1IGggMS4zMjQ4NzMgdiAxLjI0NjEgcSAw +LjQxNTM2NiwtMC43MzA0NyAxLjA4MTM4MywtMS4wODEzOSAwLjY2NjAxNywtMC4zNTgwNyAxLjYx +ODQ5MywtMC4zNTgwNyAwLjEzNjA2OCwwIDAuMzAwNzgyLDAuMDIxNSAwLjE2NDcxNCwwLjAxNDMg +MC4zNjUyMzUsMC4wNTAxIHoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBpZD0icGF0aDE1 +NiIKICAgICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgICBkPSJt +IDc1Ljg4MTQ2MywyMjIuNTUxMDUgcSAtMS4wNTk4OTgsMCAtMS42NzU3ODUsMC44MzA3MyAtMC42 +MTU4ODcsMC44MjM1NyAtMC42MTU4ODcsMi4yNjMwMyAwLDEuNDM5NDUgMC42MDg3MjUsMi4yNzAx +OCAwLjYxNTg4NywwLjgyMzU3IDEuNjgyOTQ3LDAuODIzNTcgMS4wNTI3MzcsMCAxLjY2ODYyNCwt +MC44MzA3MyAwLjYxNTg4NiwtMC44MzA3MyAwLjYxNTg4NiwtMi4yNjMwMiAwLC0xLjQyNTE0IC0w +LjYxNTg4NiwtMi4yNTU4NyAtMC42MTU4ODcsLTAuODM3ODkgLTEuNjY4NjI0LC0wLjgzNzg5IHog +bSAwLC0xLjExNzE5IHEgMS43MTg3NTQsMCAyLjY5OTg3NiwxLjExNzE5IDAuOTgxMTIyLDEuMTE3 +MTkgMC45ODExMjIsMy4wOTM3NiAwLDEuOTY5NCAtMC45ODExMjIsMy4wOTM3NSAtMC45ODExMjIs +MS4xMTcxOSAtMi42OTk4NzYsMS4xMTcxOSAtMS43MjU5MTYsMCAtMi43MDcwMzgsLTEuMTE3MTkg +LTAuOTczOTYsLTEuMTI0MzUgLTAuOTczOTYsLTMuMDkzNzUgMCwtMS45NzY1NyAwLjk3Mzk2LC0z +LjA5Mzc2IDAuOTgxMTIyLC0xLjExNzE5IDIuNzA3MDM4LC0xLjExNzE5IHoiIC8+CiAgICAgICAg +PHBhdGgKICAgICAgICAgICBpZD0icGF0aDE1OCIKICAgICAgICAgICBzdHlsZT0iZm9udC1zaXpl +OjE0LjY2NjdweCIKICAgICAgICAgICBkPSJtIDgxLjYwMzQ4LDIyNi40ODI3IHYgLTQuODU1NDgg +aCAxLjMxNzcxMiB2IDQuODA1MzUgcSAwLDEuMTM4NjcgMC40NDQwMTEsMS43MTE1OSAwLjQ0NDAx +MiwwLjU2NTc2IDEuMzMyMDM0LDAuNTY1NzYgMS4wNjcwNiwwIDEuNjgyOTQ3LC0wLjY4MDM0IDAu +NjIzMDQ4LC0wLjY4MDM0IDAuNjIzMDQ4LC0xLjg1NDgyIHYgLTQuNTQ3NTQgaCAxLjMxNzcxMiB2 +IDguMDIwODUgaCAtMS4zMTc3MTIgdiAtMS4yMzE3NyBxIC0wLjQ3OTgxOCwwLjczMDQ3IC0xLjEx +NzE5LDEuMDg4NTQgLTAuNjMwMjEsMC4zNTA5MSAtMS40NjgxMDIsMC4zNTA5MSAtMS4zODIxNjUs +MCAtMi4wOTgzMTIsLTAuODU5MzcgUSA4MS42MDM0OCwyMjguMTM3IDgxLjYwMzQ4LDIyNi40ODI3 +IFogbSAzLjMxNTc2MywtNS4wNDg4NCB6IiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgaWQ9 +InBhdGgxNjAiCiAgICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAg +ICAgZD0ibSA5Mi4zMjQyMDgsMjI4LjQ0NDk0IHYgNC4yNTM5MiBoIC0xLjMyNDg3MyB2IC0xMS4w +NzE2NCBoIDEuMzI0ODczIHYgMS4yMTc0NSBxIDAuNDE1MzY2LC0wLjcxNjE1IDEuMDQ1NTc2LC0x +LjA1OTkgMC42MzczNzEsLTAuMzUwOTEgMS41MTgyMzIsLTAuMzUwOTEgMS40NjA5NDEsMCAyLjM3 +MDQ0OCwxLjE2MDE2IDAuOTE2NjY5LDEuMTYwMTYgMC45MTY2NjksMy4wNTA3OSAwLDEuODkwNjMg +LTAuOTE2NjY5LDMuMDUwNzkgLTAuOTA5NTA3LDEuMTYwMTUgLTIuMzcwNDQ4LDEuMTYwMTUgLTAu +ODgwODYxLDAgLTEuNTE4MjMyLC0wLjM0Mzc1IC0wLjYzMDIxLC0wLjM1MDkxIC0xLjA0NTU3Niwt +MS4wNjcwNiB6IG0gNC40ODMwODQsLTIuODAwMTMgcSAwLC0xLjQ1Mzc4IC0wLjYwMTU2NCwtMi4y +NzczNSAtMC41OTQ0MDMsLTAuODMwNzMgLTEuNjM5OTc4LC0wLjgzMDczIC0xLjA0NTU3NSwwIC0x +LjY0NzEzOSwwLjgzMDczIC0wLjU5NDQwMywwLjgyMzU3IC0wLjU5NDQwMywyLjI3NzM1IDAsMS40 +NTM3OCAwLjU5NDQwMywyLjI4NDUxIDAuNjAxNTY0LDAuODIzNTcgMS42NDcxMzksMC44MjM1NyAx +LjA0NTU3NSwwIDEuNjM5OTc4LC0wLjgyMzU3IDAuNjAxNTY0LC0wLjgzMDczIDAuNjAxNTY0LC0y +LjI4NDUxIHoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICBpZD0icGF0aDE2MiIKICAgICAg +ICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2NjdweCIKICAgICAgICAgICBkPSJtIDEwNy4yMjAw +OCwyMjUuMzA4MjIgdiAwLjY0NDUzIGggLTYuMDU4NjEgcSAwLjA4NTksMS4zNjA2OCAwLjgxNjQx +LDIuMDc2ODMgMC43Mzc2MywwLjcwODk4IDIuMDQ4MTgsMC43MDg5OCAwLjc1OTExLDAgMS40Njgx +LC0wLjE4NjE5IDAuNzE2MTUsLTAuMTg2MiAxLjQxNzk3LC0wLjU1ODYgdiAxLjI0NjEgcSAtMC43 +MDg5OCwwLjMwMDc4IC0xLjQ1Mzc4LDAuNDU4MzMgLTAuNzQ0NzksMC4xNTc1NSAtMS41MTEwNyww +LjE1NzU1IC0xLjkxOTI3LDAgLTMuMDQzNjIsLTEuMTE3MTkgLTEuMTE3MTk1LC0xLjExNzE5IC0x +LjExNzE5NSwtMy4wMjIxNCAwLC0xLjk2OTQgMS4wNTk4OTUsLTMuMTIyNCAxLjA2NzA2LC0xLjE2 +MDE2IDIuODcxNzUsLTEuMTYwMTYgMS42MTg1LDAgMi41NTY2NSwxLjA0NTU4IDAuOTQ1MzIsMS4w +Mzg0MSAwLjk0NTMyLDIuODI4NzggeiBtIC0xLjMxNzcyLC0wLjM4NjcyIHEgLTAuMDE0MywtMS4w +ODEzOCAtMC42MDg3MiwtMS43MjU5MiAtMC41ODcyNCwtMC42NDQ1MyAtMS41NjEyLC0wLjY0NDUz +IC0xLjEwMjg3LDAgLTEuNzY4ODksMC42MjMwNSAtMC42NTg4NSwwLjYyMzA1IC0wLjc1OTExLDEu +NzU0NTYgeiIgLz4KICAgICAgICA8cGF0aAogICAgICAgICAgIGlkPSJwYXRoMTY0IgogICAgICAg +ICAgIHN0eWxlPSJmb250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICAgIGQ9Im0gMTE0LjY2MDg1 +LDIyMi44NDQ2NyB2IC00LjMzOTg1IGggMS4zMTc3MSB2IDExLjE0MzI1IGggLTEuMzE3NzEgdiAt +MS4yMDMxMyBxIC0wLjQxNTM2LDAuNzE2MTUgLTEuMDUyNzQsMS4wNjcwNiAtMC42MzAyMSwwLjM0 +Mzc1IC0xLjUxODIzLDAuMzQzNzUgLTEuNDUzNzgsMCAtMi4zNzA0NSwtMS4xNjAxNSAtMC45MDk1 +LC0xLjE2MDE2IC0wLjkwOTUsLTMuMDUwNzkgMCwtMS44OTA2MyAwLjkwOTUsLTMuMDUwNzkgMC45 +MTY2NywtMS4xNjAxNiAyLjM3MDQ1LC0xLjE2MDE2IDAuODg4MDIsMCAxLjUxODIzLDAuMzUwOTEg +MC42MzczOCwwLjM0Mzc1IDEuMDUyNzQsMS4wNTk5IHogbSAtNC40OTAyNCwyLjgwMDE0IHEgMCwx +LjQ1Mzc4IDAuNTk0NCwyLjI4NDUxIDAuNjAxNTYsMC44MjM1NyAxLjY0NzE0LDAuODIzNTcgMS4w +NDU1NywwIDEuNjQ3MTQsLTAuODIzNTcgMC42MDE1NiwtMC44MzA3MyAwLjYwMTU2LC0yLjI4NDUx +IDAsLTEuNDUzNzggLTAuNjAxNTYsLTIuMjc3MzUgLTAuNjAxNTcsLTAuODMwNzMgLTEuNjQ3MTQs +LTAuODMwNzMgLTEuMDQ1NTgsMCAtMS42NDcxNCwwLjgzMDczIC0wLjU5NDQsMC44MjM1NyAtMC41 +OTQ0LDIuMjc3MzUgeiIgLz4KICAgICAgPC9nPgogICAgICA8ZwogICAgICAgICBzdHlsZT0iZm9u +dC1zaXplOjE0LjY2NjdweDtsaW5lLWhlaWdodDoxLjI1O2ZvbnQtZmFtaWx5OnNhbnMtc2VyaWY7 +ZmlsbDojMDAwMDAwO3N0cm9rZTpub25lIgogICAgICAgICBpZD0idGV4dDM3NjYiCiAgICAgICAg +IGFyaWEtbGFiZWw9InRleHQiPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgaWQ9InBhdGgxNjci +CiAgICAgICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgICAgZD0ibSA1 +Ni45NzUxNzIsMjQ5LjM0OTg3IHYgMi4yNzczNSBoIDIuNzE0MTk5IHYgMS4wMjQwOSBoIC0yLjcx +NDE5OSB2IDQuMzU0MTggcSAwLDAuOTgxMTIgMC4yNjQ5NzUsMS4yNjA0MiAwLjI3MjEzNiwwLjI3 +OTI5IDEuMDk1NzA2LDAuMjc5MjkgaCAxLjM1MzUxOCB2IDEuMTAyODcgaCAtMS4zNTM1MTggcSAt +MS41MjUzOTQsMCAtMi4xMDU0NzQsLTAuNTY1NzYgUSA1NS42NTAzLDI1OC41MDk0IDU1LjY1MDMs +MjU3LjAwNTQ5IHYgLTQuMzU0MTggaCAtMC45NjY3OTkgdiAtMS4wMjQwOSBIIDU1LjY1MDMgdiAt +Mi4yNzczNSB6IiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICAgaWQ9InBhdGgxNjkiCiAgICAg +ICAgICAgc3R5bGU9ImZvbnQtc2l6ZToxNC42NjY3cHgiCiAgICAgICAgICAgZD0ibSA2OC4yOTAz +MDMsMjU1LjMwODIyIHYgMC42NDQ1MyBoIC02LjA1ODYwOCBxIDAuMDg1OTQsMS4zNjA2OCAwLjgx +NjQwOCwyLjA3NjgzIDAuNzM3NjMyLDAuNzA4OTggMi4wNDgxODIsMC43MDg5OCAwLjc1OTExNiww +IDEuNDY4MTAyLC0wLjE4NjE5IDAuNzE2MTQ4LC0wLjE4NjIgMS40MTc5NzIsLTAuNTU4NiB2IDEu +MjQ2MSBxIC0wLjcwODk4NiwwLjMwMDc4IC0xLjQ1Mzc3OSwwLjQ1ODMzIC0wLjc0NDc5MywwLjE1 +NzU1IC0xLjUxMTA3MSwwLjE1NzU1IC0xLjkxOTI3NSwwIC0zLjA0MzYyNywtMS4xMTcxOSAtMS4x +MTcxOSwtMS4xMTcxOSAtMS4xMTcxOSwtMy4wMjIxNCAwLC0xLjk2OTQgMS4wNTk4OTgsLTMuMTIy +NCAxLjA2NzA2LC0xLjE2MDE2IDIuODcxNzUyLC0xLjE2MDE2IDEuNjE4NDkzLDAgMi41NTY2NDYs +MS4wNDU1OCAwLjk0NTMxNSwxLjAzODQxIDAuOTQ1MzE1LDIuODI4NzggeiBtIC0xLjMxNzcxMiwt +MC4zODY3MiBxIC0wLjAxNDMyLC0xLjA4MTM4IC0wLjYwODcyNSwtMS43MjU5MiAtMC41ODcyNDEs +LTAuNjQ0NTMgLTEuNTYxMjAxLC0wLjY0NDUzIC0xLjEwMjg2OCwwIC0xLjc2ODg4NSwwLjYyMzA1 +IC0wLjY1ODg1NSwwLjYyMzA1IC0wLjc1OTExNiwxLjc1NDU2IHoiIC8+CiAgICAgICAgPHBhdGgK +ICAgICAgICAgICBpZD0icGF0aDE3MSIKICAgICAgICAgICBzdHlsZT0iZm9udC1zaXplOjE0LjY2 +NjdweCIKICAgICAgICAgICBkPSJtIDc2Ljg2MjU4OCwyNTEuNjI3MjIgLTIuOTAwMzk3LDMuOTAz +IDMuMDUwNzg4LDQuMTE3ODUgaCAtMS41NTQwNCBsIC0yLjMzNDY0MSwtMy4xNTEwNSAtMi4zMzQ2 +NDEsMy4xNTEwNSBoIC0xLjU1NDA0IGwgMy4xMTUyNDIsLTQuMTk2NjIgLTIuODUwMjY3LC0zLjgy +NDIzIGggMS41NTQwNCBsIDIuMTI2OTU4LDIuODU3NDMgMi4xMjY5NTgsLTIuODU3NDMgeiIgLz4K +ICAgICAgICA8cGF0aAogICAgICAgICAgIGlkPSJwYXRoMTczIgogICAgICAgICAgIHN0eWxlPSJm +b250LXNpemU6MTQuNjY2N3B4IgogICAgICAgICAgIGQ9Im0gODAuMTc4MzUxLDI0OS4zNDk4NyB2 +IDIuMjc3MzUgaCAyLjcxNDE5OSB2IDEuMDI0MDkgaCAtMi43MTQxOTkgdiA0LjM1NDE4IHEgMCww +Ljk4MTEyIDAuMjY0OTc0LDEuMjYwNDIgMC4yNzIxMzcsMC4yNzkyOSAxLjA5NTcwNiwwLjI3OTI5 +IGggMS4zNTM1MTkgdiAxLjEwMjg3IGggLTEuMzUzNTE5IHEgLTEuNTI1Mzk0LDAgLTIuMTA1NDcz +LC0wLjU2NTc2IC0wLjU4MDA4LC0wLjU3MjkxIC0wLjU4MDA4LC0yLjA3NjgyIHYgLTQuMzU0MTgg +aCAtMC45NjY3OTkgdiAtMS4wMjQwOSBoIDAuOTY2Nzk5IHYgLTIuMjc3MzUgeiIgLz4KICAgICAg +PC9nPgogICAgPC9nPgogICAgPHBhdGgKICAgICAgIGQ9Ik0gMTAwLDIwMCBIIDIwMCBWIDMwMCBI +IDEwMCBaIgogICAgICAgaW5rc2NhcGU6bGFiZWw9IiNyZWN0MzczMiIKICAgICAgIHN0eWxlPSJm +aWxsOiMwMDAwODA7c3Ryb2tlOm5vbmUiCiAgICAgICBpZD0icjEiIC8+CiAgICA8cGF0aAogICAg +ICAgZD0iTSAzMDAsMjAwIEggNTAwIFYgMzAwIEggMzAwIFoiCiAgICAgICBpbmtzY2FwZTpsYWJl +bD0iI3JlY3QzNzM0IgogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I2ZmMDAwMDtzdHJv +a2Utd2lkdGg6MTYiCiAgICAgICBpZD0icjIiIC8+CiAgICA8cGF0aAogICAgICAgZD0iTSA2NDQu +OTQzMjMsMjAwIEggNzU1LjA1Njc3IEMgNzc5Ljk1NTMyLDIwMCA4MDAsMjE3LjM3MjA2IDgwMCwy +MzguOTUwOCB2IDIyLjA5ODQgQyA4MDAsMjgyLjYyNzk0IDc3OS45NTUzMiwzMDAgNzU1LjA1Njc3 +LDMwMCBIIDY0NC45NDMyMyBDIDYyMC4wNDQ2OCwzMDAgNjAwLDI4Mi42Mjc5NCA2MDAsMjYxLjA0 +OTIgViAyMzguOTUwOCBDIDYwMCwyMTcuMzcyMDYgNjIwLjA0NDY4LDIwMCA2NDQuOTQzMjMsMjAw +IFoiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iI3JlY3QzNzQ0IgogICAgICAgc3R5bGU9ImZpbGw6 +I2ZmZmYwMDtzdHJva2U6IzAwODAwMDtzdHJva2Utd2lkdGg6MTYiCiAgICAgICBpZD0icjMiIC8+ +CiAgPC9nPgogIDxzY3JpcHQKICAgICBpZD0iSmVzc3lJbmsiCiAgICAgbnMxOnZlcnNpb249IjEu +NS41Ij4vLyBkdW1teQo8L3NjcmlwdD4KPC9zdmc+Cg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/bf3e6cfcbb81940d4f7d667750681b0c.msg b/share/extensions/tests/data/cmd/inkscape/bf3e6cfcbb81940d4f7d667750681b0c.msg new file mode 100644 index 0000000..051d4af --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/bf3e6cfcbb81940d4f7d667750681b0c.msg @@ -0,0 +1,1038 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area-page --export-background-opacity=0 --export-dpi=96 --export-filename=Slide2.png --export-id-only --export-id=layer2 --export-type=png Slide2.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="Slide2.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: Slide2.png + +iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoCAYAAABNo9TkAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAIABJREFUeJzs3XmcXHWd7//3qapT +W1fva9LZl04I4ELYVJZA2EFRwIwSCDLMyHDvXB86bvf+7syI+vCOjqPjZeYh8nP4RUkaMAiMssoW +VpVVEUP2vTvpfanuqurazvn90WFUZElyTvU51fV6Ph4+QmLqc95d1UnqXeec71cCAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlz/A6AAAAAOC2 +tVKbKX1T0lmS5nidp4JZkrbb0n1p6SvXS2mvAwF+RkEHUDbWSlFTusKQ2r3OUslsqXtIuuszUtbr +LJh0oxRYJH3Olm4wpIVe56lktrRT0vd3St+7cbKYwAN3SLML0suG1Ox1FvyJ18LSKaukjNdBAL8K +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 +8IEN8FA56xEREZHaoYAuIiIyySgcBDLAB3phS7nrEREREREREalZD8Gby12DiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI +iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiMhcMcpd +gFS+R2BxDlYasNKG1TZcYkALEJz40QjU25AzIAaMAlHy/z8A7DVgnwF73bD37vxjIiIiIiIiMokC +upzlPjCXw5UG3G7DHQbcDNQ7fJs+4AkbHrNg2z2wz+HxRURERERmzQZjMyw2YJUBK4E1wDKgidcm +qc78P+QnpkYm/hsDRgw4YMMeG/bZsHcjHDPALv2vRqqJArrwefC1wFtteD9wB9A8+Xm334W33oOv +3o2v3oOvwYPbZ2K6TQy3gctjYnpMsG1yWRsrbZHLWlhZm2wiRzqaIRXNkB7LkopmyGWsc0s4bsP/ +AFsOwJP3wXkXiIiIiIjMlfvBUw/XWfn3wrcD1wIBh28TA56zYZsBj8XguXsh4/A9pMopoNewh+Bq +GzbZ8H4D2s487qlzUdfqI9RRR6jTjzfgdvS+6fEs8cEUscEk46cSZOK5yU+fAL5mw5c2wnZHbywi +IiIiMuEBaHHB+4C3Azfx2mx4qcSAp4BveuErd8Nwie8vFUgBvcZsBVcG3mfD7wOXnnnc3+SlqTtI +w6IAnuDZgdxwGUm33zXoqXMNuoPuIV+9Z8gbco95vGba8JgZT50r6fK70li2kUtZ3kwi58+lc95c +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 +XBl3DsXqa4NwRdwhJEmSksYp7pLaKoDPxJ1BsQpD+GjcISRJkpLIgi6prQbh+zitbdmK4KZr4eG4 +c0jSPw43AAADDUlEQVSSJCWRBV1S29XgIxGU4s6htium4bfjDiFJkpRUFnRJbXcdbAvg43HnUNv9 +9tXwSNwhJEmSksqCLikWOfhfwBfjzqG2+ZtB+HTcISRJkpLMgi4pFhuhloNfAr4XdxadWhHcNnc/ +YkmSJB2DBV1SbDZCrQJvD+D6uLPo1Ajg72fgrRuhHHcWSZKkpPM+6JISYTP8WgSfCqAj7ixaEEXg +E0/CH38cwrjDSJIkLQYWdEmJcT28OIDPBPCGuLPopHw9A791JWyPO4gkSdJiYkGXlDhb4GURfBT4 +t0B33Hl0QiaC+v3tv3gN3B53GEmSpMXIgi4psbZCVwkuD+BNEVwSwHlAFlgTd7blLIKDwF5gbwqe +iODuEnzrFyEfdzZJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJknTq/X/JJrjxXJwO +bQAAAABJRU5ErkJggg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/c1bf37c2aa47000fc9941d96b415218c.msg b/share/extensions/tests/data/cmd/inkscape/c1bf37c2aa47000fc9941d96b415218c.msg new file mode 100644 index 0000000..f3c3e2a --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/c1bf37c2aa47000fc9941d96b415218c.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:49:1000:951 --export-filename=guides_5.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_5.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_5.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAOGCAYAAAB83MkXAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAALxJREFUeJztwQENAAAAwqD3T20P +BxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCDAZoM +AAG1xnPlAAAAAElFTkSuQmCC + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/d475a74656cd1f8ba68e095b0ec7c469.msg b/share/extensions/tests/data/cmd/inkscape/d475a74656cd1f8ba68e095b0ec7c469.msg new file mode 100644 index 0000000..2032307 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/d475a74656cd1f8ba68e095b0ec7c469.msg @@ -0,0 +1,1025 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=47:49:953:951 --export-filename=f4oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f4oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f4oo.png + +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 +EkVERPyloCgiIl6b6zrFggnvvwv+1dNqREREZNYUFEVExGtzCYoFFz6gkCgiIrIwKCiKiIin5rBF +RsGFD2yBf5mXgkRERGTWFBRFRMRT5uyCYsGAOxUSRUREFhYFRRER8dQstsiwXPjgJvi/81qQiIiI +zJqCooiIeCoARyltcVGO5ZZGEv+5EjWJiIjI7CgoioiIp+4E24BDZU6xDdiqkCgiIrJwKSiKiIjn +yjS0sQ3YvAm+UdGCREREZFYUFEVExHPG2YOi7cIWhUQREZGFT0FRREQ8d5YRRZvSdNOv+1GPiIiI +zE7Q7wJERKQmTex8ahvwkU3woG/ViIiIyKxoRFFERDznvDGiaAMf3QQP+FmPiIiIzI6CooiIeG4Q +DgAW8NHNsN3vekRERERERGQBeADe7ncNIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi +IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJSmwy/C6gX +X4flNqwzYJ0LF7pwgQGtQGLsTxOQcsE2IAMMAmlK/94D7DFgrwF7grDnztIxERERERERzykozoN7 +wFwDlxtwqwu3GXAjkPL4NqeBR1142IGdH4G9Hl9fRERERGTOXDC2wXID1huwDrgIWA0088Zgyfi/ +Q2mAZGDsnxlgwID9Lrzqwl4X9myBowa4lf/b1B8FRY98CSKt8E4XPgzcBrRMfD4YDRBOhYikgkRS +ISINIYIREzNoYgQNAiETM2SC62IXXZyCg110cIouxVGbQtoin7YoDBfJpy1sy5lawjEX/h3Yvh8e +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 +N/B+4HJgFXBusonaXh/1PS8fC+DWjXBv4CqPDbUFPhTB1RFcHMB5Sedpc89Tv2j8t5N3faU5YVGU +mtBNcEsAVyWdQ4n6Ri9cmXQISZLUmhx6KjWhAL6YdAYlKgzhU0mHkCRJrcuiKDWhXrgfh5u0rQhu +uxaeSjqHJElqXRZFqUnV4JMRlJLOoYYrpuE3kw4hSZJam0VRalLXwfYAPpN0DjXcb26EbUmHkCRJ +rc2iKDWxLPwv4KtJ51DD/E0vfCHpEJIkqfVZFKUmtgFqWfh54PtJZ9HciuDuyf3MJEmS5pxFUWpy +G6BWgfcHcGPSWTQ3Avj7CXjvBignnUWSJLUH91GUWshm+JUIPh9AZ9JZNCuKwGefhz/+DIRJh5Ek +Se3Doii1mBvhwgC+GMA7k86i0/LNDviNq2BH0kEkSVL7sShKLWoLvDGqb8r+74EFSefRSRkJ6vtj +fvUauCfpMJIkqX1ZFKUWtxW6S3BFAO+K4OIAzgMywKqks7WzCA4D+4B9KXgugodK8J2fg1zS2SRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJ +kiRJkiRJkiRJkiRJkiS1hP8P8aK48RBoJeEAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/da3b4e4db182a123e61e1317b2e4578b.msg b/share/extensions/tests/data/cmd/inkscape/da3b4e4db182a123e61e1317b2e4578b.msg new file mode 100644 index 0000000..d898d17 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/da3b4e4db182a123e61e1317b2e4578b.msg @@ -0,0 +1,25 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:951:47:1000 --export-filename=guides_6.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="guides_6.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: guides_6.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAAxCAYAAABK+/BHAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAB9JREFUaIHtwQEBAAAAgiD/r25I +QAEAAAAAAAAAABcGJC0AAXI8dYQAAAAASUVORK5CYII= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/ee1fdaa387bcb73ee6f7a2359fa9bd62.msg b/share/extensions/tests/data/cmd/inkscape/ee1fdaa387bcb73ee6f7a2359fa9bd62.msg new file mode 100644 index 0000000..af25e58 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/ee1fdaa387bcb73ee6f7a2359fa9bd62.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=953:49:1000:951 --export-filename=f5oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f5oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f5oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAOGCAYAAAB83MkXAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAALxJREFUeJztwQENAAAAwqD3T20P +BxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCDAZoM +AAG1xnPlAAAAAElFTkSuQmCC + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/inkscape/fbabf7cf387f29c12ae11a51af0a9926.msg b/share/extensions/tests/data/cmd/inkscape/fbabf7cf387f29c12ae11a51af0a9926.msg new file mode 100644 index 0000000..7b971d9 --- /dev/null +++ b/share/extensions/tests/data/cmd/inkscape/fbabf7cf387f29c12ae11a51af0a9926.msg @@ -0,0 +1,28 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: inkscape +Arguments: --export-area=0:49:47:951 --export-filename=f3oo.png compare_file.svg + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: img + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="f3oo.png" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: f3oo.png + +iVBORw0KGgoAAAANSUhEUgAAAC8AAAOGCAYAAAB83MkXAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA +GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAALxJREFUeJztwQENAAAAwqD3T20P +BxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCDAZoM +AAG1xnPlAAAAAElFTkSuQmCC + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/pdflatex/6cb19641894666183e4e3e0dbf0d0098.msg b/share/extensions/tests/data/cmd/pdflatex/6cb19641894666183e4e3e0dbf0d0098.msg new file mode 100644 index 0000000..f15ec4e --- /dev/null +++ b/share/extensions/tests/data/cmd/pdflatex/6cb19641894666183e4e3e0dbf0d0098.msg @@ -0,0 +1,1361 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: pdflatex +Arguments: -halt-on-error -output-directory=. input.tex + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KQ0KZW50ZXJpbmcgZXh0ZW5kZWQgbW9kZQ0KKEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9j +YWwvVGVtcC9pbmt0bXAzdm91YjVqdC9pbnB1dC50ZXgNCkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDENCkwzIHByb2dyYW1taW5nIGxheWVyIDwyMDIxLTA3LTEyPg0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25l +XHN0YW5kYWxvbmUuYw0KbHMNCkRvY3VtZW50IENsYXNzOiBzdGFuZGFsb25lIDIwMTgvMDMvMjYg +djEuM2EgQ2xhc3MgdG8gY29tcGlsZSBUZVggc3ViLWZpbGVzIHN0YW4NCmRhbG9uZQ0KKEM6XFVz +ZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xz +aGVsbGVzYy5zdHkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZsdWF0ZXguc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZ0ZXguc3R5KSkNCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtl +eXZhbFx4a2V5dmFsLnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxceGtleXZhbC50ZXgNCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxz +LnRleA0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9n +ZW5lcmljL3hrZXl2YWxca2V5dmFsLnRleCkpKQ0KKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYw0K +ZmcpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xh +dGV4L2tvbWEtc2NyaXB0XHNjcnJlcHJ0LmNsDQpzDQpEb2N1bWVudCBDbGFzczogc2NycmVwcnQg +MjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBkb2N1bWVudCBjbGFzcyAocmVwb3J0KQ0KDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tv +bWEtc2NyaXB0XHNjcmtiYXNlLnN0DQp5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmJhc2Uuc3R5DQoNCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1z +Y3JpcHRcc2NybGZpbGUuc3QNCnkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dy +YW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1zY3JpcHRcc2NybGZpbGUtaG8NCm9rLTMuMzQuc3R5 +DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5DQopKSkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFx0b2NiYXNpYy5zdA0K +eSkNCg0KTGFUZVggRm9udCBXYXJuaW5nOiBGb250IHNoYXBlIGBPVDEvY21yL20vbicgaW4gc2l6 +ZSA8MTU+IG5vdCBhdmFpbGFibGUNCihGb250KSAgICAgICAgICAgICAgc2l6ZSA8MTQuND4gc3Vi +c3RpdHV0ZWQgb24gaW5wdXQgbGluZSAyNDg3Lg0KDQoNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRh +XExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1zY3JpcHRcdHlwZWFyZWEuc3QN +CnkNCg0KUGFja2FnZSB0eXBlYXJlYSBXYXJuaW5nOiBESVYgZm9yIDE1LjBwdCBhbmQgdXNlZCBw +YXBlcnNpemUNCih0eXBlYXJlYSkgICAgICAgICAgICAgICAgbm90IGRlZmluZWQhDQoodHlwZWFy +ZWEpICAgICAgICAgICAgICAgIFVzaW5nIERJVj1jYWxjLg0KDQpESVYgY2FsY3VsYXRpb24gZm9y +IHR5cGVhcmVhIHdpdGggZ29vZCBsaW5ld2lkdGguDQopKSAoQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L3ByZXZpZXdccHJldmlldy5zdHkNCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbHVh +dGV4ODVcbHVhdGV4ODUuc3R5KQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3Jh +bXNcTWlLVGVYXHRleC9sYXRleC9wcmV2aWV3XHBydGlnaHRwYWdlLmRlZg0KKSkpIChDOlxVc2Vy +c1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxh +bXNtYXRoLnN0eQ0KRm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gYW1zbWF0aCwgdXNlIHRo +ZSBgPycgb3B0aW9uLg0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc3RleHQuc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zZ2VuLnN0eSkpDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ft +c21hdGhcYW1zYnN5LnN0eSkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1z +XE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNvcG4uc3R5KSkNCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zZm9udHNcYW1zc3ltYi5z +dHkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0 +ZXgvYW1zZm9udHNcYW1zZm9udHMuc3R5KSkNCg0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9j +YWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9sM2JhY2tlbmRcbDNiYWNrZW5kLXBkZg0KdGV4 +LmRlZikNCk5vIGZpbGUgaW5wdXQuYXV4Lg0KUHJldmlldzogRm9udHNpemUgMTVwdA0KUHJldmll +dzogUERGb3V0cHV0IDENCg0KTGFUZVggRm9udCBXYXJuaW5nOiBGb250IHNoYXBlIGBPVDEvY21y +L20vbicgaW4gc2l6ZSA8MTAuNDk5OTU+IG5vdCBhdmFpbGFibGUNCihGb250KSAgICAgICAgICAg +ICAgc2l6ZSA8MTAuOTU+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxpbmUgNS4NCg0KDQpMYVRlWCBG +b250IFdhcm5pbmc6IEZvbnQgc2hhcGUgYE9UMS9jbXIvbS9uJyBpbiBzaXplIDw3LjU+IG5vdCBh +dmFpbGFibGUNCihGb250KSAgICAgICAgICAgICAgc2l6ZSA8Nz4gc3Vic3RpdHV0ZWQgb24gaW5w +dXQgbGluZSA1Lg0KDQoNCkxhVGVYIEZvbnQgV2FybmluZzogRm9udCBzaGFwZSBgT01ML2NtbS9t +L2l0JyBpbiBzaXplIDwxNT4gbm90IGF2YWlsYWJsZQ0KKEZvbnQpICAgICAgICAgICAgICBzaXpl +IDwxNC40PiBzdWJzdGl0dXRlZCBvbiBpbnB1dCBsaW5lIDUuDQoNCg0KTGFUZVggRm9udCBXYXJu +aW5nOiBGb250IHNoYXBlIGBPTUwvY21tL20vaXQnIGluIHNpemUgPDEwLjQ5OTk1PiBub3QgYXZh +aWxhYmxlDQooRm9udCkgICAgICAgICAgICAgIHNpemUgPDEwLjk1PiBzdWJzdGl0dXRlZCBvbiBp +bnB1dCBsaW5lIDUuDQoNCg0KTGFUZVggRm9udCBXYXJuaW5nOiBGb250IHNoYXBlIGBPTUwvY21t +L20vaXQnIGluIHNpemUgPDcuNT4gbm90IGF2YWlsYWJsZQ0KKEZvbnQpICAgICAgICAgICAgICBz +aXplIDw3PiBzdWJzdGl0dXRlZCBvbiBpbnB1dCBsaW5lIDUuDQoNCg0KTGFUZVggRm9udCBXYXJu +aW5nOiBGb250IHNoYXBlIGBPTVMvY21zeS9tL24nIGluIHNpemUgPDE1PiBub3QgYXZhaWxhYmxl +DQooRm9udCkgICAgICAgICAgICAgIHNpemUgPDE0LjQ+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxp +bmUgNS4NCg0KDQpMYVRlWCBGb250IFdhcm5pbmc6IEZvbnQgc2hhcGUgYE9NUy9jbXN5L20vbicg +aW4gc2l6ZSA8MTAuNDk5OTU+IG5vdCBhdmFpbGFibGUNCihGb250KSAgICAgICAgICAgICAgc2l6 +ZSA8MTAuOTU+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxpbmUgNS4NCg0KDQpMYVRlWCBGb250IFdh +cm5pbmc6IEZvbnQgc2hhcGUgYE9NUy9jbXN5L20vbicgaW4gc2l6ZSA8Ny41PiBub3QgYXZhaWxh +YmxlDQooRm9udCkgICAgICAgICAgICAgIHNpemUgPDc+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxp +bmUgNS4NCg0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRl +eC9sYXRleC9hbXNmb250c1x1bXNhLmZkKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxc +UHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1x1bXNiLmZkKQ0KUHJldmlldzogVGln +aHRwYWdlIDAgMCAwIDANClsxe0M6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9jYWwvTWlLVGVYL3Bk +ZnRleC9jb25maWcvcGRmdGV4Lm1hcH1dDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxU +ZW1wXGlua3RtcDN2b3ViNWp0XGlucHV0LmF1eCkNCg0KTGFUZVggRm9udCBXYXJuaW5nOiBTaXpl +IHN1YnN0aXR1dGlvbnMgd2l0aCBkaWZmZXJlbmNlcw0KKEZvbnQpICAgICAgICAgICAgICB1cCB0 +byAwLjZwdCBoYXZlIG9jY3VycmVkLg0KDQogKTxDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vDQpjbWV4MTAu +cGZiPjxDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90 +eXBlMS9wdWJsaWMvYW1zDQpmb250cy9jbS9jbW1pMTAucGZiPjxDOi9Vc2Vycy9qb25hdC9BcHBE +YXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wDQp1YmxpYy9hbXNmb250cy9j +bS9jbW1pMTIucGZiPjxDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1Rl +WC9mb250DQpzL3R5cGUxL3B1YmxpYy9hbXNmb250cy9jbS9jbXIxMC5wZmI+PEM6L1VzZXJzL2pv +bmF0L0FwcERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlLDQpUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ft +c2ZvbnRzL2NtL2NtcjEyLnBmYj48QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9nDQpy +YW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21zeTEwLnBmYj4NCk91 +dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXAz +dm91YjVqdFxpbnB1dC5wZGYgKDENCiBwYWdlLCA1NDg4OCBieXRlcykuDQpUcmFuc2NyaXB0IHdy +aXR0ZW4gb24gQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlua3RtcDN2b3ViNWp0 +XGlucHV0LmxvDQpnLg0K + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.aux" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.aux + +XHJlbGF4IApccHJvdmlkZWNvbW1hbmQqXG5ld0B0cG9AbGFiZWxbMl17fQpcZ2RlZiBcQGFic3Bh +Z2VAbGFzdHsxfQo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.pdf + +JVBERi0xLjUKJdDUxdgKMyAwIG9iago8PAovTGVuZ3RoIDI4NiAgICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjajZI7T8NAEIT7+xVLlxTe3D7uVaSJRIp0CBdIIRUREiJGSpW/ +z54dCxtcIDcn+9PMeOZ2rdvsxQMpikaG9h0IqUTgglECtGc4rl690PrUHjZ7LkAeiy9UyYyaBQKy +jwPIlXKPrbs6Am8PjWqCgSK8de548nC2LwfwGEqGW891NYBKtOMFnt2T29VcnKe51Hy52vtcBrtY +7YACWpyCWWl4vV03IcfV5aMbQgtNQ5uiHZqMJaaB/7pjMsUiBs0WpyceaElJCJMVwgm1/JLS3ka1 +Yk2yfy/QaN9Wj70syXnMZMGEf7jPpdYjepYx2XYcZlYVE8baekYaS6G/0xSjAv9nG8Gk82nmV+au +NN1mMXrClJMNSbWZ2YX5Bi0Hi/AKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9Q +YWdlCi9Db250ZW50cyAzIDAgUgovUmVzb3VyY2VzIDEgMCBSCi9NZWRpYUJveCBbMCAwIDEwNi41 +ODcgNDQuNjUxXQovUGFyZW50IDEwIDAgUgo+PgplbmRvYmoKMSAwIG9iago8PAovRm9udCA8PCAv +RjMwIDQgMCBSIC9GMjkgNSAwIFIgL0YyOCA2IDAgUiAvRjMxIDcgMCBSIC9GMzMgOCAwIFIgL0Yz +NCA5IDAgUiA+PgovUHJvY1NldCBbIC9QREYgL1RleHQgXQo+PgplbmRvYmoKMTEgMCBvYmoKWzE0 +NDQuNF0KZW5kb2JqCjEyIDAgb2JqClsxMDAwIDUwMCA1MDAgMTAwMCAxMDAwIDEwMDAgNzc3Ljgg +MTAwMCAxMDAwIDYxMS4xIDYxMS4xIDEwMDAgMTAwMCAxMDAwIDc3Ny44IDI3NSAxMDAwXQplbmRv +YmoKMTMgMCBvYmoKWzUyMC42IDI5OC40IDg3OCA2MDAuMl0KZW5kb2JqCjE0IDAgb2JqCls0ODku +NiA0ODkuNiA0ODkuNiA0ODkuNiA0ODkuNiA0ODkuNiA0ODkuNiA0ODkuNiA0ODkuNiAyNzIgMjcy +IDI3MiA3NjEuNiA0NjIuNCA0NjIuNCA3NjEuNiA3MzQgNjkzLjQgNzA3LjIgNzQ3LjggNjY2LjIg +NjM5IDc2OC4zIDczNCAzNTMuMiA1MDMgNzYxLjIgNjExLjggODk3LjIgNzM0IDc2MS42IDY2Ni4y +IDc2MS42IDcyMC42IDU0NCA3MDcuMiA3MzQgNzM0IDEwMDYgNzM0IDczNCA1OTguNCAyNzIgNDg5 +LjYgMjcyIDQ4OS42IDI3MiAyNzIgNDg5LjYgNTQ0IDQzNS4yIDU0NCA0MzUuMiAyOTkuMiA0ODku +NiA1NDQgMjcyIDI5OS4yIDUxNi44IDI3MiA4MTZdCmVuZG9iagoxNSAwIG9iagpbNTAwIDUwMCA1 +MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgMjc3LjggMjc3LjggMjc3LjggNzc3LjhdCmVuZG9i +agoxNiAwIG9iagpbNTU1LjQgNTA1IDU1Ni41IDQyNS4yIDUyNy44IDU3OS41IDYxMy40IDYzNi42 +IDYwOS43IDQ1OC4yIDU3Ny4xIDgwOC45IDUwNSAzNTQuMiA2NDEuNCA5NzkuMiA5NzkuMiA5Nzku +MiA5NzkuMiAyNzIgMjcyIDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42 +IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42IDI3MiAyNzIgNzYxLjYgNDg5LjYgNzYxLjYg +NDg5LjYgNTE2LjkgNzM0IDc0My45IDcwMC41IDgxMyA3MjQuOCA2MzMuOCA3NzIuNCA4MTEuMyA0 +MzEuOSA1NDEuMiA4MzMgNjY2LjIgOTQ3LjMgNzg0LjEgNzQ4LjMgNjMxLjEgNzc1LjUgNzQ1LjMg +NjAyLjIgNTczLjkgNjY1IDU3MC44IDkyNC40IDgxMi42IDU2OC4xIDY3MC4yIDM4MC44IDM4MC44 +IDM4MC44IDk3OS4yIDk3OS4yIDQxMC45IDUxNCA0MTYuMyA0MjEuNCA1MDguOCA0NTMuOCA0ODIu +NiA0NjguOSA1NjMuNyAzMzQgNDA1LjEgNTA5LjNdCmVuZG9iagoxNyAwIG9iago8PAovTGVuZ3Ro +MSAxMzg3Ci9MZW5ndGgyIDU5NzUKL0xlbmd0aDMgMAovTGVuZ3RoIDY5MjkgICAgICAKL0ZpbHRl +ciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjajXQFVJTd2jZdAtKhxAAiDTN0d0p3K8PMAEPMwDDk +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 +i12SRdDABy/y9HYP0Fp7jhJGZ3l+gsJ5nalczu1EVdFJF6OasjOv9vD3xc9lfWhVLb4rg1kMsZmi +ZYGPERzd1xw8253N/MBRWvNSFxkLChSOm4Fb3hOjpZ2lWdbKVcktwfjABIzMmeqe5K2h7IlyeY6E +lN2W1eVBhQy55Ugm0xBI3oihytqC1VLNqZbhq4Phh8EWBOVtCtQ4br6Ko4mKVUMMCHEFBq6gCpfz +kJPFTPGvJkT3FOrGse9ImW23zpVQeWvBj2rzyqfaVlxqKD5VBfeb9YRei4eJ12CGuGTPL/sbcYrq +pBge3NWbILM0P/KMGwKdpTiS4nBAfeZ0TJ58yL2cK1E/Lzh9cWOLDqgnyZLK0YwlPLrB/QIpXcfY +irC1p7Mbw0p/z5ny6ojlmyj9NBpH3Bkgd8tlJeHbzUxSeUKJ1wy3wvEWGd/JMwZjjXFL1ZeQbrMQ +eHSi3aTo+HQrxJ06/PV6P/gpmtFnK5b2vt505HbC577znslSv9G1/pAZS+qu6FOSAvHB/K/iwulC +duVP4X15E7rqD5QH5vBri7Amzf7ake+x8fbXM2e6YvRo5LkMOPZ7N5oCb0PKEbb+THXdCdl2wMIH +eDoGUS6EaHKRMdQKzYsQ//hSSXLuVk2FRQWWWZdOyPHBa64Ahn5sBZswrmDUzRoX4AzR/wADPVyf +CmVuZHN0cmVhbQplbmRvYmoKMTggMCBvYmoKPDwKL1R5cGUgL0ZvbnREZXNjcmlwdG9yCi9Gb250 +TmFtZSAvWVFKU0RKK0NNRVgxMAovRmxhZ3MgNAovRm9udEJCb3ggWy0yNCAtMjk2MCAxNDU0IDc3 +Ml0KL0FzY2VudCA0MAovQ2FwSGVpZ2h0IDAKL0Rlc2NlbnQgLTYwMAovSXRhbGljQW5nbGUgMAov +U3RlbVYgNDcKL1hIZWlnaHQgNDMxCi9DaGFyU2V0ICgvc3VtbWF0aW9uZGlzcGxheSkKL0ZvbnRG +aWxlIDE3IDAgUgo+PgplbmRvYmoKMTkgMCBvYmoKPDwKL0xlbmd0aDEgMTQwOQovTGVuZ3RoMiA2 +MzI5Ci9MZW5ndGgzIDAKL0xlbmd0aCA3MjkyICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+ +CnN0cmVhbQp42o13B1ST29I20qQqICJICwpIEZLQe+9VIIBIDSRAKElIQglNkN6U3ptSFaR3EVCq +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 +Rm9udE5hbWUgL0lRSktJTitDTU1JMTAKL0ZsYWdzIDQKL0ZvbnRCQm94IFstMzIgLTI1MCAxMDQ4 +IDc1MF0KL0FzY2VudCA2OTQKL0NhcEhlaWdodCA2ODMKL0Rlc2NlbnQgLTE5NAovSXRhbGljQW5n +bGUgLTE0Ci9TdGVtViA3MgovWEhlaWdodCA0MzEKL0NoYXJTZXQgKC9rL24pCi9Gb250RmlsZSAx +OSAwIFIKPj4KZW5kb2JqCjIxIDAgb2JqCjw8Ci9MZW5ndGgxIDE0MDkKL0xlbmd0aDIgNjI3Mgov +TGVuZ3RoMyAwCi9MZW5ndGggNzIzMyAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJl +YW0KeNqNdQdUk2vTLShd6SodQlM6Cb1JL9K79BJCgCAkkIQO0pEiIL33KkWacABpghRRkCJIB+m9 +I1KEP5bznf98965178payTsze+aZeWbvN+zMOvq8crYIG6gyAo7mBfEBJQAKmpqqIAEAECjIBwQK +ELGzG8DQTtC//UTsj6FIFAwBl/hfCAUkFIzG+BTBaAxQEwEHqLk5AUCCAJCIBEhUAggECACB4n8D +EUgJgCLYHWYL0OQDqCHgUBQRuwLCxQsJs3dAY875+xHAAeEEgMTFRXl+pQPknKFIGAQMB2iC0Q5Q +Z8yJELATQB8BgUHRXv8qwSHlgEa7SPDze3h48IGdUXwIpL00Jw/AA4Z2AOhBUVCkO9QW8HNkgBbY +GfpnND4idoCBAwz1O6CPsEN7gJFQAMbhBINA4ShMihvcFooEYE4H6KtqALRdoPDfYI3fAB7An8sB +gPhA/yn3J/tnIRj8VzIYAkE4u4DhXjC4PcAO5gQFaCtr8KE90TwAMNz2JxDshEJg8sHuYJgT2AYD ++NU6GKAspwsAYyb8Mx8KgoS5oFF8KJjTzxn5f5bBXLMS3FYB4ewMhaNRRD/7U4QhoRDMvXvx/1nu +EzjCA+7zt2UHg9va/RzD1s2F3xAOc3WDqir+wWBcRP/47KFogDBQTFRQTAQAdQVAPSEO/D8PMPBy +gf4Kgn66MTP4+bggXAB2mDGgfjA7KOaHyAcFdocC0Eg3qJ/P/w782yICgQC2MAgaYAO1h8GJ/qmO +cUPtftuY/SNhngAzIIZ+IADw5+c/TxYYhtki4E5e/8B/rZhfV1tZS8WI+8/I/wnKyyM8AT68giAA +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 +T6ZqHR7xgCK0iEPK43vt+7tl1z4T7UndEeVv4pTaUQr6j8irDC5OFMY9beVxUpnsXNLgPrI3DWKK +R8/NBn6I3aazCs6gJIrYt+BK/vatCjsxck3IeWog6odV1RLljgHpmtd0GQOayLqspDarol/747dI +Sm8yDsf5vkU8rBLKSXw1XvcRTqaTfRo7InJW/FzEbE66aZO82UVvbK7Qc+Xqcz+u40h4Xyn0hUYI +z+UPfvDrAfXWWmOS8sz6uUZg9zV7Ify+RNh3OxZR64tD5/3XK9U4XY96HswahdIs/A/iiCRmCmVu +ZHN0cmVhbQplbmRvYmoKMjIgMCBvYmoKPDwKL1R5cGUgL0ZvbnREZXNjcmlwdG9yCi9Gb250TmFt +ZSAvUU9GTkdXK0NNTUkxMgovRmxhZ3MgNAovRm9udEJCb3ggWy0zMSAtMjUwIDEwMjYgNzUwXQov +QXNjZW50IDY5NAovQ2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAtMTQK +L1N0ZW1WIDY1Ci9YSGVpZ2h0IDQzMQovQ2hhclNldCAoL2svcGkpCi9Gb250RmlsZSAyMSAwIFIK +Pj4KZW5kb2JqCjIzIDAgb2JqCjw8Ci9MZW5ndGgxIDEzOTkKL0xlbmd0aDIgNjcyMAovTGVuZ3Ro +MyAwCi9MZW5ndGggNzY3NiAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNqN +dAVU1OveLogSg3QjMSDdQ5d0d4cgMMAAo8MMDEN3qZsuURoEVIYSBGmkS0CQbqQREKSbb9R9zvn2 +uXete9es9Z/31/E+z8vOYmDMr+iIsIeoIeAofpCAkDRQWdcIJAQUEhIREBISBrCzm0BRMMjfagC7 +GQTpAUXApf+XgzISAkZhdCpgFMZPFwEHannCgCARIEhcGiQhLSQEFBYSkvqXIwIpDVQBe0EdgboC +QC0EHOIBYFdGuPkioc4uKEyZfx2BXA7cQJCUlATf73CgoisECXUAw4G6YJQLxBVT0QEMAxojHKAQ +lO8/UnDJuqBQbtKCgt7e3gJgVw8BBNJZjpsP6A1FuQCNIB4QpBfEEfhrYKAe2BXyZzIBADvQxAXq +8UdvjHBCeYORECBGAYM6QOAemAhPuCMECcQUBxpr6gD13SDwP846fxz4gH/vBggSAP073d/RvxJB +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 +BZ31Z7M1Fg3mFJZqw/6qhsX59CHimXzyA3IjC/b/A/xs7CMKZW5kc3RyZWFtCmVuZG9iagoyNCAw +IG9iago8PAovVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9SUlVSUFUrQ01SMTAKL0Zs +YWdzIDQKL0ZvbnRCQm94IFstNDAgLTI1MCAxMDA5IDc1MF0KL0FzY2VudCA2OTQKL0NhcEhlaWdo +dCA2ODMKL0Rlc2NlbnQgLTE5NAovSXRhbGljQW5nbGUgMAovU3RlbVYgNjkKL1hIZWlnaHQgNDMx +Ci9DaGFyU2V0ICgvZXF1YWwvb25lL3R3bykKL0ZvbnRGaWxlIDIzIDAgUgo+PgplbmRvYmoKMjUg +MCBvYmoKPDwKL0xlbmd0aDEgMTQ0MwovTGVuZ3RoMiA2OTMzCi9MZW5ndGgzIDAKL0xlbmd0aCA3 +OTE4ICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o10B1QT2rI2Hem9gwTp +PfQqvUvvgiAhCRAICYTQQXqV3nsVUVA60gWkI4gUqSJSQlFRkY6Uh3ruuffc/1/rvZW1ksw338ye +mf3N5uYwNhNWhSAdoVpIBFpYTAQoD1A3MBUTBwCBEiJAoDgxN7c5DA2H/gUTc1tCUV4wJEL+Pwjq +KCgIfY1pgNDXPAMkAqDnDQeISQDEpOXFZOSBQIA4ECj3LyISJQ/QAPnAIAADEYAeEgH1IuZWR3r4 +o2DOLujrY/71F8AH5geIycnJCP0OB6i6Q1EwMAgBMAChXaDu1yeCQXCAGRIMg6L9/5GCT9EFjfaQ +FxX19fUVAbl7iSBRzkr8QgBfGNoFYAr1gqJ8oBDAr4YBhiB36J/ORIi5AeYuMK8/uBnSCe0LQkEB +1wAcBoYivK4jvBEQKApwfTjATFcfYOQBRfwh6/8hCAH+mg1ATETs73R/Rf9KBEP8DgaBwUh3DxDC +H4ZwBjjB4FCAkZa+CNoPLQQAISC/iCC4F/I6HuQDgsFBjteE35WDAFqqJgDQdYN/tecFRsE80F4i +XjD4rxZFf6W5nrImAqKOdHeHItBexL/q04ChoODrsfuL/rlZNwTSFxH4l+EEQ0CcfjUB8fYQtUDA +PL2huhp/Ua4h4n9jzlA0QAoIBMrISQKgngCoH9hF9Fd6c38P6G+n2C/4uoPgQA+kB8DpugloMMwJ +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 +64sVww2AgluZ9A6Q7nbkKIHKM71VLhxZe/vgKdG6vBiONyEX4Jg5xon4nqmh1CTr8piTBwwakYJk +61xRINOJuysb98FkWp8OLM17aJmD2AT0O6oJV5Vk/gcmpCdpCmVuZHN0cmVhbQplbmRvYmoKMjYg +MCBvYmoKPDwKL1R5cGUgL0ZvbnREZXNjcmlwdG9yCi9Gb250TmFtZSAvUEpHV1NIK0NNUjEyCi9G +bGFncyA0Ci9Gb250QkJveCBbLTM0IC0yNTEgOTg4IDc1MF0KL0FzY2VudCA2OTQKL0NhcEhlaWdo +dCA2ODMKL0Rlc2NlbnQgLTE5NAovSXRhbGljQW5nbGUgMAovU3RlbVYgNjUKL1hIZWlnaHQgNDMx +Ci9DaGFyU2V0ICgvZXF1YWwvaS9sL20vb25lL3NpeCkKL0ZvbnRGaWxlIDI1IDAgUgo+PgplbmRv +YmoKMjcgMCBvYmoKPDwKL0xlbmd0aDEgMTQwNgovTGVuZ3RoMiA2MTgyCi9MZW5ndGgzIDAKL0xl +bmd0aCA3MTQ1ICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o14BVRUbdc2 +0iKdkh6Q7u7u7kZymIGBYQZhaJCUkkYaQZAGBaRbSemSEgUpaUkBBeQb9Xne933e/1/r+9asdebc +e19733vf+7rOzDosjPpGPAqOCAewKgKO5BHg5ZcElHSMLAT4AX5+IV5+fkE8FhZjKBIG/tuOx2IK +9vCEIuCS/4FQ8gDbI1E2ZXskCqiDgAOaXjBAQAgQEJUUEJPk5wcE+fkl/gYiPCQBZXtvqCOgwwto +IuBgTzwWJYS7nwfUyRmJ2ufvW4AdxAEISEiIcf8OBxTcwB5QkD0c0LFHOoPdUDuC7GGAEQIEBSP9 +/pGCXdoZiXSX5OPz8fHhtXfz5EV4OMlycAM+UKQzYAj2BHt4gx2BXy0DuvZu4L9a48VjAYydoZ5/ +HEYICNLH3gMMoAwwKAgM90SFeMEdwR4AanfASEMb0HMHw/+Atf8AuIG/DgcQ4BX4V7q/on8lgsJ/ +B9uDQAg3d3u4HxTuBECgMDCgp6rNi/RFcgP2cMdfQHuYJwIVb+9tD4XZO6AAv0u3B1QVDAB7VId/ +9ecJ8oC6Iz15PaGwXz3y/UqDOmYVuKMSws0NDEd64v2qTxnqAQahzt2P76/husIRPvCAv1cQKNwR +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 +RJPfjb8ToXVC+BrE3GClRe/5gZeJxtFRUPcDm92lBLOJMndIOQ3uJUXXCngY+l3V+jKjPimfNqlM +DpYKNraJRydtz+N9/vaWiOz4xq55LwmjUtEim+9W3G5Xj/NnsfZa8Zbnb/JD9aQHX1S5Zyc1tUDS +zs3VWtFZoidY7FN1AwW9ry+gMhE9RFO7Q4BapofHp2blso78EGcsGdVXh6fzsDVyEI/ZHItNiPWb +spAbcFh8P1O5QmRPHM+0cFFNySPyxmmz6Btb6OwlPWiR6EZydfPdAJkGdVv1Uoz3e7UBdtxTVlbQ +huady3Ap1kMP4pxydcdRuyTeTh9IadBr5unK9zpcm6mWMmCq7MtkpVDMi3dph2+03rWPfPYHOAAl +TqMmnP8B+jXYFQplbmRzdHJlYW0KZW5kb2JqCjI4IDAgb2JqCjw8Ci9UeXBlIC9Gb250RGVzY3Jp +cHRvcgovRm9udE5hbWUgL0RSWkpDUStDTVNZMTAKL0ZsYWdzIDQKL0ZvbnRCQm94IFstMjkgLTk2 +MCAxMTE2IDc3NV0KL0FzY2VudCA3NTAKL0NhcEhlaWdodCA2ODMKL0Rlc2NlbnQgLTE5NAovSXRh +bGljQW5nbGUgLTE0Ci9TdGVtViA0MAovWEhlaWdodCA0MzEKL0NoYXJTZXQgKC9hcnJvd3JpZ2h0 +L2luZmluaXR5KQovRm9udEZpbGUgMjcgMCBSCj4+CmVuZG9iagoyOSAwIG9iago8PAovTGVuZ3Ro +IDQ5NCAgICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjabZNNb6MwEIbv/Arv +IVJ6oJiPfFUIicRBymHbqolWvSb2JEUKBhmQNv9+PR5I1VUOQY9n3hm/A5PJr/e9n6v6BH78zNkH +tHVvJPib38fGm0xELfsKdPcKoECN2faFvZta7qFj081O7HTZPVnxTstrr2BUPRat4VLqbwnew6YH ++PRlBX9D7p/68tqV2ucoPpTd1Yoe5pkNsp9B5or+gGnLWr+w8JlzbgNbrTZ1hWO0XjBYYcFo7lxq +ZQY/7ITuvDBiqpTdcHJPWdn3gcX7W9tBtdPn2ktTFnzYZNuZm/P45AVvRoEp9YVNf1qzqX3fNFdA +G4x7WcYUnG1HO//rsQIWPJzxrjncGmCRO4fkS9YK2uYowRz1BbyU84ylRZF5oNV/uaHidB6kYmGl +YmkfPM5nrmLMxXet/DoaL41d1+V2nVkOHRdz5IjiW+SY4ivkhJgjz4hd7Zz0BfKC4jnykjhEXhFv +kHPiGHlN7O7aEEfIglggb4kT5ILuQp/J4B81yeB/iTz4x7uSwf/C8gproyhEbznWch7hLMJxvEI/ +InQajv1FRHHsKWJinFckxOhZzOhNuz5zYtdnRexqcd4ojObD13BvH78k7t19SWRvjN0ft5xuLXAh +Sg33/W3qBqvczy3++E/D01vh/QMETByHCmVuZHN0cmVhbQplbmRvYmoKOSAwIG9iago8PAovVHlw +ZSAvRm9udAovU3VidHlwZSAvVHlwZTEKL0Jhc2VGb250IC9ZUUpTREorQ01FWDEwCi9Gb250RGVz +Y3JpcHRvciAxOCAwIFIKL0ZpcnN0Q2hhciA4OAovTGFzdENoYXIgODgKL1dpZHRocyAxMSAwIFIK +L1RvVW5pY29kZSAyOSAwIFIKPj4KZW5kb2JqCjMwIDAgb2JqCjw8Ci9MZW5ndGggNjk2ICAgICAg +IAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNptVE1v4jAQvedXeA+V2gPFHySBCiHZ +CZE4bFuVarVXSEw3EklQCIf++/UbE6xWPRBNnt/MvPELc/frdTvRVbe3E/XI2Zs9d5e+tJPs9+4U +3d3lXXlpbDs8W1vZajw9P7HXviu3dmD32SbftPXw4MibtjxeKjuyfiYZ+1G3gYI+7P7d/p2UTVML +Ptlf6uNQtxMO8ns9HB3px3PmQPYVZJT0x/bnumufmHjknDtg3VZZ12CMczS9SmHTUdyhbqv+qoft +oS4SklV1OVzf6Fk27j6QvP08D7bZtIcuWi7Z9M0dnof+kzQ+RNOXvrJ93X6w+6/S3NH2cjodLWQw +Hq1WrLIHV9HN/7xrLJv+OOON8/55skzSu/C6yq6y59OutP2u/bDRkvMVWxbFKrJt9e1Mcp+yP4zc +1HH5HA+l45UDDOI1AUY4QKCaiD2QAECK8CkmB7AAoAnIOADUELkHFIDCxVJ4IHWARLpcEGoyAEiX +hgCqodBWgcG5AjBDekxd+AzCYrBjdJFJAh0JGKlnJGBodNGLMJzGXEaE4YwCMA/DGaQbE4Zz6hyQ +h+EMamQ8DJdJAOo2nLv18Xpn8/G6y3+7/uoMVwukcciQkqMrlx6fI/aVFgbxzMdrxN4CDQ0uiWKq +c52PcukWhaSaBeEF5hbE54Zi722OWPq+hEvfN8e1SN83Rx3p+xaE+75uYhenPiYOasrYkLXkdZyB +r7wZEvqV8THcVpn3leLc4wXitceJT3Uk1Z9xf1foG1MvJTF7XPgYeEIcIYCn1EsoaEipl1TQluae +g7tKqQ7Pgc+vdgLX3OvBPWsR/NIy+KVV8EvPgl86Dn7pJPil0+CX1sEvnQe/jAx+mUXwKxM3v+jL +oi8J/2zsodvSKC997/YJLStaE1gQdWtv++zUnZBFP1qE4+bF20sR/Qdx7YPECmVuZHN0cmVhbQpl +bmRvYmoKNyAwIG9iago8PAovVHlwZSAvRm9udAovU3VidHlwZSAvVHlwZTEKL0Jhc2VGb250IC9J +UUpLSU4rQ01NSTEwCi9Gb250RGVzY3JpcHRvciAyMCAwIFIKL0ZpcnN0Q2hhciAxMDcKL0xhc3RD +aGFyIDExMAovV2lkdGhzIDEzIDAgUgovVG9Vbmljb2RlIDMwIDAgUgo+PgplbmRvYmoKMzEgMCBv +YmoKPDwKL0xlbmd0aCA2OTYgICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp4 +2m1UTW/iMBC951d4D5XaA8UfJIEKIdkJkThsW5VqtVdITDcSSVAIh/779RsTrFY9EE2e38y88Qtz +9+t1O9FVt7cT9cjZmz13l760k+z37hTd3eVdeWlsOzxbW9lqPD0/sde+K7d2YPfZJt+09fDgyJu2 +PF4qO7J+Jhn7UbeBgj7s/t3+nZRNUws52V/q41C3Ew7yez0cHenHc+ZA9hVklPTH9ue6a5+YeOSc +O2DdVlnXYIxzNL1KYdNR3KFuq/6qh+2hLhKSVXU5XN/oWTbuPpC8/TwPttm0hy5aLtn0zR2eh/6T +ND5E05e+sn3dfrD7r9Lc0fZyOh0tZDAerVassgdX0c3/vGssm/44443z/nmyTNK78LrKrrLn0660 +/a79sNGS8xVbFsUqsm317Uxyn7I/jNzUcfkcD6XjlQMM4jUBRjhAoJqIPZAAQIrwKSYHsACgCcg4 +ANQQuQcUgMLFUnggdYBEulwQajIASJeGAKqh0FaBwbkCMEN6TF34DMJisGN0kUkCHQkYqWckYGh0 +0YswnMZcRoThjAIwD8MZpBsThnPqHJCH4QxqZDwMl0kA6jacu/Xxemfz8brLf7v+6gxXC6RxyJCS +oyuXHp8j9pUWBvHMx2vE3gINDS6JYqpznY9y6RaFpJoF4QXmFsTnhmLvbY5Y+r6ES983x7VI3zdH +Hen7FoT7vm5iF6c+Jg5qytiQteR1nIGvvBkS+pXxMdxWmfeV4tzjBeK1x4lPdSTVn3F/V+gbUy8l +MXtc+Bh4QhwhgKfUSyhoSKmXVNCW5p6Du0qpDs+Bz692Atfc68E9axH80jL4pVXwS8+CXzoOfukk ++KXT4JfWwS+dB7+MDH6ZRfArEze/6MuiLwn/bOyh29IoL33v9gktK1oTWBB1a2/77NSdkEU/WoTj +5sXbSxH9B6P7g84KZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0 +eXBlIC9UeXBlMQovQmFzZUZvbnQgL1FPRk5HVytDTU1JMTIKL0ZvbnREZXNjcmlwdG9yIDIyIDAg +UgovRmlyc3RDaGFyIDI1Ci9MYXN0Q2hhciAxMDcKL1dpZHRocyAxNiAwIFIKL1RvVW5pY29kZSAz +MSAwIFIKPj4KZW5kb2JqCjMyIDAgb2JqCjw8Ci9MZW5ndGggNzM5ICAgICAgIAovRmlsdGVyIC9G +bGF0ZURlY29kZQo+PgpzdHJlYW0KeNptVU1v4jAUvOdXeA+V2gPFdkgCVYRk50PisG1VqtVeITHd +SJCgEA799+vxI3jZ9gAaP4+fZ+zB3P14XU9U3W3NJHzk7M2cunNfmUn2c3MM7u7yrjofTDs8G1Ob +epw9PbHXvqvWZmD32Spftc3wYMmrttqfazOyvidp89G0noJ92P27+T2pDr3gk+252Q9NO+HgvjfD +3nK+m2a2xm5qzC35ZfpT07VPTDxyzm2haOusO8DDKZhedLDpqGzXtHV/EcO2kBYIyeqmGi4j910d +7GFg8frzNJjDqt11QZqy6ZudPA39p1P4EExf+tr0TfvB7m+U2Zn1+XjcG6hgPFguWW12tqH1/rw5 +GDb9zuCV8v55NEy6sSBVVVeb03FTmX7Tfpgg5XzJ0rJcBqat/5tLaMV2N1ITS+VzfIUqWgapDC2W +MQrcYlvAZKipMLeFsLQ4ooLFQRoLixPlChYHaYLJJEMjLtBDoYdaXHexukYFyXxUVP3Z9BftPFxg +GUdjKXkMLKkOBTwkrIFnhAvgiHbgwDFh1+eys1sLnVJI15NMxDE+GGd+vMA49+MM4+If/sgpb2vg +CedBhDgLAQ/2JBNgSVzoE84D1zNg50FmjuM8yBxaBV2DwiGLhOoKeE5rHcd547nj0B0U8CKcNxHB +vyBfpeOTp8xxCuJIYPLh9pWCbhv6paRrzIETwvAdUk8FTkg9Q3BCOiMNPdElAjiTiDgROFFBfqEh +KskXesac+NCQ5FQHPyF+jj4J6XR3qTjpxHkq4XOjpM+NCn1u1MznRkU+Nyr2uVGJz41SPjeKsqKg +R128O37u86SK2zyp8jZPmt/mSYuvedLya5506POkZz5POvJ50rHPk058nvTc50kvfJ608nnS2udJ +Zz5POvd50oXPky59njLu85QJn6dM+jxls+uduV+++6XjbcI7en31qnPf2wfRPbbuocMT17Tm+h4f +uyNWuY97yMe/DYxeyuAv8fOoUAplbmRzdHJlYW0KZW5kb2JqCjUgMCBvYmoKPDwKL1R5cGUgL0Zv +bnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvUlJVUlBVK0NNUjEwCi9Gb250RGVzY3JpcHRv +ciAyNCAwIFIKL0ZpcnN0Q2hhciA0OQovTGFzdENoYXIgNjEKL1dpZHRocyAxNSAwIFIKL1RvVW5p +Y29kZSAzMiAwIFIKPj4KZW5kb2JqCjMzIDAgb2JqCjw8Ci9MZW5ndGggNzM5ICAgICAgIAovRmls +dGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNptVU1v4jAUvOdXeA+V2gPFdkgCVYRk50PisG1V +qtVeITHdSJCgEA799+vxI3jZ9gAaP4+fZ+zB3P14XU9U3W3NJHzk7M2cunNfmUn2c3MM7u7yrjof +TDs8G1Obepw9PbHXvqvWZmD32Spftc3wYMmrttqfazOyvidp89G0noJ92P27+T2pDr2Qk+252Q9N +O+HgvjfD3nK+m2a2xm5qzC35ZfpT07VPTDxyzm2haOusO8DDKZhedLDpqGzXtHV/EcO2kBYIyeqm +Gi4j910d7GFg8frzNJjDqt11QZqy6ZudPA39p1P4EExf+tr0TfvB7m+U2Zn1+XjcG6hgPFguWW12 +tqH1/rw5GDb9zuCV8v55NEy6sSBVVVeb03FTmX7Tfpgg5XzJ0rJcBqat/5tLaMV2N1ITS+VzfIUq +WgapDC2WMQrcYlvAZKipMLeFsLQ4ooLFQRoLixPlChYHaYLJJEMjLtBDoYdaXHexukYFyXxUVP3Z +9BftPFxgGUdjKXkMLKkOBTwkrIFnhAvgiHbgwDFh1+eys1sLnVJI15NMxDE+GGd+vMA49+MM4+If +/sgpb2vgCedBhDgLAQ/2JBNgSVzoE84D1zNg50FmjuM8yBxaBV2DwiGLhOoKeE5rHcd547nj0B0U +8CKcNxHBvyBfpeOTp8xxCuJIYPLh9pWCbhv6paRrzIETwvAdUk8FTkg9Q3BCOiMNPdElAjiTiDgR +OFFBfqEhKskXesac+NCQ5FQHPyF+jj4J6XR3qTjpxHkq4XOjpM+NCn1u1MznRkU+Nyr2uVGJz41S +PjeKsqKgR128O37u86SK2zyp8jZPmt/mSYuvedLya5506POkZz5POvJ50rHPk058nvTc50kvfJ60 +8nnS2udJZz5POvd50oXPky59njLu85QJn6dM+jxls+uduV+++6XjbcI7en31qnPf2wfRPbbuocMT +17Tm+h4fuyNWuY97yMe/DYxeyuAvK5CoWgplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKPDwKL1R5 +cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvUEpHV1NIK0NNUjEyCi9Gb250RGVz +Y3JpcHRvciAyNiAwIFIKL0ZpcnN0Q2hhciA0OQovTGFzdENoYXIgMTA5Ci9XaWR0aHMgMTQgMCBS +Ci9Ub1VuaWNvZGUgMzMgMCBSCj4+CmVuZG9iagozNCAwIG9iago8PAovTGVuZ3RoIDkwMCAgICAg +ICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjabVVNb9s6ELzrV7CHAOnBNT8kUi4M +A6RkAzn0A03w8K6OxOQJiGVDtg/594+za5ttkUOM1XC5Ozschneffj7OfL9/jjPzRYpf8bg/T12c +Nd+2h+Lurt13510cT99j7GN/XT1+FT+nffcYT+K+eWgfxuH0OSU/jN3buY/XrI+TQnwdxpyCPuL+ +Kf4763bHdyVnz+fh7TSMM4nkp+H0lpI+XBcJFH+Cgjb9E6fjsB+/CvVFSpmA9dg3+x3GOBbzCxUx +v5J7GcZ+uvARz2BXKC36oTtdvui32yU9sPnx/XiKu4fxZV8sl2L+Ky0eT9M7cfxczH9MfZyG8VXc +/0ktLT2eD4e3CBpCFquV6ONLqpjm/77dRTH/cMZbztP7IQpN34p5dfs+Hg/bLk7b8TUWSylXYrnZ +rIo49n+tacdbnl+uuXXKlU360XpRrYql0ilWhoDaAigBVATYEoAF4AB4vwHgAQTeogGgnmp5iwew +BrAhwAHQ1ACVtVoYANTAMuAAUD0iplpkGNQwXMODR6lSXKG3lCkulhUyKs7QqGEhhFW8BcQshrPU +20jwsKBgKwZqANDDLgC4NQAHTs6xQOjisOjQVkstE+ABeJ8l9JjcMw+aJaBBsFnTgHqhzpoG1Ag+ +axpQI6yzpgH1Gpk1bTBXo2+apsO+nmqtrqfc/bedLobQWqGOVCRYAC+pKW4p5iNXFJeEbyjmk2/A +UlreCxkkS6JwNJKOWrYtYuJcrTGm3LBK5AnmUCJH8ZFY1FGsgmkQLzgHumvJXoDCWnGMOlpzjL2a +OZRkoJqtQvkLjinfc0z5Le8FN73meIGYz0qBm6G+0mCvYZ7JvSlmpckkhrWSATGZuApk0YpjqkNa +GUP5PKMEN8MzSspn83rMbvj+SBjIsO0V4cxZgX/JmhjkVJyvYYWK76/GLBVfuxqcLZ+XA0/rOAY3 +y30d6ttLHdS03JdMbLlvS/Ga8ivKZ61KzOIuvgIHR1p5A/O6i1bwj2OtNDi4ku8EvOTYV3T5Xc06 +UH5gj+GMHPGxlnJajnEubs0xXccNx+BT/+YZL6kO31CV/e919r832f++zP73Vfa/t9n/3mX/+zr7 +P8js/6Cy/4PO/g8m+z+U2f8hZP+HJvu/MXmWprzNSLecbjX+ueMpur0b3Xma0pNC7xW9FHgjhjHe +nrTD/oBd9Edv4fXxxdePTfE/rljqHgplbmRzdHJlYW0KZW5kb2JqCjggMCBvYmoKPDwKL1R5cGUg +L0ZvbnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvRFJaSkNRK0NNU1kxMAovRm9udERlc2Ny +aXB0b3IgMjggMCBSCi9GaXJzdENoYXIgMzMKL0xhc3RDaGFyIDQ5Ci9XaWR0aHMgMTIgMCBSCi9U +b1VuaWNvZGUgMzQgMCBSCj4+CmVuZG9iagoxMCAwIG9iago8PAovVHlwZSAvUGFnZXMKL0NvdW50 +IDEKL0tpZHMgWzIgMCBSXQo+PgplbmRvYmoKMzUgMCBvYmoKPDwKL1R5cGUgL0NhdGFsb2cKL1Bh +Z2VzIDEwIDAgUgo+PgplbmRvYmoKMzYgMCBvYmoKPDwKL1Byb2R1Y2VyIChNaUtUZVggcGRmVGVY +LTEuNDAuMjMpCi9DcmVhdG9yIChUZVgpCi9DcmVhdGlvbkRhdGUgKEQ6MjAyMjAzMDUyMDMxNDEr +MDEnMDAnKQovTW9kRGF0ZSAoRDoyMDIyMDMwNTIwMzE0MSswMScwMCcpCi9UcmFwcGVkIC9GYWxz +ZQovUFRFWC5GdWxsYmFubmVyIChUaGlzIGlzIE1pS1RlWC1wZGZUZVggNC44LjAgKDEuNDAuMjMp +KQo+PgplbmRvYmoKeHJlZgowIDM3CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDQ5MiAwMDAw +MCBuIAowMDAwMDAwMzgwIDAwMDAwIG4gCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDA1MDQxNyAw +MDAwMCBuIAowMDAwMDUxMzk0IDAwMDAwIG4gCjAwMDAwNTIzNjkgMDAwMDAgbiAKMDAwMDA0OTQ4 +MiAwMDAwMCBuIAowMDAwMDUzNTA2IDAwMDAwIG4gCjAwMDAwNDg1NDkgMDAwMDAgbiAKMDAwMDA1 +MzY2MyAwMDAwMCBuIAowMDAwMDAwNjE1IDAwMDAwIG4gCjAwMDAwMDA2NDAgMDAwMDAgbiAKMDAw +MDAwMDc0NCAwMDAwMCBuIAowMDAwMDAwNzg0IDAwMDAwIG4gCjAwMDAwMDExMjEgMDAwMDAgbiAK +MDAwMDAwMTE5OSAwMDAwMCBuIAowMDAwMDAxNjkxIDAwMDAwIG4gCjAwMDAwMDg3MzkgMDAwMDAg +biAKMDAwMDAwODk3MCAwMDAwMCBuIAowMDAwMDE2MzgxIDAwMDAwIG4gCjAwMDAwMTY2MDMgMDAw +MDAgbiAKMDAwMDAyMzk1NSAwMDAwMCBuIAowMDAwMDI0MTc4IDAwMDAwIG4gCjAwMDAwMzE5NzMg +MDAwMDAgbiAKMDAwMDAzMjIwMiAwMDAwMCBuIAowMDAwMDQwMjM5IDAwMDAwIG4gCjAwMDAwNDA0 +NzMgMDAwMDAgbiAKMDAwMDA0NzczNyAwMDAwMCBuIAowMDAwMDQ3OTc1IDAwMDAwIG4gCjAwMDAw +NDg3MDYgMDAwMDAgbiAKMDAwMDA0OTY0MSAwMDAwMCBuIAowMDAwMDUwNTc1IDAwMDAwIG4gCjAw +MDAwNTE1NTAgMDAwMDAgbiAKMDAwMDA1MjUyNiAwMDAwMCBuIAowMDAwMDUzNzIxIDAwMDAwIG4g +CjAwMDAwNTM3NzIgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSAzNwovUm9vdCAzNSAwIFIKL0lu +Zm8gMzYgMCBSCi9JRCBbPEM2OTc3NDAyQzA1MDFDRUQ2NUZDQzY3RThCRTk2OUZGPiA8QzY5Nzc0 +MDJDMDUwMUNFRDY1RkNDNjdFOEJFOTY5RkY+XSA+PgpzdGFydHhyZWYKNTM5OTEKJSVFT0YK + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: inktmp3voub5jt + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.log" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.log + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KSAocHJlbG9hZGVkIGZvcm1hdD1wZGZsYXRleCAyMDIxLjguMjMpICA1IE1BUiAyMDIyIDIw +OjMxCmVudGVyaW5nIGV4dGVuZGVkIG1vZGUKKipDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1RlbXAvaW5rdG1wM3ZvdWI1anQvaW5wdXQudGV4CihDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xv +Y2FsL1RlbXAvaW5rdG1wM3ZvdWI1anQvaW5wdXQudGV4CkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDEKTDMgcHJvZ3JhbW1pbmcgbGF5ZXIgPDIwMjEtMDctMTI+CihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvc3RhbmRhbG9uZVxz +dGFuZGFsb25lLmMKbHMKRG9jdW1lbnQgQ2xhc3M6IHN0YW5kYWxvbmUgMjAxOC8wMy8yNiB2MS4z +YSBDbGFzcyB0byBjb21waWxlIFRlWCBzdWItZmlsZXMgc3RhbgpkYWxvbmUKKEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xzaGVsbGVz +Yy5zdHkKUGFja2FnZTogc2hlbGxlc2MgMjAxOS8xMS8wOCB2MS4wYyB1bmlmaWVkIHNoZWxsIGVz +Y2FwZSBpbnRlcmZhY2UgZm9yIExhVGVYClBhY2thZ2Ugc2hlbGxlc2MgSW5mbzogUmVzdHJpY3Rl +ZCBzaGVsbCBlc2NhcGUgZW5hYmxlZCBvbiBpbnB1dCBsaW5lIDc3LgopCihDOlxVc2Vyc1xqb25h +dFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZmx1YXRl +eC5zdHkKUGFja2FnZTogaWZsdWF0ZXggMjAxOS8xMC8yNSB2MS41IGlmbHVhdGV4IGxlZ2FjeSBw +YWNrYWdlLiBVc2UgaWZ0ZXggaW5zdGVhZC4KCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZnRleC5zdHkKUGFja2FnZTogaWZ0 +ZXggMjAyMC8wMy8wNiB2MS4wZCBUZVggZW5naW5lIHRlc3RzCikpCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtleXZhbFx4a2V5dmFsLnN0 +eQpQYWNrYWdlOiB4a2V5dmFsIDIwMjAvMTEvMjAgdjIuOCBwYWNrYWdlIG9wdGlvbiBwcm9jZXNz +aW5nIChIQSkKCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0 +ZXgvZ2VuZXJpYy94a2V5dmFsXHhrZXl2YWwudGV4CihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExv +Y2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxzLnRleApcWEtW +QHRva3M9XHRva3MxNgpcWEtWQHRlbXBhQHRva3M9XHRva3MxNwoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxca2V5dmFsLnRl +eCkpClxYS1ZAZGVwdGg9XGNvdW50MTgyCkZpbGU6IHhrZXl2YWwudGV4IDIwMTQvMTIvMDMgdjIu +N2Ega2V5PXZhbHVlIHBhcnNlciAoSEEpCikpClxzYUBpbnRlcm5hbD1cY291bnQxODMKXGNAc2Fw +YWdlPVxjb3VudDE4NAoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYwpmZwpGaWxlOiBzdGFuZGFsb25l +LmNmZyAyMDE4LzAzLzI2IHYxLjNhIERlZmF1bHQgY29uZmlndXJhdGlvbiBmaWxlIGZvciAnc3Rh +bmRhbG9uCmUnIGNsYXNzCikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JyZXBydC5jbApzCkRvY3VtZW50IENsYXNz +OiBzY3JyZXBydCAyMDIxLzExLzEzIHYzLjM1IEtPTUEtU2NyaXB0IGRvY3VtZW50IGNsYXNzIChy +ZXBvcnQpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmtiYXNlLnN0CnkKUGFja2FnZTogc2Nya2Jhc2UgMjAyMS8x +MS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChLT01BLVNjcmlwdC1kZXBlbmRlbnQgYgph +c2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JiYXNlLnN0eQpQYWNrYWdlOiBz +Y3JiYXNlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFja2FnZSAoS09NQS1TY3JpcHQt +aW5kZXBlbmRlbnQgCmJhc2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmls +ZS5zdAp5ClBhY2thZ2U6IHNjcmxmaWxlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFj +a2FnZSAoZmlsZSBsb2FkIGhvb2tzKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmlsZS1obwpvay0zLjM0LnN0 +eQpQYWNrYWdlOiBzY3JsZmlsZS1ob29rLTMuMzQgMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlw +dCBwYWNrYWdlICh1c2luZyBMYVRlWCBoCm9va3MpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxM +b2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5ClBh +Y2thZ2U6IHNjcmxvZ28gMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChsb2dv +KQopKSkKQXBwbHlpbmc6IFsyMDIxLzA1LzAxXSBVc2FnZSBvZiByYXcgb3IgY2xhc3NpYyBvcHRp +b24gbGlzdCBvbiBpbnB1dCBsaW5lIDI1Mi4KQWxyZWFkeSBhcHBsaWVkOiBbMDAwMC8wMC8wMF0g +VXNhZ2Ugb2YgcmF3IG9yIGNsYXNzaWMgb3B0aW9uIGxpc3Qgb24gaW5wdXQgbGluZQogMzY4Lgop +KQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHRvY2Jhc2ljLnN0CnkKUGFja2FnZTogdG9jYmFzaWMgMjAyMS8xMS8xMyB2 +My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChoYW5kbGluZyB0b2MtZmlsZXMpClxzY3JAZHRlQHRv +Y2xpbmVAbnVtYmVyd2lkdGg9XHNraXA0Nwpcc2NyQGR0ZUB0b2NsaW5lQG51bWJveD1cYm94NTAK +KQpQYWNrYWdlIHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3IgYHRvYycgb21pdHRl +ZAoodG9jYmFzaWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBcYmJsQHNldEBsYW5n +dWFnZSBvbiBpbnB1dCBsaW5lIDEzNy4KCgpMYVRlWCBGb250IFdhcm5pbmc6IEZvbnQgc2hhcGUg +YE9UMS9jbXIvbS9uJyBpbiBzaXplIDwxNT4gbm90IGF2YWlsYWJsZQooRm9udCkgICAgICAgICAg +ICAgIHNpemUgPDE0LjQ+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxpbmUgMjQ4Ny4KCgooQzpcVXNl +cnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2Ny +aXB0XHR5cGVhcmVhLnN0CnkKUGFja2FnZTogdHlwZWFyZWEgMjAyMS8xMS8xMyB2My4zNSBLT01B +LVNjcmlwdCBwYWNrYWdlICh0eXBlIGFyZWEpClx0YUBiY29yPVxza2lwNDgKXHRhQGRpdj1cY291 +bnQxODUKXHRhQGhibGs9XHNraXA0OQpcdGFAdmJsaz1cc2tpcDUwClx0YUB0ZW1wPVxza2lwNTEK +XGZvb3RoZWlnaHQ9XHNraXA1MgoKClBhY2thZ2UgdHlwZWFyZWEgV2FybmluZzogRElWIGZvciAx +NS4wcHQgYW5kIHVzZWQgcGFwZXJzaXplCih0eXBlYXJlYSkgICAgICAgICAgICAgICAgbm90IGRl +ZmluZWQhCih0eXBlYXJlYSkgICAgICAgICAgICAgICAgVXNpbmcgRElWPWNhbGMuCgpESVYgY2Fs +Y3VsYXRpb24gZm9yIHR5cGVhcmVhIHdpdGggZ29vZCBsaW5ld2lkdGguClBhY2thZ2UgdHlwZWFy +ZWEgSW5mbzogVGhlc2UgYXJlIHRoZSB2YWx1ZXMgZGVzY3JpYmluZyB0aGUgbGF5b3V0OgoodHlw +ZWFyZWEpICAgICAgICAgICAgIERJViAgPSAxNgoodHlwZWFyZWEpICAgICAgICAgICAgIEJDT1Ig +PSAwLjBwdAoodHlwZWFyZWEpICAgICAgICAgICAgIFxwYXBlcndpZHRoICAgICAgPSA1OTcuNTA3 +OTNwdAoodHlwZWFyZWEpICAgICAgICAgICAgICBcdGV4dHdpZHRoICAgICAgPSA0ODUuNDc1MjJw +dAoodHlwZWFyZWEpICAgICAgICAgICAgICBESVYgZGVwYXJ0dXJlICAgPSAwJQoodHlwZWFyZWEp +ICAgICAgICAgICAgICBcZXZlbnNpZGVtYXJnaW4gPSAtMTYuMjUzNjNwdAoodHlwZWFyZWEpICAg +ICAgICAgICAgICBcb2Rkc2lkZW1hcmdpbiAgPSAtMTYuMjUzNjNwdAoodHlwZWFyZWEpICAgICAg +ICAgICAgIFxwYXBlcmhlaWdodCAgICAgPSA4NDUuMDQ2OTRwdAoodHlwZWFyZWEpICAgICAgICAg +ICAgICBcdGV4dGhlaWdodCAgICAgPSA2OTguOTk4MjZwdAoodHlwZWFyZWEpICAgICAgICAgICAg +ICBcdG9wbWFyZ2luICAgICAgPSAtNjguOTU0NDJwdAoodHlwZWFyZWEpICAgICAgICAgICAgICBc +aGVhZGhlaWdodCAgICAgPSAyMi40OTk5NHB0Cih0eXBlYXJlYSkgICAgICAgICAgICAgIFxoZWFk +c2VwICAgICAgICA9IDI2Ljk5OTkycHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXHRvcHNraXAg +ICAgICAgID0gMTUuMHB0Cih0eXBlYXJlYSkgICAgICAgICAgICAgIFxmb290c2tpcCAgICAgICA9 +IDYyLjk5OTgzcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXGJhc2VsaW5lc2tpcCAgID0gMTcu +OTk5OTVwdAoodHlwZWFyZWEpICAgICAgICAgICAgICBvbiBpbnB1dCBsaW5lIDE3NDMuCikKXGNA +cGFydD1cY291bnQxODYKXGNAY2hhcHRlcj1cY291bnQxODcKXGNAc2VjdGlvbj1cY291bnQxODgK +XGNAc3Vic2VjdGlvbj1cY291bnQxODkKXGNAc3Vic3Vic2VjdGlvbj1cY291bnQxOTAKXGNAcGFy +YWdyYXBoPVxjb3VudDE5MQpcY0BzdWJwYXJhZ3JhcGg9XGNvdW50MTkyClxzY3JAZHRlQGNoYXB0 +ZXJAbWF4bnVtd2lkdGg9XHNraXA1MwpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRp +YmlsaXR5IGRlZmF1bHQgYGFmdGVyaW5kZW50PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAg +Zm9yIGBcY2hhcHRlciBvbiBpbnB1dCBsaW5lIDU3MTcuClxzY3JAZHRlQHNlY3Rpb25AbWF4bnVt +d2lkdGg9XHNraXA1NApDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRl +ZmF1bHQgYHJ1bmluPWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc2VjdGlvbiBv +biBpbnB1dCBsaW5lIDU3MjguCkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxp +dHkgZGVmYXVsdCBgYWZ0ZXJpbmRlbnQ9YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3Ig +YFxzZWN0aW9uIG9uIGlucHV0IGxpbmUgNTcyOC4KXHNjckBkdGVAcGFydEBtYXhudW13aWR0aD1c +c2tpcDU1CkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBg +YWZ0ZXJpbmRlbnQ9dHJ1ZScKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBccGFydCBvbiBpbnB1 +dCBsaW5lIDU3MzcuClxzY3JAZHRlQHN1YnNlY3Rpb25AbWF4bnVtd2lkdGg9XHNraXA1NgpDbGFz +cyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmluPWJ5c2ln +bicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc3Vic2VjdGlvbiBvbiBpbnB1dCBsaW5lIDU3 +NDcuCkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0 +ZXJpbmRlbnQ9YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJzZWN0aW9uIG9u +IGlucHV0IGxpbmUgNTc0Ny4KXHNjckBkdGVAc3Vic3Vic2VjdGlvbkBtYXhudW13aWR0aD1cc2tp +cDU3CkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgcnVu +aW49YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJzdWJzZWN0aW9uIG9uIGlu +cHV0IGxpbmUgNTc1Ny4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBk +ZWZhdWx0IGBhZnRlcmluZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHN1 +YnN1YnNlY3Rpb24gb24gaW5wdXQgbGluZSA1NzU3Lgpcc2NyQGR0ZUBwYXJhZ3JhcGhAbWF4bnVt +d2lkdGg9XHNraXA1OApDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRl +ZmF1bHQgYHJ1bmluPWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBccGFyYWdyYXBo +IG9uIGlucHV0IGxpbmUgNTc2OC4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJp +bGl0eSBkZWZhdWx0IGBhZnRlcmluZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZv +ciBgXHBhcmFncmFwaCBvbiBpbnB1dCBsaW5lIDU3NjguClxzY3JAZHRlQHN1YnBhcmFncmFwaEBt +YXhudW13aWR0aD1cc2tpcDU5CkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxp +dHkgZGVmYXVsdCBgcnVuaW49YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJw +YXJhZ3JhcGggb24gaW5wdXQgbGluZSA1Nzc4LgpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBj +b21wYXRpYmlsaXR5IGRlZmF1bHQgYGFmdGVyaW5kZW50PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAg +ICAgICAgZm9yIGBcc3VicGFyYWdyYXBoIG9uIGlucHV0IGxpbmUgNTc3OC4KXGFib3ZlY2FwdGlv +bnNraXA9XHNraXA2MApcYmVsb3djYXB0aW9uc2tpcD1cc2tpcDYxClxjQHB0aUBuYkBzaWRAYkB4 +PVxib3g1MQpQYWNrYWdlIHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3IgYGxvZicg +b21pdHRlZAoodG9jYmFzaWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBcYmJsQHNl +dEBsYW5ndWFnZSBvbiBpbnB1dCBsaW5lIDY5NTguCgpcc2NyQGR0ZUBmaWd1cmVAbWF4bnVtd2lk +dGg9XHNraXA2MgpcY0BmaWd1cmU9XGNvdW50MTkzClBhY2thZ2UgdG9jYmFzaWMgSW5mbzogYmFi +ZWwgZXh0ZW5zaW9uIGZvciBgbG90JyBvbWl0dGVkCih0b2NiYXNpYykgICAgICAgICAgICAgYmVj +YXVzZSBvZiBtaXNzaW5nIFxiYmxAc2V0QGxhbmd1YWdlIG9uIGlucHV0IGxpbmUgNjk3NC4KClxz +Y3JAZHRlQHRhYmxlQG1heG51bXdpZHRoPVxza2lwNjMKXGNAdGFibGU9XGNvdW50MTk0CkNsYXNz +IHNjcnJlcHJ0IEluZm86IFJlZGVmaW5pbmcgYFxudW1iZXJsaW5lJyBvbiBpbnB1dCBsaW5lIDcx +NDIuClxiaWJpbmRlbnQ9XGRpbWVuMTM4CikgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxc +UHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9wcmV2aWV3XHByZXZpZXcuc3R5ClBhY2thZ2U6IHBy +ZXZpZXcgMjAxNy8wNC8yNCAxMy4xIChBVUNUZVgvcHJldmlldy1sYXRleCkKCihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbHVhdGV4ODVcbHVh +dGV4ODUuc3R5ClBhY2thZ2U6IGx1YXRleDg1IDIwMTYvMDYvMTUgdjEuNCBwZGZ0ZXggYWxpYXNl +cyBmb3IgbHVhdGV4CikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9wcmV2aWV3XHBydGlnaHRwYWdlLmRlZgpcUHJldmlld0JvcmRlcj1cZGlt +ZW4xMzkKKQpccHJAc25pcHBldD1cY291bnQxOTUKXHByQGJveD1cYm94NTIKXHByQG91dHB1dD1c +dG9rczE4CikpIChDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0 +ZXgvbGF0ZXgvYW1zbWF0aFxhbXNtYXRoLnN0eQpQYWNrYWdlOiBhbXNtYXRoIDIwMjEvMDQvMjAg +djIuMTdqIEFNUyBtYXRoIGZlYXR1cmVzClxAbWF0aG1hcmdpbj1cc2tpcDY0CkZvciBhZGRpdGlv +bmFsIGluZm9ybWF0aW9uIG9uIGFtc21hdGgsIHVzZSB0aGUgYD8nIG9wdGlvbi4KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFt +c3RleHQuc3R5ClBhY2thZ2U6IGFtc3RleHQgMjAwMC8wNi8yOSB2Mi4wMSBBTVMgdGV4dAoKKEM6 +XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNt +YXRoXGFtc2dlbi5zdHkKRmlsZTogYW1zZ2VuLnN0eSAxOTk5LzExLzMwIHYyLjAgZ2VuZXJpYyBm +dW5jdGlvbnMKXEBlbXB0eXRva3M9XHRva3MxOQpcZXhAPVxkaW1lbjE0MAopKQooQzpcVXNlcnNc +am9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1z +YnN5LnN0eQpQYWNrYWdlOiBhbXNic3kgMTk5OS8xMS8yOSB2MS4yZCBCb2xkIFN5bWJvbHMKXHBt +YnJhaXNlQD1cZGltZW4xNDEKKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFt +c1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zb3BuLnN0eQpQYWNrYWdlOiBhbXNvcG4gMjAx +Ni8wMy8wOCB2Mi4wMiBvcGVyYXRvciBuYW1lcwopClxpbmZAYmFkPVxjb3VudDE5NgpMYVRlWCBJ +bmZvOiBSZWRlZmluaW5nIFxmcmFjIG9uIGlucHV0IGxpbmUgMjM0LgpcdXByb290QD1cY291bnQx +OTcKXGxlZnRyb290QD1cY291bnQxOTgKTGFUZVggSW5mbzogUmVkZWZpbmluZyBcb3ZlcmxpbmUg +b24gaW5wdXQgbGluZSAzOTkuClxjbGFzc251bUA9XGNvdW50MTk5ClxET1RTQ0FTRUA9XGNvdW50 +MjY2CkxhVGVYIEluZm86IFJlZGVmaW5pbmcgXGxkb3RzIG9uIGlucHV0IGxpbmUgNDk2LgpMYVRl +WCBJbmZvOiBSZWRlZmluaW5nIFxkb3RzIG9uIGlucHV0IGxpbmUgNDk5LgpMYVRlWCBJbmZvOiBS +ZWRlZmluaW5nIFxjZG90cyBvbiBpbnB1dCBsaW5lIDYyMC4KXE1hdGhzdHJ1dGJveEA9XGJveDUz +ClxzdHJ1dGJveEA9XGJveDU0ClxiaWdAc2l6ZT1cZGltZW4xNDIKTGFUZVggRm9udCBJbmZvOiAg +ICBSZWRlY2xhcmluZyBmb250IGVuY29kaW5nIE9NTCBvbiBpbnB1dCBsaW5lIDc0My4KTGFUZVgg +Rm9udCBJbmZvOiAgICBSZWRlY2xhcmluZyBmb250IGVuY29kaW5nIE9NUyBvbiBpbnB1dCBsaW5l +IDc0NC4KXG1hY2NAZGVwdGg9XGNvdW50MjY3ClxjQE1heE1hdHJpeENvbHM9XGNvdW50MjY4Clxk +b3Rzc3BhY2VAPVxtdXNraXAxNgpcY0BwYXJlbnRlcXVhdGlvbj1cY291bnQyNjkKXGRzcGJya0Bs +dmw9XGNvdW50MjcwClx0YWdAaGVscD1cdG9rczIwClxyb3dAPVxjb3VudDI3MQpcY29sdW1uQD1c +Y291bnQyNzIKXG1heGZpZWxkc0A9XGNvdW50MjczClxhbmRoZWxwQD1cdG9rczIxClxlcW5zaGlm +dEA9XGRpbWVuMTQzClxhbGlnbnNlcEA9XGRpbWVuMTQ0Clx0YWdzaGlmdEA9XGRpbWVuMTQ1Clx0 +YWd3aWR0aEA9XGRpbWVuMTQ2Clx0b3R3aWR0aEA9XGRpbWVuMTQ3ClxsaW5laHRAPVxkaW1lbjE0 +OApcQGVudmJvZHk9XHRva3MyMgpcbXVsdGxpbmVnYXA9XHNraXA2NQpcbXVsdGxpbmV0YWdnYXA9 +XHNraXA2NgpcbWF0aGRpc3BsYXlAc3RhY2s9XHRva3MyMwpMYVRlWCBJbmZvOiBSZWRlZmluaW5n +IFxbIG9uIGlucHV0IGxpbmUgMjkyMy4KTGFUZVggSW5mbzogUmVkZWZpbmluZyBcXSBvbiBpbnB1 +dCBsaW5lIDI5MjQuCikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9hbXNmb250c1xhbXNzeW1iLnN0eQpQYWNrYWdlOiBhbXNzeW1iIDIwMTMv +MDEvMTQgdjMuMDEgQU1TIGZvbnQgc3ltYm9scwoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9j +YWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1xhbXNmb250cy5zdHkKUGFja2Fn +ZTogYW1zZm9udHMgMjAxMy8wMS8xNCB2My4wMSBCYXNpYyBBTVNGb250cyBzdXBwb3J0ClxzeW1B +TVNhPVxtYXRoZ3JvdXA0ClxzeW1BTVNiPVxtYXRoZ3JvdXA1CkxhVGVYIEZvbnQgSW5mbzogICAg +UmVkZWNsYXJpbmcgbWF0aCBzeW1ib2wgXGhiYXIgb24gaW5wdXQgbGluZSA5OC4KTGFUZVggRm9u +dCBJbmZvOiAgICBPdmVyd3JpdGluZyBtYXRoIGFscGhhYmV0IGBcbWF0aGZyYWsnIGluIHZlcnNp +b24gYGJvbGQnCihGb250KSAgICAgICAgICAgICAgICAgIFUvZXVmL20vbiAtLT4gVS9ldWYvYi9u +IG9uIGlucHV0IGxpbmUgMTA2LgopKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9n +cmFtc1xNaUtUZVhcdGV4L2xhdGV4L2wzYmFja2VuZFxsM2JhY2tlbmQtcGRmCnRleC5kZWYKRmls +ZTogbDNiYWNrZW5kLXBkZnRleC5kZWYgMjAyMS0wOC0wNCBMMyBiYWNrZW5kIHN1cHBvcnQ6IFBE +RiBvdXRwdXQgKHBkZlRlWCkKXGxfX2NvbG9yX2JhY2tlbmRfc3RhY2tfaW50PVxjb3VudDI3NApc +bF9fcGRmX2ludGVybmFsX2JveD1cYm94NTUKKQpObyBmaWxlIGlucHV0LmF1eC4KXG9wZW5vdXQx +ID0gYGlucHV0LmF1eCcuCgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRlZmF1bHRzIGZv +ciBPTUwvY21tL20vaXQgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIC4uLiBv +a2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2luZyBkZWZhdWx0 +cyBmb3IgT01TL2Ntc3kvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAu +Li4gb2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVm +YXVsdHMgZm9yIE9UMS9jbXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAg +ICAuLi4gb2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcg +ZGVmYXVsdHMgZm9yIFQxL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86 +ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2lu +ZyBkZWZhdWx0cyBmb3IgVFMxL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IElu +Zm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVj +a2luZyBkZWZhdWx0cyBmb3IgT01YL2NtZXgvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9u +dCBJbmZvOiAgICAuLi4gb2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAg +Q2hlY2tpbmcgZGVmYXVsdHMgZm9yIFUvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZv +bnQgSW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpQYWNrYWdlIHNjcmJhc2UgSW5m +bzogYWN0aXZhdGluZyBlbmdsaXNoIFxjb250ZW50c25hbWUgb24gaW5wdXQgbGluZSA0LgpQYWNr +YWdlIHNjcmJhc2UgSW5mbzogYWN0aXZhdGluZyBlbmdsaXNoIFxsaXN0ZmlndXJlbmFtZSBvbiBp +bnB1dCBsaW5lIDQuClBhY2thZ2Ugc2NyYmFzZSBJbmZvOiBhY3RpdmF0aW5nIGVuZ2xpc2ggXGxp +c3R0YWJsZW5hbWUgb24gaW5wdXQgbGluZSA0LgpQYWNrYWdlIHR5cGVhcmVhIEluZm86IHBhY2th +Z2UgYHByZXZpZXcnIHdpdGggb3B0aW9uIGB0aWdodHBhZ2UnIGRldGVjdGVkLgoodHlwZWFyZWEp +ICAgICAgICAgICAgIGluaXRpYWwgcGFnZSBzaXplIHNwZWNpYWwgZGVhY3RpdmF0ZWQgb24gaW5w +dXQgbGluZSA0LgpQcmV2aWV3OiBGb250c2l6ZSAxNXB0ClByZXZpZXc6IFBERm91dHB1dCAxCkxh +VGVYIEZvbnQgSW5mbzogICAgQ2FsY3VsYXRpbmcgbWF0aCBzaXplcyBmb3Igc2l6ZSA8MTU+IG9u +IGlucHV0IGxpbmUgNS4KCkxhVGVYIEZvbnQgV2FybmluZzogRm9udCBzaGFwZSBgT1QxL2Ntci9t +L24nIGluIHNpemUgPDEwLjQ5OTk1PiBub3QgYXZhaWxhYmxlCihGb250KSAgICAgICAgICAgICAg +c2l6ZSA8MTAuOTU+IHN1YnN0aXR1dGVkIG9uIGlucHV0IGxpbmUgNS4KCgpMYVRlWCBGb250IFdh +cm5pbmc6IEZvbnQgc2hhcGUgYE9UMS9jbXIvbS9uJyBpbiBzaXplIDw3LjU+IG5vdCBhdmFpbGFi +bGUKKEZvbnQpICAgICAgICAgICAgICBzaXplIDw3PiBzdWJzdGl0dXRlZCBvbiBpbnB1dCBsaW5l +IDUuCgoKTGFUZVggRm9udCBXYXJuaW5nOiBGb250IHNoYXBlIGBPTUwvY21tL20vaXQnIGluIHNp +emUgPDE1PiBub3QgYXZhaWxhYmxlCihGb250KSAgICAgICAgICAgICAgc2l6ZSA8MTQuND4gc3Vi +c3RpdHV0ZWQgb24gaW5wdXQgbGluZSA1LgoKCkxhVGVYIEZvbnQgV2FybmluZzogRm9udCBzaGFw +ZSBgT01ML2NtbS9tL2l0JyBpbiBzaXplIDwxMC40OTk5NT4gbm90IGF2YWlsYWJsZQooRm9udCkg +ICAgICAgICAgICAgIHNpemUgPDEwLjk1PiBzdWJzdGl0dXRlZCBvbiBpbnB1dCBsaW5lIDUuCgoK +TGFUZVggRm9udCBXYXJuaW5nOiBGb250IHNoYXBlIGBPTUwvY21tL20vaXQnIGluIHNpemUgPDcu +NT4gbm90IGF2YWlsYWJsZQooRm9udCkgICAgICAgICAgICAgIHNpemUgPDc+IHN1YnN0aXR1dGVk +IG9uIGlucHV0IGxpbmUgNS4KCgpMYVRlWCBGb250IFdhcm5pbmc6IEZvbnQgc2hhcGUgYE9NUy9j +bXN5L20vbicgaW4gc2l6ZSA8MTU+IG5vdCBhdmFpbGFibGUKKEZvbnQpICAgICAgICAgICAgICBz +aXplIDwxNC40PiBzdWJzdGl0dXRlZCBvbiBpbnB1dCBsaW5lIDUuCgoKTGFUZVggRm9udCBXYXJu +aW5nOiBGb250IHNoYXBlIGBPTVMvY21zeS9tL24nIGluIHNpemUgPDEwLjQ5OTk1PiBub3QgYXZh +aWxhYmxlCihGb250KSAgICAgICAgICAgICAgc2l6ZSA8MTAuOTU+IHN1YnN0aXR1dGVkIG9uIGlu +cHV0IGxpbmUgNS4KCgpMYVRlWCBGb250IFdhcm5pbmc6IEZvbnQgc2hhcGUgYE9NUy9jbXN5L20v +bicgaW4gc2l6ZSA8Ny41PiBub3QgYXZhaWxhYmxlCihGb250KSAgICAgICAgICAgICAgc2l6ZSA8 +Nz4gc3Vic3RpdHV0ZWQgb24gaW5wdXQgbGluZSA1LgoKTGFUZVggRm9udCBJbmZvOiAgICBUcnlp +bmcgdG8gbG9hZCBmb250IGluZm9ybWF0aW9uIGZvciBVK21zYSBvbiBpbnB1dCBsaW5lIDUuCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1z +Zm9udHNcdW1zYS5mZApGaWxlOiB1bXNhLmZkIDIwMTMvMDEvMTQgdjMuMDEgQU1TIHN5bWJvbHMg +QQopCkxhVGVYIEZvbnQgSW5mbzogICAgVHJ5aW5nIHRvIGxvYWQgZm9udCBpbmZvcm1hdGlvbiBm +b3IgVSttc2Igb24gaW5wdXQgbGluZSA1LgoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxc +UHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1x1bXNiLmZkCkZpbGU6IHVtc2IuZmQg +MjAxMy8wMS8xNCB2My4wMSBBTVMgc3ltYm9scyBCCikKUHJldmlldzogVGlnaHRwYWdlIDAgMCAw +IDAKWzF7QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9NaUtUZVgvcGRmdGV4L2NvbmZpZy9w +ZGZ0ZXgubWFwfV0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXAzdm91 +YjVqdFxpbnB1dC5hdXgpCgpMYVRlWCBGb250IFdhcm5pbmc6IFNpemUgc3Vic3RpdHV0aW9ucyB3 +aXRoIGRpZmZlcmVuY2VzCihGb250KSAgICAgICAgICAgICAgdXAgdG8gMC42cHQgaGF2ZSBvY2N1 +cnJlZC4KCiApIApIZXJlIGlzIGhvdyBtdWNoIG9mIFRlWCdzIG1lbW9yeSB5b3UgdXNlZDoKIDUx +NTcgc3RyaW5ncyBvdXQgb2YgNDc4ODY4CiAxMDMwNjUgc3RyaW5nIGNoYXJhY3RlcnMgb3V0IG9m +IDI4NDg4MDkKIDUyOTExNSB3b3JkcyBvZiBtZW1vcnkgb3V0IG9mIDMwMDAwMDAKIDIzMDU5IG11 +bHRpbGV0dGVyIGNvbnRyb2wgc2VxdWVuY2VzIG91dCBvZiAxNTAwMCs2MDAwMDAKIDQwNzE2NSB3 +b3JkcyBvZiBmb250IGluZm8gZm9yIDQyIGZvbnRzLCBvdXQgb2YgODAwMDAwMCBmb3IgOTAwMAog +MTE0MSBoeXBoZW5hdGlvbiBleGNlcHRpb25zIG91dCBvZiA4MTkxCiAxMjJpLDRuLDEyOHAsMTA3 +MjdiLDI4MHMgc3RhY2sgcG9zaXRpb25zIG91dCBvZiA1MDAwaSw1MDBuLDEwMDAwcCwyMDAwMDBi +LDgwMDAwcwo8QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9u +dHMvdHlwZTEvcHVibGljL2Ftc2ZvbnRzL2NtLwpjbWV4MTAucGZiPjxDOi9Vc2Vycy9qb25hdC9B +cHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zCmZvbnRz +L2NtL2NtbWkxMC5wZmI+PEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlL +VGVYL2ZvbnRzL3R5cGUxL3AKdWJsaWMvYW1zZm9udHMvY20vY21taTEyLnBmYj48QzovVXNlcnMv +am9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9udApzL3R5cGUxL3B1YmxpYy9h +bXNmb250cy9jbS9jbXIxMC5wZmI+PEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9jYWwvUHJvZ3Jh +bXMvTWlLClRlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21yMTIucGZiPjxDOi9V +c2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2cKcmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVi +bGljL2Ftc2ZvbnRzL2NtL2Ntc3kxMC5wZmI+Ck91dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXAzdm91YjVqdFxpbnB1dC5wZGYgKDEKIHBhZ2Us +IDU0ODg4IGJ5dGVzKS4KUERGIHN0YXRpc3RpY3M6CiAzNiBQREYgb2JqZWN0cyBvdXQgb2YgMTAw +MCAobWF4LiA4Mzg4NjA3KQogMCBuYW1lZCBkZXN0aW5hdGlvbnMgb3V0IG9mIDEwMDAgKG1heC4g +NTAwMDAwKQogMSB3b3JkcyBvZiBleHRyYSBtZW1vcnkgZm9yIFBERiBvdXRwdXQgb3V0IG9mIDEw +MDAwIChtYXguIDEwMDAwMDAwKQoK + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/pdflatex/93c25fa37a5c8216644b4392a3d3654e.msg b/share/extensions/tests/data/cmd/pdflatex/93c25fa37a5c8216644b4392a3d3654e.msg new file mode 100644 index 0000000..a5277d4 --- /dev/null +++ b/share/extensions/tests/data/cmd/pdflatex/93c25fa37a5c8216644b4392a3d3654e.msg @@ -0,0 +1,673 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: pdflatex +Arguments: -halt-on-error -output-directory=. input.tex + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KQ0KZW50ZXJpbmcgZXh0ZW5kZWQgbW9kZQ0KKEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9j +YWwvVGVtcC9pbmt0bXBqMHY3aXFrOS9pbnB1dC50ZXgNCkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDENCkwzIHByb2dyYW1taW5nIGxheWVyIDwyMDIxLTA3LTEyPg0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25l +XHN0YW5kYWxvbmUuYw0KbHMNCkRvY3VtZW50IENsYXNzOiBzdGFuZGFsb25lIDIwMTgvMDMvMjYg +djEuM2EgQ2xhc3MgdG8gY29tcGlsZSBUZVggc3ViLWZpbGVzIHN0YW4NCmRhbG9uZQ0KKEM6XFVz +ZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xz +aGVsbGVzYy5zdHkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZsdWF0ZXguc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZ0ZXguc3R5KSkNCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtl +eXZhbFx4a2V5dmFsLnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxceGtleXZhbC50ZXgNCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxz +LnRleA0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9n +ZW5lcmljL3hrZXl2YWxca2V5dmFsLnRleCkpKQ0KKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYw0K +ZmcpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xh +dGV4L2tvbWEtc2NyaXB0XHNjcnJlcHJ0LmNsDQpzDQpEb2N1bWVudCBDbGFzczogc2NycmVwcnQg +MjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBkb2N1bWVudCBjbGFzcyAocmVwb3J0KQ0KDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tv +bWEtc2NyaXB0XHNjcmtiYXNlLnN0DQp5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmJhc2Uuc3R5DQoNCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1z +Y3JpcHRcc2NybGZpbGUuc3QNCnkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dy +YW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1zY3JpcHRcc2NybGZpbGUtaG8NCm9rLTMuMzQuc3R5 +DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5DQopKSkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFx0b2NiYXNpYy5zdA0K +eSkgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRl +eC9leHRzaXplc1xzaXplMjAuY2xvKQ0KDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHR5cGVhcmVhLnN0DQp5DQoNClBh +Y2thZ2UgdHlwZWFyZWEgV2FybmluZzogRElWIGZvciAyMC4wcHQgYW5kIHVzZWQgcGFwZXJzaXpl +DQoodHlwZWFyZWEpICAgICAgICAgICAgICAgIG5vdCBkZWZpbmVkIQ0KKHR5cGVhcmVhKSAgICAg +ICAgICAgICAgICBVc2luZyBESVY9Y2FsYy4NCg0KRElWIGNhbGN1bGF0aW9uIGZvciB0eXBlYXJl +YSB3aXRoIGdvb2QgbGluZXdpZHRoLg0KKSkgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxc +UHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9wcmV2aWV3XHByZXZpZXcuc3R5DQooQzpcVXNlcnNc +am9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2x1YXRleDg1XGx1 +YXRleDg1LnN0eSkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1Rl +WFx0ZXgvbGF0ZXgvcHJldmlld1xwcnRpZ2h0cGFnZS5kZWYNCikpKSAoQzpcVXNlcnNcam9uYXRc +QXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zbWF0aC5z +dHkNCkZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIG9uIGFtc21hdGgsIHVzZSB0aGUgYD8nIG9w +dGlvbi4NCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgv +bGF0ZXgvYW1zbWF0aFxhbXN0ZXh0LnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxc +UHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc2dlbi5zdHkpKQ0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFt +c2JzeS5zdHkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhc +dGV4L2xhdGV4L2Ftc21hdGhcYW1zb3BuLnN0eSkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxM +b2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc3N5bWIuc3R5DQooQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2Zv +bnRzXGFtc2ZvbnRzLnN0eSkpDQoNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dy +YW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbDNiYWNrZW5kXGwzYmFja2VuZC1wZGYNCnRleC5kZWYpDQpO +byBmaWxlIGlucHV0LmF1eC4NClByZXZpZXc6IEZvbnRzaXplIDIwLjc0cHQNClByZXZpZXc6IFBE +Rm91dHB1dCAxDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhc +dGV4L2xhdGV4L2Ftc2ZvbnRzXHVtc2EuZmQpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2Nh +bFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXHVtc2IuZmQpDQpQcmV2aWV3OiBU +aWdodHBhZ2UgMCAwIDAgMA0KWzF7QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9NaUtUZVgv +cGRmdGV4L2NvbmZpZy9wZGZ0ZXgubWFwfV0NCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFRlbXBcaW5rdG1wajB2N2lxazlcaW5wdXQuYXV4KSApPEM6L1VzZXJzL2pvbmF0L0ENCnBwRGF0 +YS9Mb2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ftc2ZvbnRzL2NtL2Nt +cjEyLnBmYj48QzovVXNlcnMNCi9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9m +b250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21zeTEwLnBmYj4NCk91dHB1dCB3cml0dGVu +IG9uIEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXBqMHY3aXFrOVxpbnB1 +dC5wZGYgKDENCiBwYWdlLCAxODQ3OSBieXRlcykuDQpUcmFuc2NyaXB0IHdyaXR0ZW4gb24gQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlua3RtcGowdjdpcWs5XGlucHV0LmxvDQpn +Lg0K + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: inktmpj0v7iqk9 + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.aux" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.aux + +XHJlbGF4IApccHJvdmlkZWNvbW1hbmQqXG5ld0B0cG9AbGFiZWxbMl17fQpcZ2RlZiBcQGFic3Bh +Z2VAbGFzdHsxfQo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.log" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.log + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KSAocHJlbG9hZGVkIGZvcm1hdD1wZGZsYXRleCAyMDIxLjguMjMpICA1IE1BUiAyMDIyIDIw +OjMxCmVudGVyaW5nIGV4dGVuZGVkIG1vZGUKKipDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1RlbXAvaW5rdG1wajB2N2lxazkvaW5wdXQudGV4CihDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xv +Y2FsL1RlbXAvaW5rdG1wajB2N2lxazkvaW5wdXQudGV4CkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDEKTDMgcHJvZ3JhbW1pbmcgbGF5ZXIgPDIwMjEtMDctMTI+CihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvc3RhbmRhbG9uZVxz +dGFuZGFsb25lLmMKbHMKRG9jdW1lbnQgQ2xhc3M6IHN0YW5kYWxvbmUgMjAxOC8wMy8yNiB2MS4z +YSBDbGFzcyB0byBjb21waWxlIFRlWCBzdWItZmlsZXMgc3RhbgpkYWxvbmUKKEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xzaGVsbGVz +Yy5zdHkKUGFja2FnZTogc2hlbGxlc2MgMjAxOS8xMS8wOCB2MS4wYyB1bmlmaWVkIHNoZWxsIGVz +Y2FwZSBpbnRlcmZhY2UgZm9yIExhVGVYClBhY2thZ2Ugc2hlbGxlc2MgSW5mbzogUmVzdHJpY3Rl +ZCBzaGVsbCBlc2NhcGUgZW5hYmxlZCBvbiBpbnB1dCBsaW5lIDc3LgopCihDOlxVc2Vyc1xqb25h +dFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZmx1YXRl +eC5zdHkKUGFja2FnZTogaWZsdWF0ZXggMjAxOS8xMC8yNSB2MS41IGlmbHVhdGV4IGxlZ2FjeSBw +YWNrYWdlLiBVc2UgaWZ0ZXggaW5zdGVhZC4KCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZnRleC5zdHkKUGFja2FnZTogaWZ0 +ZXggMjAyMC8wMy8wNiB2MS4wZCBUZVggZW5naW5lIHRlc3RzCikpCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtleXZhbFx4a2V5dmFsLnN0 +eQpQYWNrYWdlOiB4a2V5dmFsIDIwMjAvMTEvMjAgdjIuOCBwYWNrYWdlIG9wdGlvbiBwcm9jZXNz +aW5nIChIQSkKCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0 +ZXgvZ2VuZXJpYy94a2V5dmFsXHhrZXl2YWwudGV4CihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExv +Y2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxzLnRleApcWEtW +QHRva3M9XHRva3MxNgpcWEtWQHRlbXBhQHRva3M9XHRva3MxNwoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxca2V5dmFsLnRl +eCkpClxYS1ZAZGVwdGg9XGNvdW50MTgyCkZpbGU6IHhrZXl2YWwudGV4IDIwMTQvMTIvMDMgdjIu +N2Ega2V5PXZhbHVlIHBhcnNlciAoSEEpCikpClxzYUBpbnRlcm5hbD1cY291bnQxODMKXGNAc2Fw +YWdlPVxjb3VudDE4NAoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYwpmZwpGaWxlOiBzdGFuZGFsb25l +LmNmZyAyMDE4LzAzLzI2IHYxLjNhIERlZmF1bHQgY29uZmlndXJhdGlvbiBmaWxlIGZvciAnc3Rh +bmRhbG9uCmUnIGNsYXNzCikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JyZXBydC5jbApzCkRvY3VtZW50IENsYXNz +OiBzY3JyZXBydCAyMDIxLzExLzEzIHYzLjM1IEtPTUEtU2NyaXB0IGRvY3VtZW50IGNsYXNzIChy +ZXBvcnQpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmtiYXNlLnN0CnkKUGFja2FnZTogc2Nya2Jhc2UgMjAyMS8x +MS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChLT01BLVNjcmlwdC1kZXBlbmRlbnQgYgph +c2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JiYXNlLnN0eQpQYWNrYWdlOiBz +Y3JiYXNlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFja2FnZSAoS09NQS1TY3JpcHQt +aW5kZXBlbmRlbnQgCmJhc2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmls +ZS5zdAp5ClBhY2thZ2U6IHNjcmxmaWxlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFj +a2FnZSAoZmlsZSBsb2FkIGhvb2tzKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmlsZS1obwpvay0zLjM0LnN0 +eQpQYWNrYWdlOiBzY3JsZmlsZS1ob29rLTMuMzQgMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlw +dCBwYWNrYWdlICh1c2luZyBMYVRlWCBoCm9va3MpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxM +b2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5ClBh +Y2thZ2U6IHNjcmxvZ28gMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChsb2dv +KQopKSkKQXBwbHlpbmc6IFsyMDIxLzA1LzAxXSBVc2FnZSBvZiByYXcgb3IgY2xhc3NpYyBvcHRp +b24gbGlzdCBvbiBpbnB1dCBsaW5lIDI1Mi4KQWxyZWFkeSBhcHBsaWVkOiBbMDAwMC8wMC8wMF0g +VXNhZ2Ugb2YgcmF3IG9yIGNsYXNzaWMgb3B0aW9uIGxpc3Qgb24gaW5wdXQgbGluZQogMzY4Lgop +KQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHRvY2Jhc2ljLnN0CnkKUGFja2FnZTogdG9jYmFzaWMgMjAyMS8xMS8xMyB2 +My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChoYW5kbGluZyB0b2MtZmlsZXMpClxzY3JAZHRlQHRv +Y2xpbmVAbnVtYmVyd2lkdGg9XHNraXA0Nwpcc2NyQGR0ZUB0b2NsaW5lQG51bWJveD1cYm94NTAK +KQpQYWNrYWdlIHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3IgYHRvYycgb21pdHRl +ZAoodG9jYmFzaWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBcYmJsQHNldEBsYW5n +dWFnZSBvbiBpbnB1dCBsaW5lIDEzNy4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogRmlsZSBgc2l6ZTIw +LmNsbycgdXNlZCB0byBzZXR1cCBmb250IHNpemVzIG9uIGlucHV0IGxpbmUgMgo0ODcuCiAoQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2V4dHNp +emVzXHNpemUyMC5jbG8KRmlsZTogc2l6ZTIwLmNsbyAxOTk5LzExLzExIE5PTi1TdGFuZGFyZCBM +YVRlWCBmaWxlIChzaXplIG9wdGlvbikKKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHR5cGVhcmVhLnN0CnkKUGFja2Fn +ZTogdHlwZWFyZWEgMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlICh0eXBlIGFy +ZWEpClx0YUBiY29yPVxza2lwNDgKXHRhQGRpdj1cY291bnQxODUKXHRhQGhibGs9XHNraXA0OQpc +dGFAdmJsaz1cc2tpcDUwClx0YUB0ZW1wPVxza2lwNTEKXGZvb3RoZWlnaHQ9XHNraXA1MgoKClBh +Y2thZ2UgdHlwZWFyZWEgV2FybmluZzogRElWIGZvciAyMC4wcHQgYW5kIHVzZWQgcGFwZXJzaXpl +Cih0eXBlYXJlYSkgICAgICAgICAgICAgICAgbm90IGRlZmluZWQhCih0eXBlYXJlYSkgICAgICAg +ICAgICAgICAgVXNpbmcgRElWPWNhbGMuCgpESVYgY2FsY3VsYXRpb24gZm9yIHR5cGVhcmVhIHdp +dGggZ29vZCBsaW5ld2lkdGguClBhY2thZ2UgdHlwZWFyZWEgSW5mbzogTWF5YmUgbm8gb3B0aW1h +bCB0eXBlIGFyZWEgc2V0dGluZ3MhCih0eXBlYXJlYSkgICAgICAgICAgICAgVGhlIGRldGVjdGVk +IGxpbmUgd2lkdGggaXMgYWJvdXQgMjclCih0eXBlYXJlYSkgICAgICAgICAgICAgc21hbGxlciB0 +aGFuIHRoZSBoZXVyaXN0aWNhbGx5IGVzdGltYXRlZCBtYXhpbXVtCih0eXBlYXJlYSkgICAgICAg +ICAgICAgbGltaXQgb2YgdHlwb2dyYXBoaWNhbCBnb29kIGxpbmUgd2lkdGguCih0eXBlYXJlYSkg +ICAgICAgICAgICAgWW91IGNvdWxkIGUuZy4gaW5jcmVhc2UgRElWLCBkZWNyZWFzZSBmb250c2l6 +ZQoodHlwZWFyZWEpICAgICAgICAgICAgIG9yIGNoYW5nZSB0aGUgcGFwZXJzaXplLgpQYWNrYWdl +IHR5cGVhcmVhIEluZm86IFRoZXNlIGFyZSB0aGUgdmFsdWVzIGRlc2NyaWJpbmcgdGhlIGxheW91 +dDoKKHR5cGVhcmVhKSAgICAgICAgICAgICBESVYgID0gMTIKKHR5cGVhcmVhKSAgICAgICAgICAg +ICBCQ09SID0gMC4wcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICBccGFwZXJ3aWR0aCAgICAgID0g +NTk3LjUwNzkzcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXHRleHR3aWR0aCAgICAgID0gNDQ4 +LjEzMDk1cHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgRElWIGRlcGFydHVyZSAgID0gMjclCih0 +eXBlYXJlYSkgICAgICAgICAgICAgIFxldmVuc2lkZW1hcmdpbiA9IDIuNDE4NXB0Cih0eXBlYXJl +YSkgICAgICAgICAgICAgIFxvZGRzaWRlbWFyZ2luICA9IDIuNDE4NXB0Cih0eXBlYXJlYSkgICAg +ICAgICAgICAgXHBhcGVyaGVpZ2h0ICAgICA9IDg0NS4wNDY5NHB0Cih0eXBlYXJlYSkgICAgICAg +ICAgICAgIFx0ZXh0aGVpZ2h0ICAgICA9IDY0NS4wcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAg +XHRvcG1hcmdpbiAgICAgID0gLTcwLjU5OTQxcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXGhl +YWRoZWlnaHQgICAgID0gMzEuMjVwdAoodHlwZWFyZWEpICAgICAgICAgICAgICBcaGVhZHNlcCAg +ICAgICAgPSAzNy41cHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXHRvcHNraXAgICAgICAgID0g +MjAuMHB0Cih0eXBlYXJlYSkgICAgICAgICAgICAgIFxmb290c2tpcCAgICAgICA9IDg3LjVwdAoo +dHlwZWFyZWEpICAgICAgICAgICAgICBcYmFzZWxpbmVza2lwICAgPSAyNS4wcHQKKHR5cGVhcmVh +KSAgICAgICAgICAgICAgb24gaW5wdXQgbGluZSAxNzQzLgopClxjQHBhcnQ9XGNvdW50MTg2Clxj +QGNoYXB0ZXI9XGNvdW50MTg3ClxjQHNlY3Rpb249XGNvdW50MTg4ClxjQHN1YnNlY3Rpb249XGNv +dW50MTg5ClxjQHN1YnN1YnNlY3Rpb249XGNvdW50MTkwClxjQHBhcmFncmFwaD1cY291bnQxOTEK +XGNAc3VicGFyYWdyYXBoPVxjb3VudDE5Mgpcc2NyQGR0ZUBjaGFwdGVyQG1heG51bXdpZHRoPVxz +a2lwNTMKQ2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBh +ZnRlcmluZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXGNoYXB0ZXIgb24g +aW5wdXQgbGluZSA1NzE3Lgpcc2NyQGR0ZUBzZWN0aW9uQG1heG51bXdpZHRoPVxza2lwNTQKQ2xh +c3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBydW5pbj1ieXNp +Z24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHNlY3Rpb24gb24gaW5wdXQgbGluZSA1NzI4 +LgpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYGFmdGVy +aW5kZW50PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc2VjdGlvbiBvbiBpbnB1 +dCBsaW5lIDU3MjguClxzY3JAZHRlQHBhcnRAbWF4bnVtd2lkdGg9XHNraXA1NQpDbGFzcyBzY3Jy +ZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYGFmdGVyaW5kZW50PXRydWUn +CihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHBhcnQgb24gaW5wdXQgbGluZSA1NzM3Lgpcc2Ny +QGR0ZUBzdWJzZWN0aW9uQG1heG51bXdpZHRoPVxza2lwNTYKQ2xhc3Mgc2NycmVwcnQgSW5mbzog +dXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBydW5pbj1ieXNpZ24nCihzY3JyZXBydCkgICAg +ICAgICAgIGZvciBgXHN1YnNlY3Rpb24gb24gaW5wdXQgbGluZSA1NzQ3LgpDbGFzcyBzY3JyZXBy +dCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYGFmdGVyaW5kZW50PWJ5c2lnbicK +KHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc3Vic2VjdGlvbiBvbiBpbnB1dCBsaW5lIDU3NDcu +ClxzY3JAZHRlQHN1YnN1YnNlY3Rpb25AbWF4bnVtd2lkdGg9XHNraXA1NwpDbGFzcyBzY3JyZXBy +dCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmluPWJ5c2lnbicKKHNjcnJl +cHJ0KSAgICAgICAgICAgZm9yIGBcc3Vic3Vic2VjdGlvbiBvbiBpbnB1dCBsaW5lIDU3NTcuCkNs +YXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0ZXJpbmRl +bnQ9YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJzdWJzZWN0aW9uIG9uIGlu +cHV0IGxpbmUgNTc1Ny4KXHNjckBkdGVAcGFyYWdyYXBoQG1heG51bXdpZHRoPVxza2lwNTgKQ2xh +c3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBydW5pbj1ieXNp +Z24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHBhcmFncmFwaCBvbiBpbnB1dCBsaW5lIDU3 +NjguCkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0 +ZXJpbmRlbnQ9YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxwYXJhZ3JhcGggb24g +aW5wdXQgbGluZSA1NzY4Lgpcc2NyQGR0ZUBzdWJwYXJhZ3JhcGhAbWF4bnVtd2lkdGg9XHNraXA1 +OQpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmlu +PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc3VicGFyYWdyYXBoIG9uIGlucHV0 +IGxpbmUgNTc3OC4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZh +dWx0IGBhZnRlcmluZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHN1YnBh +cmFncmFwaCBvbiBpbnB1dCBsaW5lIDU3NzguClxhYm92ZWNhcHRpb25za2lwPVxza2lwNjAKXGJl +bG93Y2FwdGlvbnNraXA9XHNraXA2MQpcY0BwdGlAbmJAc2lkQGJAeD1cYm94NTEKUGFja2FnZSB0 +b2NiYXNpYyBJbmZvOiBiYWJlbCBleHRlbnNpb24gZm9yIGBsb2YnIG9taXR0ZWQKKHRvY2Jhc2lj +KSAgICAgICAgICAgICBiZWNhdXNlIG9mIG1pc3NpbmcgXGJibEBzZXRAbGFuZ3VhZ2Ugb24gaW5w +dXQgbGluZSA2OTU4LgoKXHNjckBkdGVAZmlndXJlQG1heG51bXdpZHRoPVxza2lwNjIKXGNAZmln +dXJlPVxjb3VudDE5MwpQYWNrYWdlIHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3Ig +YGxvdCcgb21pdHRlZAoodG9jYmFzaWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBc +YmJsQHNldEBsYW5ndWFnZSBvbiBpbnB1dCBsaW5lIDY5NzQuCgpcc2NyQGR0ZUB0YWJsZUBtYXhu +dW13aWR0aD1cc2tpcDYzClxjQHRhYmxlPVxjb3VudDE5NApDbGFzcyBzY3JyZXBydCBJbmZvOiBS +ZWRlZmluaW5nIGBcbnVtYmVybGluZScgb24gaW5wdXQgbGluZSA3MTQyLgpcYmliaW5kZW50PVxk +aW1lbjEzOAopIChDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0 +ZXgvbGF0ZXgvcHJldmlld1xwcmV2aWV3LnN0eQpQYWNrYWdlOiBwcmV2aWV3IDIwMTcvMDQvMjQg +MTMuMSAoQVVDVGVYL3ByZXZpZXctbGF0ZXgpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2Nh +bFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2x1YXRleDg1XGx1YXRleDg1LnN0eQpQYWNrYWdl +OiBsdWF0ZXg4NSAyMDE2LzA2LzE1IHYxLjQgcGRmdGV4IGFsaWFzZXMgZm9yIGx1YXRleAopCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvcHJl +dmlld1xwcnRpZ2h0cGFnZS5kZWYKXFByZXZpZXdCb3JkZXI9XGRpbWVuMTM5CikKXHByQHNuaXBw +ZXQ9XGNvdW50MTk1ClxwckBib3g9XGJveDUyClxwckBvdXRwdXQ9XHRva3MxOAopKSAoQzpcVXNl +cnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhc +YW1zbWF0aC5zdHkKUGFja2FnZTogYW1zbWF0aCAyMDIxLzA0LzIwIHYyLjE3aiBBTVMgbWF0aCBm +ZWF0dXJlcwpcQG1hdGhtYXJnaW49XHNraXA2NApGb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBv +biBhbXNtYXRoLCB1c2UgdGhlIGA/JyBvcHRpb24uCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExv +Y2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXN0ZXh0LnN0eQpQYWNrYWdl +OiBhbXN0ZXh0IDIwMDAvMDYvMjkgdjIuMDEgQU1TIHRleHQKCihDOlxVc2Vyc1xqb25hdFxBcHBE +YXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNnZW4uc3R5CkZp +bGU6IGFtc2dlbi5zdHkgMTk5OS8xMS8zMCB2Mi4wIGdlbmVyaWMgZnVuY3Rpb25zClxAZW1wdHl0 +b2tzPVx0b2tzMTkKXGV4QD1cZGltZW4xNDAKKSkKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9j +YWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc2JzeS5zdHkKUGFja2FnZTog +YW1zYnN5IDE5OTkvMTEvMjkgdjEuMmQgQm9sZCBTeW1ib2xzClxwbWJyYWlzZUA9XGRpbWVuMTQx +CikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRl +eC9hbXNtYXRoXGFtc29wbi5zdHkKUGFja2FnZTogYW1zb3BuIDIwMTYvMDMvMDggdjIuMDIgb3Bl +cmF0b3IgbmFtZXMKKQpcaW5mQGJhZD1cY291bnQxOTYKTGFUZVggSW5mbzogUmVkZWZpbmluZyBc +ZnJhYyBvbiBpbnB1dCBsaW5lIDIzNC4KXHVwcm9vdEA9XGNvdW50MTk3ClxsZWZ0cm9vdEA9XGNv +dW50MTk4CkxhVGVYIEluZm86IFJlZGVmaW5pbmcgXG92ZXJsaW5lIG9uIGlucHV0IGxpbmUgMzk5 +LgpcY2xhc3NudW1APVxjb3VudDE5OQpcRE9UU0NBU0VAPVxjb3VudDI2NgpMYVRlWCBJbmZvOiBS +ZWRlZmluaW5nIFxsZG90cyBvbiBpbnB1dCBsaW5lIDQ5Ni4KTGFUZVggSW5mbzogUmVkZWZpbmlu +ZyBcZG90cyBvbiBpbnB1dCBsaW5lIDQ5OS4KTGFUZVggSW5mbzogUmVkZWZpbmluZyBcY2RvdHMg +b24gaW5wdXQgbGluZSA2MjAuClxNYXRoc3RydXRib3hAPVxib3g1Mwpcc3RydXRib3hAPVxib3g1 +NApcYmlnQHNpemU9XGRpbWVuMTQyCkxhVGVYIEZvbnQgSW5mbzogICAgUmVkZWNsYXJpbmcgZm9u +dCBlbmNvZGluZyBPTUwgb24gaW5wdXQgbGluZSA3NDMuCkxhVGVYIEZvbnQgSW5mbzogICAgUmVk +ZWNsYXJpbmcgZm9udCBlbmNvZGluZyBPTVMgb24gaW5wdXQgbGluZSA3NDQuClxtYWNjQGRlcHRo +PVxjb3VudDI2NwpcY0BNYXhNYXRyaXhDb2xzPVxjb3VudDI2OApcZG90c3NwYWNlQD1cbXVza2lw +MTYKXGNAcGFyZW50ZXF1YXRpb249XGNvdW50MjY5Clxkc3BicmtAbHZsPVxjb3VudDI3MApcdGFn +QGhlbHA9XHRva3MyMApccm93QD1cY291bnQyNzEKXGNvbHVtbkA9XGNvdW50MjcyClxtYXhmaWVs +ZHNAPVxjb3VudDI3MwpcYW5kaGVscEA9XHRva3MyMQpcZXFuc2hpZnRAPVxkaW1lbjE0MwpcYWxp +Z25zZXBAPVxkaW1lbjE0NApcdGFnc2hpZnRAPVxkaW1lbjE0NQpcdGFnd2lkdGhAPVxkaW1lbjE0 +NgpcdG90d2lkdGhAPVxkaW1lbjE0NwpcbGluZWh0QD1cZGltZW4xNDgKXEBlbnZib2R5PVx0b2tz +MjIKXG11bHRsaW5lZ2FwPVxza2lwNjUKXG11bHRsaW5ldGFnZ2FwPVxza2lwNjYKXG1hdGhkaXNw +bGF5QHN0YWNrPVx0b2tzMjMKTGFUZVggSW5mbzogUmVkZWZpbmluZyBcWyBvbiBpbnB1dCBsaW5l +IDI5MjMuCkxhVGVYIEluZm86IFJlZGVmaW5pbmcgXF0gb24gaW5wdXQgbGluZSAyOTI0LgopCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1z +Zm9udHNcYW1zc3ltYi5zdHkKUGFja2FnZTogYW1zc3ltYiAyMDEzLzAxLzE0IHYzLjAxIEFNUyBm +b250IHN5bWJvbHMKCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1Rl +WFx0ZXgvbGF0ZXgvYW1zZm9udHNcYW1zZm9udHMuc3R5ClBhY2thZ2U6IGFtc2ZvbnRzIDIwMTMv +MDEvMTQgdjMuMDEgQmFzaWMgQU1TRm9udHMgc3VwcG9ydApcc3ltQU1TYT1cbWF0aGdyb3VwNApc +c3ltQU1TYj1cbWF0aGdyb3VwNQpMYVRlWCBGb250IEluZm86ICAgIFJlZGVjbGFyaW5nIG1hdGgg +c3ltYm9sIFxoYmFyIG9uIGlucHV0IGxpbmUgOTguCkxhVGVYIEZvbnQgSW5mbzogICAgT3Zlcndy +aXRpbmcgbWF0aCBhbHBoYWJldCBgXG1hdGhmcmFrJyBpbiB2ZXJzaW9uIGBib2xkJwooRm9udCkg +ICAgICAgICAgICAgICAgICBVL2V1Zi9tL24gLS0+IFUvZXVmL2IvbiBvbiBpbnB1dCBsaW5lIDEw +Ni4KKSkKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9s +YXRleC9sM2JhY2tlbmRcbDNiYWNrZW5kLXBkZgp0ZXguZGVmCkZpbGU6IGwzYmFja2VuZC1wZGZ0 +ZXguZGVmIDIwMjEtMDgtMDQgTDMgYmFja2VuZCBzdXBwb3J0OiBQREYgb3V0cHV0IChwZGZUZVgp +ClxsX19jb2xvcl9iYWNrZW5kX3N0YWNrX2ludD1cY291bnQyNzQKXGxfX3BkZl9pbnRlcm5hbF9i +b3g9XGJveDU1CikKTm8gZmlsZSBpbnB1dC5hdXguClxvcGVub3V0MSA9IGBpbnB1dC5hdXgnLgoK +TGFUZVggRm9udCBJbmZvOiAgICBDaGVja2luZyBkZWZhdWx0cyBmb3IgT01ML2NtbS9tL2l0IG9u +IGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBpbnB1dCBsaW5l +IDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVsdHMgZm9yIE9NUy9jbXN5L20v +biBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQg +bGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRlZmF1bHRzIGZvciBPVDEvY21y +L20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgLi4uIG9rYXkgb24gaW5w +dXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRlZmF1bHRzIGZvciBUMS9j +bXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBp +bnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVsdHMgZm9yIFRT +MS9jbXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBv +biBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVsdHMgZm9y +IE9NWC9jbWV4L20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgLi4uIG9r +YXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRlZmF1bHRz +IGZvciBVL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIC4uLiBv +a2F5IG9uIGlucHV0IGxpbmUgNC4KUGFja2FnZSBzY3JiYXNlIEluZm86IGFjdGl2YXRpbmcgZW5n +bGlzaCBcY29udGVudHNuYW1lIG9uIGlucHV0IGxpbmUgNC4KUGFja2FnZSBzY3JiYXNlIEluZm86 +IGFjdGl2YXRpbmcgZW5nbGlzaCBcbGlzdGZpZ3VyZW5hbWUgb24gaW5wdXQgbGluZSA0LgpQYWNr +YWdlIHNjcmJhc2UgSW5mbzogYWN0aXZhdGluZyBlbmdsaXNoIFxsaXN0dGFibGVuYW1lIG9uIGlu +cHV0IGxpbmUgNC4KUGFja2FnZSB0eXBlYXJlYSBJbmZvOiBwYWNrYWdlIGBwcmV2aWV3JyB3aXRo +IG9wdGlvbiBgdGlnaHRwYWdlJyBkZXRlY3RlZC4KKHR5cGVhcmVhKSAgICAgICAgICAgICBpbml0 +aWFsIHBhZ2Ugc2l6ZSBzcGVjaWFsIGRlYWN0aXZhdGVkIG9uIGlucHV0IGxpbmUgNC4KUHJldmll +dzogRm9udHNpemUgMjAuNzRwdApQcmV2aWV3OiBQREZvdXRwdXQgMQpMYVRlWCBGb250IEluZm86 +ICAgIFRyeWluZyB0byBsb2FkIGZvbnQgaW5mb3JtYXRpb24gZm9yIFUrbXNhIG9uIGlucHV0IGxp +bmUgNS4KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9s +YXRleC9hbXNmb250c1x1bXNhLmZkCkZpbGU6IHVtc2EuZmQgMjAxMy8wMS8xNCB2My4wMSBBTVMg +c3ltYm9scyBBCikKTGFUZVggRm9udCBJbmZvOiAgICBUcnlpbmcgdG8gbG9hZCBmb250IGluZm9y +bWF0aW9uIGZvciBVK21zYiBvbiBpbnB1dCBsaW5lIDUuCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXHVtc2IuZmQKRmlsZTog +dW1zYi5mZCAyMDEzLzAxLzE0IHYzLjAxIEFNUyBzeW1ib2xzIEIKKQpQcmV2aWV3OiBUaWdodHBh +Z2UgMCAwIDAgMApbMXtDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL01pS1RlWC9wZGZ0ZXgv +Y29uZmlnL3BkZnRleC5tYXB9XQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlu +a3RtcGowdjdpcWs5XGlucHV0LmF1eCkgKSAKSGVyZSBpcyBob3cgbXVjaCBvZiBUZVgncyBtZW1v +cnkgeW91IHVzZWQ6CiA1MTUyIHN0cmluZ3Mgb3V0IG9mIDQ3ODg2OAogMTAzMTYyIHN0cmluZyBj +aGFyYWN0ZXJzIG91dCBvZiAyODQ4ODA5CiA1MjgzNDYgd29yZHMgb2YgbWVtb3J5IG91dCBvZiAz +MDAwMDAwCiAyMzA1MyBtdWx0aWxldHRlciBjb250cm9sIHNlcXVlbmNlcyBvdXQgb2YgMTUwMDAr +NjAwMDAwCiA0MDgwNjYgd29yZHMgb2YgZm9udCBpbmZvIGZvciA0NSBmb250cywgb3V0IG9mIDgw +MDAwMDAgZm9yIDkwMDAKIDExNDEgaHlwaGVuYXRpb24gZXhjZXB0aW9ucyBvdXQgb2YgODE5MQog +MTIyaSw0biwxMjhwLDEwNzI3YiwyODBzIHN0YWNrIHBvc2l0aW9ucyBvdXQgb2YgNTAwMGksNTAw +biwxMDAwMHAsMjAwMDAwYiw4MDAwMHMKPEM6L1VzZXJzL2pvbmF0L0EKcHBEYXRhL0xvY2FsL1By +b2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21yMTIucGZiPjxD +Oi9Vc2Vycwovam9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9udHMvdHlwZTEv +cHVibGljL2Ftc2ZvbnRzL2NtL2Ntc3kxMC5wZmI+Ck91dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXBqMHY3aXFrOVxpbnB1dC5wZGYgKDEKIHBh +Z2UsIDE4NDc5IGJ5dGVzKS4KUERGIHN0YXRpc3RpY3M6CiAxNiBQREYgb2JqZWN0cyBvdXQgb2Yg +MTAwMCAobWF4LiA4Mzg4NjA3KQogMCBuYW1lZCBkZXN0aW5hdGlvbnMgb3V0IG9mIDEwMDAgKG1h +eC4gNTAwMDAwKQogMSB3b3JkcyBvZiBleHRyYSBtZW1vcnkgZm9yIFBERiBvdXRwdXQgb3V0IG9m +IDEwMDAwIChtYXguIDEwMDAwMDAwKQoK + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.pdf + +JVBERi0xLjUKJdDUxdgKMyAwIG9iago8PAovTGVuZ3RoIDE2MSAgICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjafY67CsJAEEX7+YpbKsK4M/vKtgFTpBO3C6kMVga08vfdxAdq +QKYZhjP33DrTttEEcWxdUOQThCUFiGdnA/KAbiWbdZ/bbWP9Fxc5ufIpXIX4AC8TR7tMVxKYMgJb +4qCRfcJxpK43GMq9hWEfHW4zNSKyUVe2Mw60p3pZao757OSXqmdxZU3yK6s0vGU2cNLqn00Ci5uI +WaUv1R1XBD8KCmVuZHN0cmVhbQplbmRvYmoKMiAwIG9iago8PAovVHlwZSAvUGFnZQovQ29udGVu +dHMgMyAwIFIKL1Jlc291cmNlcyAxIDAgUgovTWVkaWFCb3ggWzAgMCAzOS4zMTkgMjguNDUxXQov +UGFyZW50IDYgMCBSCj4+CmVuZG9iagoxIDAgb2JqCjw8Ci9Gb250IDw8IC9GMjkgNCAwIFIgL0Yz +NSA1IDAgUiA+PgovUHJvY1NldCBbIC9QREYgL1RleHQgXQo+PgplbmRvYmoKNyAwIG9iagpbODMz +LjNdCmVuZG9iago4IDAgb2JqCls3NjEuNiAyNzIgMzI2LjQgMjcyIDQ4OS42IDQ4OS42IDQ4OS42 +IDQ4OS42IDQ4OS42IDQ4OS42IDQ4OS42XQplbmRvYmoKOSAwIG9iago8PAovTGVuZ3RoMSAxNDE0 +Ci9MZW5ndGgyIDY0MDkKL0xlbmd0aDMgMAovTGVuZ3RoIDczNzggICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjajXQHVFNb1y0d6b0LBOk99Cq9CFJDU5QSSIBQkhgChCa9Skd6 +BxEE6b2JSOeCSBeQXgRFkSogyh/Ld+9/v/fGeG+cMc45a6651l5r77k2L5eJmag6BOEA1UHA0aIS +YkBFgKYhSEISAARKiQGBkqS8vOYwtDv0D0zKawlFecIQcMX/RdBEQcFoLKYFRmN5hgg4QN/LHSAh +BZCQVZSQUwQCAZJAoMJ/iAiUIkAL7A2DAAzFAPoIONSTlFcTgfRFwZxd0Nhl/vMLEHAUBEgoKMiJ +/AoHqHtAUTBHMBxgCEa7QD2wKzqC3QFmCEcYFO37rxQCyi5oNFJRXNzHx0cM7OEphkA5qwiKAHxg +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 +ZfP2p+Fd+Xtljn54vdSDmJAYPMK74cqeHH3wqHkpM86KjYQzb45Z9z5LgeZfZR9CjZnMfMzHskcW +D82MqVi6ZQqdJU/cRNbx7WdRs2Ed6nOfZfGh1naOYl2bpX5ljHrzD6+LMltARRKjMgouNLzVddE8 +lAZ7+POHHblyq5mKNMKhDmmHAs1sdigYvQDfxdLH4038YrESeGRKKEjtlaP49uzRMHzlk+16rJYm +1IIwrn/FcI/zhWwZjGeF/2j7CmM6V6/DzL2qbBCxrVxPsMw1EU8C435SkJecAU1v9luVwOxs8AsX +AwsGRx1MIHtKtB/cy4UiQmitkl48fqQ5KNi9dHmiGHPO4WPKafX0ibD4rk+pUTS1nip++utjpQuZ +B+yX2ZNSgTfqMtzi5OZVBTeaHAdOJukWIpDhXvQevL5j1pbO+U4OQm0N/FGayikXrmTQTHYmlRPG +m4O0WX5ZiZIffNXi+JCcX05uj557M7XdEzXIKBROpz/Trw/4TkIN9F22u/gyYlrLSTLb7LXzhLFb +hHt/8y43J+7Yq5X3z4fnNCGUdxlL4obeQzpOcuLMb9S9C73qsUQsyh+dhaZ6omOs6r8GBcMY0mUJ +kTMU/kKFD/Aeui6KpW+8vDvrObqtIBMKKgPNBhQQSc2sy/C/Fs7sulHxsCFFpnU3slmV8tp+xfSr +moQodoEqxsTnH3FShaMCONjf3Mo9UE4JcHaWvt7FPaXmMUtU/henqbDMfd1XG5kjOgT0ct5dfrYW +J369IchcufgCYooEDdjVdD3FLOfU9JnurWHRH7tsUQNgXLtXuFYpLqxh9GKyUVqYe6eFHcw44TM3 +Tm04CiwI9l4+W8w38dBpHIoQtIgaDcgNoVuXDE27bAqwS/9m7dGO1v7avIJPm/W9p8HOe+V2DD/t +zN3zi9NUlEqv7sV6jA1FUfv+mpVeSW2VV5mH0m0TrUMSmlI1T5X/AXfAEUIKZW5kc3RyZWFtCmVu +ZG9iagoxMCAwIG9iago8PAovVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9DSkJFQkkr +Q01SMTIKL0ZsYWdzIDQKL0ZvbnRCQm94IFstMzQgLTI1MSA5ODggNzUwXQovQXNjZW50IDY5NAov +Q2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAwCi9TdGVtViA2NQovWEhl +aWdodCA0MzEKL0NoYXJTZXQgKC9maXZlL29uZS9wbHVzL3R3bykKL0ZvbnRGaWxlIDkgMCBSCj4+ +CmVuZG9iagoxMSAwIG9iago8PAovTGVuZ3RoMSAxMzgzCi9MZW5ndGgyIDU5NzYKL0xlbmd0aDMg +MAovTGVuZ3RoIDY5MjYgICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjajXgH +VFPbujUCAiK9dwPSawLSe++9i5SQBAiEBEnoIFWa9CZNEKQXAelIUaqAdOkK0psIAgIi6Isez733 +3P8f472RMXb2+r75tbXm3MnYXOxGpkLKUJQjTAOFxAiBhIEyAFV9U2sQEAAEigkDgaLEXFxmcAwC +9redmMsC5omGo5Ay/4FQ9YSBMVibGhiDBeqjkAAdLwQAJAYASciAJGWAQIAoECj9NxDlKQNQA3vD +oQB9YYAOCglDE3Opojz8POHOLhhsnb9vAbwQPgBIWlpS8Hc4QNkd5gmHgJEAfTDGBeaOrQgBIwCm +KAgchvH7RwpeORcMxkNGRMTHx0cY7I4WRnk6K/AJAnzgGBeACQwN8/SGQQG/RgYYgN1hf0YTJuYC +mLnA0X85TFFOGB+wJwyANSDgEBgSjQ3xQkJhngBsdYCpth7A0AOG/Aus9xdAEPBncwAgYdC/0v2J +/pUIjvwdDIZAUO4eYKQfHOkMcIIjYABDDT1hjC9GEABGQn8BwQg0ChsP9gbDEWBHLOB362CAhrIx +AIyd8M98aIgn3AODFkbDEb9mFPmVBrvN6kioKsrdHYbEoIl/9acG94RBsPvuJ/LncN2QKB9kwN8r +JzgS6vRrDKiXh4g5En7fC6at9geDNRH/2+YMwwDEgdISEuIgAOw+AOYLcRH5VcDMzwP22/nbjJ0h +KMAD5QFwwo4BC4I7wbBfxAFosDcMgPH0ggUF/KfjnytiEAgAhUMwAEeYMxxJ/O/sWDPM6a819vw9 +4b4AGyCWfiAA8NfnX3e2WIZBUUiE37/hv49YRENXQ99QW+DPyP9yqqigfAEBQqLSACFpCSAABAJJ +ACQlxQFB/8xjBIb/6eM/YrWRTiiA9F/tYvfp75a9/3CA949A+AD/zGWAwjIXBuD9N9HvAcWBEOwF +9H+m+++Q/x/Lf2X5X4n+3x1peCEQv/28fwH+Hz/YHY7w+4PAMtcLg1WBPgqrBeR/Qy1hf0lXHwaF +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 +TGytNZy5EKUwKetuIPd9s71HdCvauI/oxEfFeTx5tf3K9OplXg7HbAUix/Hw1F+2tS5T22/6nvrs +9dfDuzEenmVu+iTNSgRK3TDuV0/F0jMRPUMxGNOzzV4u1tB9vm0RD5OB86X5VxUcDKKNXsSZ6rAU +8XOB3vladOndIx4mIpq61tKvmR+3HKONXzCdHNaaIqjyXftOAUmMTP6E3ow4FEshqw+4hKl1/e8Z +0BTERmxdrp3Rqe8SCq7BLEQnKeX16VHUfDRCoTqQAYuPRTKTTObzohMtCoOg6Nk3qRzkXcaWbU/D +Da++TiTf4Tf0/94mDGk5doWkVVpzXy6/n5sbo078tCu/J0mVZs2Q1XB6/uZwV1BZHDmkvawRmy6S +q3j5NjZrhdQWjBZuMODfemHWVg+YkE76OdKkKG/GNsn0kWPbfRnAVuV87alnxZE39IOBL6Z3nddF +UG3pSQ5Nt31Z97Y38YjfFxbqlUwHgZ15S0UUPlQ2pPI5SxN3Hs6bSuUn2j0ObpR15ydIPx/fHMbP +4X3t4l298SVTQu8mENR4tX5PfmRekJybUl1nvPttJ2VhAIFozvvKANuspTp6cjolJl+x4SaRsCTS +7WqFp3a1P/Ktn9rpa3Rw3RaQ3PcRppvv2tsO1TCPahKd78/jrtDF2v7vtB9cZwBl4VILbAikQgzI +qN988543FnN5bZUj5zvBwA8luE+f7caFfy8iwrCCwUryMttu/Yb5/gGvn+JR/A/lGc76rgyYf8gG +mDgyX6j3u2K/oXFR2xbQECK5dLSpU24fkMW4icOhJKWw9XGW5mrqeQXpePiW3qlE7e2bF2G3T10n +cz8OJYWLC/tPKWy8aSmf3ElbGGiGIICegaMMkcBS5xJpS42bWTf1Fu/NjF3rT6Q7pAxedrdpZRO7 +P9NgTsFxYplIM7qqW2xvJn5F/z9k6mtSCmVuZHN0cmVhbQplbmRvYmoKMTIgMCBvYmoKPDwKL1R5 +cGUgL0ZvbnREZXNjcmlwdG9yCi9Gb250TmFtZSAvRktGTU9JK0NNU1kxMAovRmxhZ3MgNAovRm9u +dEJCb3ggWy0yOSAtOTYwIDExMTYgNzc1XQovQXNjZW50IDc1MAovQ2FwSGVpZ2h0IDY4MwovRGVz +Y2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAtMTQKL1N0ZW1WIDQwCi9YSGVpZ2h0IDQzMQovQ2hhclNl +dCAoL3JhZGljYWwpCi9Gb250RmlsZSAxMSAwIFIKPj4KZW5kb2JqCjEzIDAgb2JqCjw8Ci9MZW5n +dGggNzM5ICAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNptVU1v4jAUvOdX +eA+V2gPFdkgCVYRk50PisG1VqtVeITHdSJCgEA799+vxI3jZ9gAaP4+fZ+zB3P14XU9U3W3NJHzk +7M2cunNfmUn2c3MM7u7yrjofTDs8G1Obepw9PbHXvqvWZmD32Spftc3wYMmrttqfazOyvidp89G0 +noJ92P27+T2pDr2Qk+252Q9NO+HgvjfD3nK+m2a2xm5qzC35ZfpT07VPTDxyzm2haOusO8DDKZhe +dLDpqGzXtHV/EcO2kBYIyeqmGi4j910d7GFg8frzNJjDqt11QZqy6ZudPA39p1P4EExf+tr0TfvB +7m+U2Zn1+XjcG6hgPFguWW12tqH1/rw5GDb9zuCV8v55NEy6sSBVVVeb03FTmX7Tfpgg5XzJ0rJc +Bqat/5tLaMV2N1ITS+VzfIUqWgapDC2WMQrcYlvAZKipMLeFsLQ4ooLFQRoLixPlChYHaYLJJEMj +LtBDoYdaXHexukYFyXxUVP3Z9BftPFxgGUdjKXkMLKkOBTwkrIFnhAvgiHbgwDFh1+eys1sLnVJI +15NMxDE+GGd+vMA49+MM4+If/sgpb2vgCedBhDgLAQ/2JBNgSVzoE84D1zNg50FmjuM8yBxaBV2D +wiGLhOoKeE5rHcd547nj0B0U8CKcNxHBvyBfpeOTp8xxCuJIYPLh9pWCbhv6paRrzIETwvAdUk8F +Tkg9Q3BCOiMNPdElAjiTiDgROFFBfqEhKskXesac+NCQ5FQHPyF+jj4J6XR3qTjpxHkq4XOjpM+N +Cn1u1MznRkU+Nyr2uVGJz41SPjeKsqKgR128O37u86SK2zyp8jZPmt/mSYuvedLya5506POkZz5P +OvJ50rHPk058nvTc50kvfJ608nnS2udJZz5POvd50oXPky59njLu85QJn6dM+jxls+uduV+++6Xj +bcI7en31qnPf2wfRPbbuocMT17Tm+h4fuyNWuY97yMe/DYxeyuAvK5CoWgplbmRzdHJlYW0KZW5k +b2JqCjQgMCBvYmoKPDwKL1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvQ0pC +RUJJK0NNUjEyCi9Gb250RGVzY3JpcHRvciAxMCAwIFIKL0ZpcnN0Q2hhciA0MwovTGFzdENoYXIg +NTMKL1dpZHRocyA4IDAgUgovVG9Vbmljb2RlIDEzIDAgUgo+PgplbmRvYmoKMTQgMCBvYmoKPDwK +L0xlbmd0aCA5MDAgICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42m1VTW/b +OhC861ewhwDpwTU/JFIuDAOkZAM59ANN8PCujsTkCYhlQ7YP+fePs2ubbZFDjNVwuTs7HIZ3n34+ +zny/f44z80WKX/G4P09dnDXftofi7q7dd+ddHE/fY+xjf109fhU/p333GE/ivnloH8bh9DklP4zd +27mP16yPk0J8Hcacgj7i/in+O+t2x3clZ8/n4e00jDOJ5Kfh9JaSPlwXCRR/goI2/ROn47Afvwr1 +RUqZgPXYN/sdxjgW8wsVMb+SexnGfrrwEc9gVygt+qE7Xb7ot9slPbD58f14iruH8WVfLJdi/ist +Hk/TO3H8XMx/TH2chvFV3P9JLS09ng+HtwgaQharlejjS6qY5v++3UUx/3DGW87T+yEKTd+KeXX7 +Ph4P2y5O2/E1FkspV2K52ayKOPZ/rWnHW55frrl1ypVN+tF6Ua2KpdIpVoaA2gIoAVQE2BKABeAA +eL8B4AEE3qIBoJ5qeYsHsAawIcAB0NQAlbVaGADUwDLgAFA9IqZaZBjUMFzDg0epUlyht5QpLpYV +MirO0KhhIYRVvAXELIaz1NtI8LCgYCsGagDQwy4AuDUAB07OsUDo4rDo0FZLLRPgAXifJfSY3DMP +miWgQbBZ04B6oc6aBtQIPmsaUCOss6YB9RqZNW0wV6NvmqbDvp5qra6n3P23nS6G0FqhjlQkWAAv +qSluKeYjVxSXhG8o5pNvwFJa3gsZJEuicDSSjlq2LWLiXK0xptywSuQJ5lAiR/GRWNRRrIJpEC84 +B7pryV6AwlpxjDpac4y9mjmUZKCarUL5C44p33NM+S3vBTe95niBmM9KgZuhvtJgr2Geyb0pZqXJ +JIa1kgExmbgKZNGKY6pDWhlD+TyjBDfDM0rKZ/N6zG74/kgYyLDtFeHMWYF/yZoY5FScr2GFiu+v +xiwVX7sanC2flwNP6zgGN8t9HerbSx3UtNyXTGy5b0vxmvIrymetSsziLr4CB0daeQPzuotW8I9j +rTQ4uJLvBLzk2Fd0+V3NOlB+YI/hjBzxsZZyWo5xLm7NMV3HDcfgU//mGS+pDt9Qlf3vdfa/N9n/ +vsz+91X2v7fZ/95l//s6+z/I7P+gsv+Dzv4PJvs/lNn/IWT/hyb7vzF5lqa8zUi3nG41/rnjKbq9 +G915mtKTQu8VvRR4I4Yx3p60w/6AXfRHb+H18cXXj03xP65Y6h4KZW5kc3RyZWFtCmVuZG9iago1 +IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovQmFzZUZvbnQgL0ZLRk1PSStD +TVNZMTAKL0ZvbnREZXNjcmlwdG9yIDEyIDAgUgovRmlyc3RDaGFyIDExMgovTGFzdENoYXIgMTEy +Ci9XaWR0aHMgNyAwIFIKL1RvVW5pY29kZSAxNCAwIFIKPj4KZW5kb2JqCjYgMCBvYmoKPDwKL1R5 +cGUgL1BhZ2VzCi9Db3VudCAxCi9LaWRzIFsyIDAgUl0KPj4KZW5kb2JqCjE1IDAgb2JqCjw8Ci9U +eXBlIC9DYXRhbG9nCi9QYWdlcyA2IDAgUgo+PgplbmRvYmoKMTYgMCBvYmoKPDwKL1Byb2R1Y2Vy +IChNaUtUZVggcGRmVGVYLTEuNDAuMjMpCi9DcmVhdG9yIChUZVgpCi9DcmVhdGlvbkRhdGUgKEQ6 +MjAyMjAzMDUyMDMxNTcrMDEnMDAnKQovTW9kRGF0ZSAoRDoyMDIyMDMwNTIwMzE1NyswMScwMCcp +Ci9UcmFwcGVkIC9GYWxzZQovUFRFWC5GdWxsYmFubmVyIChUaGlzIGlzIE1pS1RlWC1wZGZUZVgg +NC44LjAgKDEuNDAuMjMpKQo+PgplbmRvYmoKeHJlZgowIDE3CjAwMDAwMDAwMDAgNjU1MzUgZiAK +MDAwMDAwMDM2NSAwMDAwMCBuIAowMDAwMDAwMjU1IDAwMDAwIG4gCjAwMDAwMDAwMTUgMDAwMDAg +biAKMDAwMDAxNjM2MyAwMDAwMCBuIAowMDAwMDE3NDk4IDAwMDAwIG4gCjAwMDAwMTc2NTYgMDAw +MDAgbiAKMDAwMDAwMDQ0NCAwMDAwMCBuIAowMDAwMDAwNDY3IDAwMDAwIG4gCjAwMDAwMDA1NDYg +MDAwMDAgbiAKMDAwMDAwODA0MiAwMDAwMCBuIAowMDAwMDA4MjczIDAwMDAwIG4gCjAwMDAwMTUz +MTggMDAwMDAgbiAKMDAwMDAxNTU0NCAwMDAwMCBuIAowMDAwMDE2NTE4IDAwMDAwIG4gCjAwMDAw +MTc3MTMgMDAwMDAgbiAKMDAwMDAxNzc2MyAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDE3Ci9S +b290IDE1IDAgUgovSW5mbyAxNiAwIFIKL0lEIFs8NkI4RjA5MkMxQjRCNDg3Q0MzOEQ5MTQ3NjVG +N0E5QTk+IDw2QjhGMDkyQzFCNEI0ODdDQzM4RDkxNDc2NUY3QTlBOT5dID4+CnN0YXJ0eHJlZgox +Nzk4MgolJUVPRgo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/pdflatex/acb704059fd20b4a9a5c69387a391c7d.msg b/share/extensions/tests/data/cmd/pdflatex/acb704059fd20b4a9a5c69387a391c7d.msg new file mode 100644 index 0000000..3f87fde --- /dev/null +++ b/share/extensions/tests/data/cmd/pdflatex/acb704059fd20b4a9a5c69387a391c7d.msg @@ -0,0 +1,1171 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: pdflatex +Arguments: -halt-on-error -output-directory=. input.tex + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KQ0KZW50ZXJpbmcgZXh0ZW5kZWQgbW9kZQ0KKEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9j +YWwvVGVtcC9pbmt0bXBkc3J4bXJqNy9pbnB1dC50ZXgNCkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDENCkwzIHByb2dyYW1taW5nIGxheWVyIDwyMDIxLTA3LTEyPg0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9iYXNlXG1pbmlt +YWwuY2xzDQpEb2N1bWVudCBDbGFzczogbWluaW1hbCAyMDAxLzA1LzI1IFN0YW5kYXJkIExhVGVY +IG1pbmltYWwgY2xhc3MNCikgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc21hdGguc3R5DQpGb3IgYWRkaXRpb25hbCBpbmZv +cm1hdGlvbiBvbiBhbXNtYXRoLCB1c2UgdGhlIGA/JyBvcHRpb24uDQooQzpcVXNlcnNcam9uYXRc +QXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zdGV4dC5z +dHkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0 +ZXgvYW1zbWF0aFxhbXNnZW4uc3R5KSkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFBy +b2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNic3kuc3R5KQ0KKEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc29w +bi5zdHkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRl +eC9sYXRleC9hbXNmb250c1xhbXNzeW1iLnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9j +YWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1xhbXNmb250cy5zdHkpKQ0KDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2wz +YmFja2VuZFxsM2JhY2tlbmQtcGRmDQp0ZXguZGVmKQ0KTm8gZmlsZSBpbnB1dC5hdXguDQooQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2Zv +bnRzXHVtc2EuZmQpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXHVtc2IuZmQpDQpbMXtDOi9Vc2Vycy9qb25hdC9BcHBEYXRh +L0xvY2FsL01pS1RlWC9wZGZ0ZXgvY29uZmlnL3BkZnRleC5tYXB9XQ0KKEM6XFVzZXJzXGpvbmF0 +XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXBkc3J4bXJqN1xpbnB1dC5hdXgpICk8QzovVXNlcnMv +am9uYXQvQQ0KcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMv +YW1zZm9udHMvY20vY21leDEwLnBmYj48QzovVXNlcg0Kcy9qb25hdC9BcHBEYXRhL0xvY2FsL1By +b2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21taTEwLnBmYg0K +PjxDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBl +MS9wdWJsaWMvYW1zZm9udHMvY20vYw0KbW1pNy5wZmI+PEM6L1VzZXJzL2pvbmF0L0FwcERhdGEv +TG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRzL3R5cGUxL3B1YmxpYy9hbXNmbw0KbnRzL2NtL2Nt +cjEwLnBmYj48QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9u +dHMvdHlwZTEvcHVibA0KaWMvYW1zZm9udHMvY20vY21yNy5wZmI+PEM6L1VzZXJzL2pvbmF0L0Fw +cERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRzL3R5cA0KZTEvcHVibGljL2Ftc2ZvbnRz +L2NtL2Ntc3k3LnBmYj4NCk91dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcVGVtcFxpbmt0bXBkc3J4bXJqN1xpbnB1dC5wZGYgKDENCiBwYWdlLCA1NjM1MSBieXRl +cykuDQpUcmFuc2NyaXB0IHdyaXR0ZW4gb24gQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxU +ZW1wXGlua3RtcGRzcnhtcmo3XGlucHV0LmxvDQpnLg0K + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.pdf + +JVBERi0xLjUKJdDUxdgKMyAwIG9iago8PAovTGVuZ3RoIDI5MiAgICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjajZKxTsNADIb3ewqztUPcs33n8w1dKtGhGyIDUulEVQnRIjHx ++jhJU1KRAWWJki+/v/i/TRtWW2aoWJUV2hNUQWKCohGpFGiPsF+8RqHlod2ttmSgWItYhypGURBU +0oHjDgqPbfgKBNEvusXljJUN3i5hf4hw9Hc7iCjV4LsnL0ARc1S/PcNzeAqbzozq1CyjmUBJihrT +MFG7iUCExT9VNLk+Xy8bZVuc3y+Dtyv8eneTXLlxpWID/3nF0gRLbpzdpwceaCaIGYUrkGESugui +6UqbhEUEGsZqdcBeZtKaiDE7RZjSdfEfM1tPmKKMWuuxl+miKLuPdVrFq+05+tsM5eI/yP+pxqPL +fTF3R+aWNG1mTj17wwSMNq79dmB+AOlajKAKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8Ci9U +eXBlIC9QYWdlCi9Db250ZW50cyAzIDAgUgovUmVzb3VyY2VzIDEgMCBSCi9NZWRpYUJveCBbMCAw +IDU5NS4yNzYgODQxLjg5XQovUGFyZW50IDEwIDAgUgo+PgplbmRvYmoKMSAwIG9iago8PAovRm9u +dCA8PCAvRjIyIDQgMCBSIC9GMTggNSAwIFIgL0YxOSA2IDAgUiAvRjIxIDcgMCBSIC9GMjQgOCAw +IFIgL0YxMiA5IDAgUiA+PgovUHJvY1NldCBbIC9QREYgL1RleHQgXQo+PgplbmRvYmoKMTEgMCBv +YmoKWzE0NDQuNV0KZW5kb2JqCjEyIDAgb2JqClsxMTM4LjkgNTg1LjMgNTg1LjMgMTEzOC45IDEx +MzguOSAxMTM4LjkgODkyLjkgMTEzOC45IDExMzguOSA3MDguMyA3MDguMyAxMTM4LjkgMTEzOC45 +IDExMzguOSA4OTIuOSAzMjkuNCAxMTM4LjldCmVuZG9iagoxMyAwIG9iagpbNjA3LjMgMzYxLjMg +MTAxMy43IDcwNi4yXQplbmRvYmoKMTQgMCBvYmoKWzUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUw +MCA1MDAgNTAwIDI3Ny44IDI3Ny44IDI3Ny44IDc3Ny44IDQ3Mi4yIDQ3Mi4yIDc3Ny44IDc1MCA3 +MDguMyA3MjIuMiA3NjMuOSA2ODAuNiA2NTIuOCA3ODQuNyA3NTAgMzYxLjEgNTEzLjkgNzc3Ljgg +NjI1IDkxNi43IDc1MCA3NzcuOCA2ODAuNiA3NzcuOCA3MzYuMSA1NTUuNiA3MjIuMiA3NTAgNzUw +IDEwMjcuOCA3NTAgNzUwIDYxMS4xIDI3Ny44IDUwMCAyNzcuOCA1MDAgMjc3LjggMjc3LjggNTAw +IDU1NS42IDQ0NC40IDU1NS42IDQ0NC40IDMwNS42IDUwMCA1NTUuNiAyNzcuOCAzMDUuNiA1Mjcu +OCAyNzcuOCA4MzMuM10KZW5kb2JqCjE1IDAgb2JqCls1NjkuNSA1NjkuNSA1NjkuNSA1NjkuNSA1 +NjkuNSA1NjkuNSA1NjkuNSA1NjkuNSA1NjkuNSAzMjMuNCAzMjMuNCAzMjMuNCA4NzddCmVuZG9i +agoxNiAwIG9iagpbNTcwIDUxNyA1NzEuNCA0MzcuMiA1NDAuMyA1OTUuOCA2MjUuNyA2NTEuNCA2 +MjIuNSA0NjYuMyA1OTEuNCA4MjguMSA1MTcgMzYyLjggNjU0LjIgMTAwMCAxMDAwIDEwMDAgMTAw +MCAyNzcuOCAyNzcuOCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAw +IDUwMCAyNzcuOCAyNzcuOCA3NzcuOCA1MDAgNzc3LjggNTAwIDUzMC45IDc1MCA3NTguNSA3MTQu +NyA4MjcuOSA3MzguMiA2NDMuMSA3ODYuMyA4MzEuMyA0MzkuNiA1NTQuNSA4NDkuMyA2ODAuNiA5 +NzAuMSA4MDMuNSA3NjIuOCA2NDIgNzkwLjYgNzU5LjMgNjEzLjIgNTg0LjQgNjgyLjggNTgzLjMg +OTQ0LjQgODI4LjUgNTgwLjYgNjgyLjYgMzg4LjkgMzg4LjkgMzg4LjkgMTAwMCAxMDAwIDQxNi43 +IDUyOC42IDQyOS4yIDQzMi44IDUyMC41IDQ2NS42IDQ4OS42IDQ3NyA1NzYuMiAzNDQuNSA0MTEu +OCA1MjAuNl0KZW5kb2JqCjE3IDAgb2JqCjw8Ci9MZW5ndGgxIDEzODcKL0xlbmd0aDIgNTk3NQov +TGVuZ3RoMyAwCi9MZW5ndGggNjkyOSAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJl +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 +rrU8w6gkks3A3/bx8bUvo08Rh6HURh9nQaxclsSjvmU5KtKLXZJF0MAHL/L0dg/QWnuOEkZneX6C +wnmdqVzO7URV0UkXo5qyM6/28PfFz2V9aFUtviuDWQyxmaJlgY8RHN3XHDzbnc38wFFa81IXGQsK +FI6bgVveE6OlnaVZ1spVyS3B+MAEjMyZ6p7kraHsiXJ5joSU3ZbV5UGFDLnlSCbTEEjeiKHK2oLV +Us2pluGrg+GHwRYE5W0K1DhuvoqjiYpVQwwIcQUGrqAKl/OQk8VM8a8mRPcU6sax70iZbbfOlVB5 +a8GPavPKp9pWXGooPlUF95v1hF6Lh4nXYIa4ZM8v+xtxiuqkGB7c1ZsgszQ/8owbAp2lOJLicEB9 +5nRMnnzIvZwrUT8vOH1xY4sOqCfJksrRjCU8usH9Aildx9iKsLWnsxvDSn/PmfLqiOWbKP00Gkfc +GSB3y2Ul4dvNTFJ5QonXDLfC8RYZ38kzBmONcUvVl5BusxB4dKLdpOj4dCvEnTr89Xo/+Cma0Wcr +lva+3nTkdsLnvvOeyVK/0bX+kBlL6q7oU5IC8cH8r+LC6UJ25U/hfXkTuuoPlAfm8GuLsCbN/tqR +77Hx9tczZ7pi9GjkuQw49ns3mgJvQ8oRtv5Mdd0J2XbAwgd4OgZRLoRocpEx1ArNixD/+FJJcu5W +TYVFBZZZl07I8cFrrgCGfmwFmzCuYNTNGhfgDNH/AAM9XJ8KZW5kc3RyZWFtCmVuZG9iagoxOCAw +IG9iago8PAovVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9ZUUpTREorQ01FWDEwCi9G +bGFncyA0Ci9Gb250QkJveCBbLTI0IC0yOTYwIDE0NTQgNzcyXQovQXNjZW50IDQwCi9DYXBIZWln +aHQgMAovRGVzY2VudCAtNjAwCi9JdGFsaWNBbmdsZSAwCi9TdGVtViA0NwovWEhlaWdodCA0MzEK +L0NoYXJTZXQgKC9zdW1tYXRpb25kaXNwbGF5KQovRm9udEZpbGUgMTcgMCBSCj4+CmVuZG9iagox +OSAwIG9iago8PAovTGVuZ3RoMSAxNDA5Ci9MZW5ndGgyIDYyODEKL0xlbmd0aDMgMAovTGVuZ3Ro +IDcyNDYgICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjajXcHVJPb0jaCIEWk +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 +SEdQS0MrQ01NSTEwCi9GbGFncyA0Ci9Gb250QkJveCBbLTMyIC0yNTAgMTA0OCA3NTBdCi9Bc2Nl +bnQgNjk0Ci9DYXBIZWlnaHQgNjgzCi9EZXNjZW50IC0xOTQKL0l0YWxpY0FuZ2xlIC0xNAovU3Rl +bVYgNzIKL1hIZWlnaHQgNDMxCi9DaGFyU2V0ICgvay9waSkKL0ZvbnRGaWxlIDE5IDAgUgo+Pgpl +bmRvYmoKMjEgMCBvYmoKPDwKL0xlbmd0aDEgMTQwMAovTGVuZ3RoMiA2MzI5Ci9MZW5ndGgzIDAK +L0xlbmd0aCA3MjkzICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o10BVSU +7/YuKYiESJcM3TBDd3d3CALDMMAQM8TQICHdgnQp0p3SoIQ0CCKtICklKQIS/zHOOf/fuXete9es +9c239372fvd+9/N8LAy6BjxytggbqDICjuQB8QLFAQpaWmoiACBQgBcI5MdjYTGEIZ2hf914LMZQ +dw8YAi7+vwAK7lAwEuVTBCNROC0EHKDu6QwACQBAwuIgEXEgEMAPBIr9C4hwFwcogr1gtgAtXoA6 +Ag71wGNRQLj6usPsHZCoY/71CmCHcABAYmIi3L/TAXIuUHcYBAwHaIGRDlAX1IkQsDPAAAGBQZG+ +/yjBLumARLqK8/F5e3vzgl08eBHu9tIc3ABvGNIBoA/1gLp7QW0BvwYGaINdoH8m48VjARg6wDz+ ++A0QdkhvsDsUgHI4wyBQuAcqwxNuC3UHoA4HGKhpAnRcofA/YM0/AG7A37sBgHhB/y73N/tXIRj8 +dzIYAkG4uILhvjC4PcAO5gwF6Chr8iJ9kNwAMNz2FxDs7IFA5YO9wDBnsA0K8LtzMEBZTg8ARg34 +dzwPiDvMFenB6wFz/jUi368yqFtWgtsqIFxcoHCkB96v/hRh7lAI6tp9+f5s1gmO8Ib7/zXsYHBb +u19D2Hq68hnBYW6eUDXFvxCUC+8/PnsoEiAEFBUREOUHQN0AUB+IA9+v8oa+rtDfQdAvN2qCQH9X +hCvADjUENBBmB0X94fl7gL2gAKS7JzTQ/38H/mnhgUAAWxgECbCB2sPgeP+pjnJD7f7YqOW7w3wA +5kAU90AA4K/fv98eo+hli4A7+/4H/nu/fMZKairGhlx/Jv53TF4e4QPw5wEBePiFgAAQSAQEEEG9 +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 +qnDV6L4Wd+0FR3p6nFPgJrdFmVnFqo4yzW6kOgf1TKiM8V3sqTnIWOFSOIQSf/WTMqsQRSfi/14U +cD9ym0owzsEIgbbESCBMVgmb79MzPp1KorMCEJS/pxu0Sq/bxdngPJh/tBs80W7wjt/b+ntw7sqB +Fb7q87qqW4zdq7WnsyM57AsbKk/KmxoKEqyy/QxLU1W2mrtrey/jvonvWqJFD11TN4/1fqBdl60Y +PK8VjFe+Fey0LcEctRHTliM44l9rZ1Nyqn5AoFKSCd8w/6jdfG+lQLuqYfKptjlrJOnUFTZ3LUFM +Lh35o3y/GKYWycIQUPDrocBPQV8DwHYeSnk3Xh9GVh8qzprW7FVl7E7+DxKmHyYKZW5kc3RyZWFt +CmVuZG9iagoyMiAwIG9iago8PAovVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9WRUlH +VlQrQ01NSTcKL0ZsYWdzIDQKL0ZvbnRCQm94IFstMSAtMjUwIDExNzEgNzUwXQovQXNjZW50IDY5 +NAovQ2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAtMTQKL1N0ZW1WIDgx +Ci9YSGVpZ2h0IDQzMQovQ2hhclNldCAoL2svbikKL0ZvbnRGaWxlIDIxIDAgUgo+PgplbmRvYmoK +MjMgMCBvYmoKPDwKL0xlbmd0aDEgMTQ0NAovTGVuZ3RoMiA4OTA0Ci9MZW5ndGgzIDAKL0xlbmd0 +aCA5ODg4ICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o23BVAc2rIujAcN +rkEGd3d3d3dngCEwg7t7IISgCe5uIWiw4A7B3d01uD2y9z7nnnP/v+q9mqqZ1d1f92r5elUNNbma +JrO4FcQCKAMBuzKzs7AJACSVNdjZAGxsnCxsbBzI1NRaIFd74D9qZGodoLMLCAIW+A+ApDPQ3PVV +J2Xu+opThoABCm72AHZOADuPADuvABsbgIONjf9fQIizAEDK3B1kBVBmAShAwEAXZGpJiKOXM8jG +1vX1mn8dAXSW9AB2fn5epr/cAeIOQGeQpTkYoGzuagt0eL3R0tweoAmxBAFdvf4rBJ2QraurowAr +q4eHB4u5gwsLxNlGhJ4J4AFytQVoAF2Azu5AK8CfggEq5g7AvytjQaYGaNmCXP7Wa0KsXT3MnYGA +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 +Wsz4XO9QCBV5Qrd9+oxHGJ+nkONEnUa9T4MXT2Nzj2rx4mulfYZ9oFPbgTBvKWwqpU5IAuWY5EXU +JFM+D4Gsm9I2RQ1FINkbVTzpUAfZ1F+kmISPq/qZ9ddv3Ow5szCOu8z3/e6eb43ky6a3K+IUOY/r +UfCA2ImFkvFxhnsFyKFz1Kzgu9lUJOUoLiD2HvU5z6CvZWxxf3mOjvio+EbqcpI/gjR2UcBAQpc2 +LObUwW4jXe9jc0HCb5RH49YHk2eg9tWqWuOqXMiqATD4A7C7INdlNA4dCQqNCD4Tr0L3i0fIM0Ut +F7lWaUKYBxJSaqd7v3hZ5jr+R9za6oCemCdAwgttFENOzRXfCF7c3vPJ2subBouOyUOU/NBa4WfM +5fTr32bi0ivh3nGwlStbeIhEllWeGR1ZEddxyzQFog5VL2qOhXboKwYmFA0YdIxtzlhVnIMahOtW +nyw5kvozcZXsktcFPuLslPB50xcvxAt7l7VuZLpXVkMzjLE1jZNbkN8zIWgvmK3Q/uDCxpMyxJ40 +LpCTTKn/NFIlkaXb4K8igGlqUTXQjeKw/4YWa8Yy9wXZMvK9GZlid4p9siyu6W75r+xjHcHNfKXH +CN6X1PzjL9X/B8gjNPoKZW5kc3RyZWFtCmVuZG9iagoyNCAwIG9iago8PAovVHlwZSAvRm9udERl +c2NyaXB0b3IKL0ZvbnROYW1lIC9MSENBTkErQ01SMTAKL0ZsYWdzIDQKL0ZvbnRCQm94IFstNDAg +LTI1MCAxMDA5IDc1MF0KL0FzY2VudCA2OTQKL0NhcEhlaWdodCA2ODMKL0Rlc2NlbnQgLTE5NAov +SXRhbGljQW5nbGUgMAovU3RlbVYgNjkKL1hIZWlnaHQgNDMxCi9DaGFyU2V0ICgvZXF1YWwvaS9s +L20vb25lL3NpeCkKL0ZvbnRGaWxlIDIzIDAgUgo+PgplbmRvYmoKMjUgMCBvYmoKPDwKL0xlbmd0 +aDEgMTM5MQovTGVuZ3RoMiA2MTg2Ci9MZW5ndGgzIDAKL0xlbmd0aCA3MTM2ICAgICAgCi9GaWx0 +ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o12BVQTbN83JTE6pJFJKL2NBqW7O6XGGDBgG4yR +AySUEhEkFSSlEVEEEaSZgEgoISEtoaQiSPNOvZ/7fu/n+875vrNztuvfcf1+15ngZVMLcTU3tCtc +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 +xB9+U4R3GP3MoOv9dKmQt0tt5NGzl8gI0lrFg6UYMP6CzxwuOX1hQEpWPI7Zp2pUhS1qZzLG8S4J +zRgx/sXulcR4yO6rAT0JC6MHDiap8GfbbEhqdHod5+fNNf7vH6bNC9JvHlX4Stz4vGX1jN8rgp9e +BWQnpEjqOD42JyNw9CmBv3+rAyogewBjby/2F89+v3EkwzzUYjKON0039UlzzLimLMrrQb1RpMJZ +bJYhwstcUXcL07co/8W6Nk19/RYyQ1wzxIS0PJG0JJKB5NXZ/f0bb5S9Lap5WVUWntgRv72995CU +o687Y26uJmq4825pwx30TXPl193Wz64LSdmyGmjhy6eeqRVQ4YMGq4u783q4fV8bG4Hzt5nryUDb +JlMwFpQV1+dkR7oinfHqsFR2dSlL2CWT07hpp33FVt2lOYncp0zi/VIyhsRXLCZ94zT3Tk/KW+Ut +HwqoJdN2VpkCTZ/W4ck48OTQeBWegC9MzohcrYvhQxajLRlOYiW4DdcnxpjSn31O3SFe+FWmgt3d +Zx2i8R7ZYWbY8nf3kdTSeYue6vjk1AOWxKcRDO7Wd/fiFCRSmO0KZrSJsev4R7F9QAnGRaPp2Ofc +i3JJF9Uotmm3XeZ5rBAx95YLxry2vphcWNkyVwx5y+d+356acjeGHuvAGmX50fLwW9WaPri92eg+ +a1AVfXR/Dcdjw5eulx644DSn5PfTPe2cpkZWrUo05QOlz3VOSCjsm2eEGo/keuNZyZKQft+CUy2y +OysmbqdL9msgy97EMlnmzCip6mVBJ1wryU+7fOi96WcSnlOo7jpciJWTk324Isk50/06bo/eMKKj +SeXMLiWZV0CYirHa0+seyXduA/KponahxAQrzg3yZ/8DrrSxdQplbmRzdHJlYW0KZW5kb2JqCjI2 +IDAgb2JqCjw8Ci9UeXBlIC9Gb250RGVzY3JpcHRvcgovRm9udE5hbWUgL01BWEhLWCtDTVI3Ci9G +bGFncyA0Ci9Gb250QkJveCBbLTI3IC0yNTAgMTEyMiA3NTBdCi9Bc2NlbnQgNjk0Ci9DYXBIZWln +aHQgNjgzCi9EZXNjZW50IC0xOTQKL0l0YWxpY0FuZ2xlIDAKL1N0ZW1WIDc5Ci9YSGVpZ2h0IDQz +MQovQ2hhclNldCAoL2VxdWFsL29uZS90d28pCi9Gb250RmlsZSAyNSAwIFIKPj4KZW5kb2JqCjI3 +IDAgb2JqCjw8Ci9MZW5ndGgxIDEzOTgKL0xlbmd0aDIgNjE3NwovTGVuZ3RoMyAwCi9MZW5ndGgg +NzEzNSAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNqNdAVUlO3aLt0o3eCg +gIQwDC0S0t1ICw7DAEPMwDB0dyOgdIm00iCIdDdICALSSHcpKPCPsff+v33OWuesWeud97nufu7r +etlZtfV4ZawQllBFBBzFC+LjFwfIaegZiwL4+QX5+PkFiNjZ9WEoB+hfmIjdAIp0gSHg4v/LQQ4J +BaPQmDwYhfbTQMABqq4OAJAgACQiDhIV5+cHCPDzP/yXIwIpDpAHu8GsABp8AFUEHOpCxC6HcPJE +wmxsUegy/3oFcEK4AKCHD0Uf/A4HyDhCkTAIGA7QAKNsoY7oihCwA0APAYFBUZ7/SMEpYYtCOYkD +ge7u7nxgRxc+BNJGiusBwB2GsgXoQl2gSDeoFeDXwABNsCP0z2R8ROwAfVuYyx9cD2GNcgcjoQA0 +4ACDQOEu6AhXuBUUCUAXB+ipqAO0nKDwP87qfxweAP7eDQDEB/p3ur/RvxLB4L+DwRAIwtEJDPeE +wW0A1jAHKEBLUZ0P5YF6AADDrX45gh1cEOh4sBsY5gC2RDv87hwMUJTRAYDRA/4dzwWChDmhXPhc +YA6/RgT+SoO+ZQW4lRzC0REKR7kQ/epPHoaEQtDX7gn8s1l7OMId7v33YA2DW1n/GsLK1Qn4BA5z +doWqyP91QUNE/8FsoCiAMP9DEREhMQDUGQD1gNgCf6XX93SC/jaCfsHoCXy9nRBOAGv0EFBfmDUU +/Ufk7QJ2gwJQSFeor/f/NvzzRAQCAaxgEBTAEmoDgxP9Jzsahlr/OaOXj4R5AEz50dwDAfh//f79 +9hRNLysE3MHzP+6/9wvUN3gip6/A82fif9tkZREeAG9ekDCA96EwCAASQD9ExQQAvv9Mow2G/W2D +/z+xKnBrBODhn27R1/Svjt3+EoDzrzi4AP/MpYlAsxYK4PwPyc34hfkh6Afo/5vqv0P+bwz/leX/ +RfL/bkjR1cHht5nzt/3/MIMdYQ6efx3QpHVFoQWggUDLAP7frobQP6LVgFrBXB3/26qCAqOFIAO3 +QZOZFyTExy/0B4e5KMI8oFbaMBTE9g9l/uBPfknNAQaHaiNcYL++Legofv7/sqH1BbFHfz9c0Lz8 +bYKi5fPPugpwCMLql84EhEUAYCQS7EnEj6aTgLAwwBuEFqQV1OM3kwFAPjgChQ4BoGf0BVgjkES/ +1iooCACioxDuf5aFtv2GhR4CgDA4Wjow9Dp+gf8oCnFFItHi+80NdEf/Ov9WOhTqAYUQzUwhII9C +7KpDmr5XyjC6834dxltcbomMN+6OEEZxTL/ytlXHT1cad5Z9ZlVGN5ii/bkkbGzKh5F7//uIh1l7 +ZuBCsnIOCkOhe1X2kDe3/+Kk3QbKYoVgsBkVTYlcJT9I0GG+/cwUx/T+C8Opn6GiHYIb5ev5Vy0u +GyYPdwCOgMJzMtZkRlSsTHbLDla0MSvbMmrA2IwsjgJpmuqqr/Jk9AorGhb3TbYphv7Cc9U0Lm1g +fr4vs6c7RfD4tVpnhUhZGCU9lZcqa/ZgYi89dUKmar0LBoes8LlcSVL8XfoCxzCOBWzH6kkQExNb +XBc9vyOgiMluUAYWgZmI1LqtOlrb2DQ2JMDRJ8H608sT7xW75PCtJqR+khYYC9wnCivjhGx5Fg0k +tKy3HEUq1X5dnE5yGwnYARuzZUXp9R7SDe51cMrlLBhFOx8q39LUuoxa2mhPi3dqlISNPL2jUy4s +P2YyqzenXk3ioyMyD43J/2R7sm4mR/+cgoJO7q7DkdH6dLrS0c4GZuCUrAeA/CU+045hBm7FfQyF +DdNlDYtLZY3jiMFOkRIeCOWy5axT9qKJZZ3CR/JW/yzcg0FzxBehtdqtkYFXJDFKlXpL/F/Mrs2B +X04+HisyMrxWz/RDAPHDHgkwQj5IRYjyre/JWrboxmBVeS98fROggFlNrEfVxVf7kBbHn2JgHhiL +7/7+mDFCaUyC4V7dVjbQdCJN6HNjkZ1Xs5fz0hjLAxoVvKSCusGg2Twar+0Kj+VrQkzLVN4fmsrP +KWhf0AwcUICLpMnluAuiyeb9MX5OFcOwaqeSHlzf3650TT3OuJEu4tzJ86SgTHhfszhxAWRz2g3N +cun+ghyNuKMnd4HgeE890TNcKWsyyNIThxe1pNq0ymhQcHabS7m/5vuZMziJMVW6Dbvj0TThnbj4 +Qrv3WNWvy1jFItPIO+rvc3ohpfhRfgzhj7FkRcevsmvLmqQqB1C4bw/LB43cJKcas4ZQ3KkQgvou +FvKj3pVlvNqW69e2DxbLQtNGPRN62G9bvr5ocF/+/tESEiDgTySDOhLO+7rm7HhPS1zVDm8+MSu8 +C3Jm8nHEv272lE1IuUnbLY+A99DAlJN+EyzauyBsDU1Wn4ydq2oUsPCw2YCEmRerf/JZsCAUlYXs +NgeCche77jtexNFNBnV/IixnNiTKrUEAAizVtFtL5qwHWGS0viQ8k/FgxBHwmhh0IGn/IvLqS4iH +r+aXqt7sndmhZIib6YZ52FEo3/FdrItrCI4b5D3bwr20m4ypg0fpYHI2wcvmsyKfWAqhFI+ls8Vm +kptBjDdERSHkJZyFsakvwY8he7pDc3ARJ9vP6Sb01l5ex9JRagOMxFQz9JdsEcYXdaoIYJTz8cAQ +WevLgzCcmPVhguN9vhOQ9VHrtw8hpFmJqlSy5BPu94XevwuUviLzlT8GpnH4k4T0mUgapCQnFa4M +v1kVrVfwl4B6+5h+AEE7LwF9KwFaYzorC4XvzN5EhOG9yEutURYW6poV2uShBMR6V07NpDjB1AEF +fnzMaae53x1K03WJ1SCFlYdpWkKcOaS9W08+OOLGN3ziviVK4KwG7HoT+4j4ECebnDOBlypMTFAc +U0RCAhjSldZhfCf74qpZvJoWp2ZHHn6miBK/hzsQ1v2wIYujLYdBdky8352ESD+vIcowbo+hB7fk +Al9BWFR9yW4l3XL8lbnPKkzaemyL/SVrGWhi7fui8f1D+XyaOwn00pMrt+qE38kPIHo+huH/uHHh +dBDUifJfw/eoN7IWhc8uKQWN3hl2ohpGhoBAcwZk1WIzUY5Zi218C6a+Et9WRa9IZxtj5fG41RdE +/QzyXXJyGqUAVa8q+2NjKnwDFgYyac8/y9+O7N/LOd/ARX1jvFkL7H2zM0cQutXVOrTLOmX0UETh +vsQWS9J2hyMBB9d+nGoL2bCeO40Qq+BI7e5e6fLwB6a3S9k1IzhDozWhYSkGDduqyV+dHwTHPSkz +6QyZN81Q/dSso0ZPGJPNrZ4iVrESWjORR/+YP7YyuY/6x/XsnA2+T1+lYtUz/eWv9gdJlM+TBVKz +xjMap2N7wg/L7kXdGWLJ6t/ysOx+Fmwc+JjwbX82HOGdPTlB07MG/ub2wwgWXxVqz5bVR1EJw8eV +xL8v93L5B462wp7L7SwOAql76+kaQ0YiZQpDrOQJyqfCBFscshCe73xMLqADzg+JDFURug9JtE2K +9RZVYsZkIohxGpWpD7jCvT0fjK1Vp9N9ubVV9zC1vDGRKWOiuGR881VQ6uYhxkRcgP48DWWZSw7O +Q1uEM1PWCwPwvZUfYCoY2XQvW/x1Ei02OxHUue0eN/MUq8D1vNBbDL20r3dLKT30NI4LlQatGPNO +g9p5Iqabbr18b8XAF8uPzNAwoJOdtdXx+tiC9Uj0bH0Pw2iEfhf7naVSZG8AVAhx6XF26Mr2dAEn +5n4ZdOpJiDCJ29scGMkTeKhAeoRZJ3Vlq6TIoVHwEO1yvOIeu/+s1Z3NjJpSRdbRx4sHDPi+vsVR +zgo0t4cZk0o9LfPDwIZLrLBLL5cWtfMeWWAFlzbtdSNTXwBNJie0V+31aMXQVeowc7IRitfXgG1T +sF7dM3/WpvDThFHeBXbzBLXQ/NQoUmndNHr2YPXEz/BoYJKEAVPQSqKTrDxcPg9GizKzCKssuPEL +bgWW5EQlDBXG7d/KKUz3FwBz5uAfGAjMNmkSCEvJn6p/t6IddE3XFA3FEfdj733uI3QtSaAL/LRo +tMDFhrmp8illhZcYQWuSaO+Xxa5AmiD+Y1iGjOIxVuHaKDsrx27OWEVyaJKgtVjOlMPlllXwTw3d +DN6tB/wlihdwLGbqTIz7xudK7mM7rvudeBbcsTeWayw1Rrjl7mWSMsbOUldmj2TzZrqHyGrjSblH +tV02xL9tE7Yn17e89bSP33hl9KwIpyclyoi5qTqfyzvF2dLV6gKRcYNvI0IdME6z3B3KZTwiJfKR +dceIdO2pj8GA4zk+rmWpJ8hMQPJ2/Gbp2w6n4ISPDG8fn07RrcsiwiQVmu44GdwR/sIuV2WY3tr5 +8dYRmX4JPKL2hNuZRECoUZ0j0Tc/TdhgCHDFhgXq4c/4qoSLyUJ9ar5jMpn8YK22yDPe9VtT4vaT +84JJOUX5gq/htxohDpg+EZpehNnqU7ss0XYsvDWdU+6tUhtaz+7e746463QhmUMcS7m61uDpxfpq +IheTRKqTaRNhf26vD5UZNuPdP3hCEUeL599PTedKLieSaplU3bB858BhqI0O/A0TN9zpA30FaetS +CjEza/XTqLPUKuBPWIP9tnPHk5QbgbWC0dy9961dzu/7KCIqopWKg9KUWoTJcCVkGs52plXeajou ++BlWrwa9NgumQ+reZZbJLb9ef0pKU2r2Ez7fKAAlZ+U47tukiNipi2T/aAaTb7wKOIk+GjzP8J5A +sq3HHt8um4vOFA6MkB6c2mRQNU6By+RjSxM85xH25MCvjVnGURYBfWDDY/J6HX0J9BK3b+A9p6si +pRGRsjYEqKwJ6Alnh4o0M91kk9o3BSSsyd85Fvn8Ol2SBqkAkkb1d2xP859ZqONF3hbKwuQm47lm +1gmX0dnf5mcUwPaZS45rZHxT91SFxmg5aO7txqdokoVMbsKX3RY4uouRecbsWLWawv0r4SK7Exa7 +LYXWSdil4UhTeic9ZdCXHZ6RoTFCA5eKtwFd+W3fyjZpdIDdnlCn4MkIngmAyZd44Vh+k/qloFPR +JRd7vEJqTG9QtfBUxGwiiUWCE0ZPbY7XMeF7WtvtI6biLk2SsuwXlMtjpJ32k3Kp8yylqjdMVVvE +JJvqNkxLmsNaVxrbZgI1TVn0hCs2LIM8Eom+XdKrdj6FBI9WMrW87jC11Zq/tO3uWWmLTitIGBb8 +3MgmkioWpehnI21BLXZ+6X165mr72YN9XChhxSegFZ9Fdn49/BRvWQbWbvd+gl1HzLT7MuqmbliU +pC7KZkffe1w4xsnvuT1KiWrOfTKC8lhA660g4TF9waY1XaIR/bt3GmeLiz/wEhS08jFLA8jjimuI +wxditOdwX7wNilbGtHx0X5j50+FZxYcJyr1JEuEOGY3re52LH7EqPuph6tl2LKfmVSeWAtyiG515 +5eGjTCZ5j77WzNYFrH4ffaPxCYcloOmVkcUVWbXKWHWBllN6gXBbLriYNEx2h73n88PiH3lPt01Y +F6g/zz4CuF35v8omx6kMVIsWotd2xLccx/pIwz5X2O2Nx8VM6FKbsuLcoPyy7Aw7OvdRsN1LtzG6 +fu/9b7uL3nObvOH2PMpaZAe4lYtXhsOFN1HHWkPiSgI0B54xUuXOpZy48wuHDxmE8HDHmTntW3Bl +Ty6jzOsRuuPnewtDpkC/KiY5f4F5kurjTew9dntCjbrgJe+4Oqfgzxh0TCGln/w3hB9D3etjmKQv +mJu+Zcxo+byvfrQW2JLc1hu25Kk4t7sNOnxDeqgJnGY8ti00sgvacbB1f8Ggr1G3Ut9hTs2clTZg +3nty7AjFUn7Vloq1iQkO/fzY4cndUVaTz332nSFSvDSSjPivVPopVdd5dWW4tR/Xs7q2Rh7W7XEN +zHVOueE8hb7Ie3d1xeb1wyI0tTW+/JHhzwJkaeZ1eI3Ed+pBBRLCbnF1SVeafXnCdZXFM/6WpKrA +n1tyd3oy17xme1s3306Jjh77x8x28rut6jKYPmuoZYn5+W22myuWp1Hc5/J5CZwpMBlFUM3oEuc5 +ig0q8nMl8tHLzo007iOAPdua8UIqdnrbKSmYGypHvxEN5My38Y3XGJ+ZpDHgra7g/n5h5Uw1UmW6 +HdVpPkoaMR1BttaEAZzxpKXtSiCdu6+fWAWrlDAuhgPNZxmfDdcxyYeU7PD0dRyoeIRffl59kRjZ +EsOpdbDIhh0nE2akKqS/YZzx5i4HH1Mws7H3uTMyzK65Ykxu9h6So5Vh5VZR6Ad1xI5KKWOTvEbm +KZBew92M9z0R5sIZTNErXq19yRwMhpx+B5s+dUapawXHxD6iAjERbKeVS4rzkTF/49A4gGOhJltD +IqfhwcWiUbEt0T/5vt0uZOHCoPGyyAil+9EuVdxcI/7TM1GdHLYNVXnHMK944+Gkc5b0oA6moVl8 +tHENeZVOdTzIaGNYs0qplijBck121Pz6ZvtJV5kWknnzK28U7/eD1yiibEgP+/NAQ2xdaVFtHYrg +pq9CV2nvdHGjCTUuRILym2dYJr0wQumCaybNcTil21feadKrwijdww5+VsSNA9/prZ8trlnjZhEc +T5MVlxPtkvutJ5zdz6HyWapP0hS+S3ngR9IHEKCnTnx3rBwYRs09c5G7GveVAEjiB7yx7JHsABYy +2IGk/Kjw5G3GOAcj6QaHzAueQQ/dXEhYaNhQR5IK41mvz+a/PYKGzE3y9Zj95B3AqFIaPiKxb2Pl +xhZ2I9s8ySag+jDTSqmZn6/dbVKtZv/T3B37HIILnF+W3a9nvbyYoV6AZCIyiabT7eUeimh0lH2s +DW0/BAWUe9HzdXRcRj87k7vMue7QsLfWeUhP1mDpq84hlR+E6xtzEOgRbI7ZVBNoWQmO6/+MPZbG +v2ugpSweXW8eY6ea2x5F0ipqP+aekBxmELRDJS85dVF0hxTzW4fK4Buf7pGQLrL6/ukQ2S6fi6Pw +Dz+6MQtekr0g7TwtrEiBbqt+2Wjgoc3aoReNDXKIN8nVGD8pmK0RlRFq13+hnelUmZmtMVLyRLet +MrkLP8B6NwJ/jqcxKaElBvQ1qbWXu9F95G3QoOetYfdp63s4RdUjYVzLJL768NTybDZ1o9VebX/M +FuMX2Nlid4L5HZ9+5I2CYXPRQsP1BGIQRRkNxg6vM1xNfW7x49iZtXyRKEv8kRUhYVqNi5G2+5jU +/ZirS6wz8BCR2fqFPIBwtpWTa0+Zy0Zys9178fvYu5yGp9IKfvr+daWcZ9dHM0YRFPdro57pX7au +LA+kFOfd7STsk3lMDxYL0GPT21jmXX2S39TJTrQTCWNda7vM0w428EwxoaIi38J1maJMdCXXXW6L +8r06uJjhpGRGxX+g3y6UTo6AWWx+AdPXVPhEhZQRf7Ktow2d855tKD9TvXVSzfu5ZvfZC48qA/mf +pRxYac+cDoiZeE4AJ7e6qlYY7LR4NYVLL3AxDaoUlVpWs5qTWnevi5KiuP3V5n505YWb9dqv8VXu +nZEuMzvkG9XoQVZ9kNfPTZ+SDafu/9DhCC+NZp0Fv+4zKkeVZZ41H5ki09WYdAMbLITqZrp1x4m9 +816w3vnILkgxT8NHG+y7SDTNKzvAEzLUuZB2s/ryRw9s9iqQxb/T71Nwg4SG6LuAmbA+h5cde5Oj +coIuaxgu4kO+2b7NXYJDXJ5wvOf6b8SEGimxS9f8BLv1RciKi4puO5xnTtwSQNQ1sObwVBD1WDjH +cJB31muR2WQMd7ePbWmH1xJeMzESkOSwyBqUZrY/XLJLpLl1+SIAJspQsifMIhZAlYGUXetKMpmT +8KytbdwKT6KQSrq2HQb476sdb3A/OAfa1tRo2623eK89YwgmbpWXO3W3oLSlPX0PrHQShCoDVTJl +3vRzwQ477O/9eP+E+Cn2szIOBN0h55C9YLMUHnjSoSkGN5Vl9/uYZGSQGk4z0SJwX/BxncxHnxos +JZ4FfdnorSzd9cPpYFJBrakjmVXZ9w4dY97rLg53KUeOQN9EAasj9gPjDBYJ0LUxXoqbeJ0wzVJF +nYyAT/SYGUQv95MPY7lhLV2SW/VYwV8UxXa5q3OpltglNcoYHbHC2kyLhnOfYonWKwcFA7cm+vDe +MkFflgGT6iEJLxRWkVhmQigFqWlqFYFGsfkafVLrz1Mn4erE3+Re3BuzTSdylz0huN391ioNOfrZ +53utdxZGn/5X4VwdxLxAy17LTpa0dtGGIzTiY0j2HB/v4Gjp16cO1T2t/cdlYrk3QukY1FTXEiOq +WDu8SkVjXY+9CFqPmkYGSw/PzAMQkOzHK0GIIHKT49ra2i/wu57IrfZNmxHozHJeR6nlBFs/VxGF +QHZpgU6z2FwWiy5D9NeDkz55Kzmj8QyiWsXubWWv4RKq/P0lguG8Vfxw/zPriCp2bVUd8tK5YKYX +z1l7TeYwIy9IGfgZur2+yFgwHAOSCd1PMG73MxAZksvcy7Wa3KgyWzOXyoeIdzYl6J1OEpTqYnFu +XR/h7G3F7FOwxaF8jyRYiJRxLwERhSN4nvXGUtZ8yYe9ZIlHJbq9K6GlVB/u2JUQ+r6h5iGL1y4/ +slPgywsorCma/G70nv5V6aCNmJoSlcU+fw1r4BTi1KvQMPgnt9BTjw7m3a43G5jtNYQ7M4KOR80i +r78BkJt2uQ3DqRuubm+kHNQN3QuYtDWds74qLcS6CpwSXr/cv3F6NB/v1UWiUmNbkC+5q9KmWkPM +TDR/ovszsy1z3QiXlqeOkQYjq5w9llyxa0oXdOpVSoRHMC7fJ45Fu2JTHX3sXWl87CsYdEMhdbkv +cjC/QULco5ZyqGN75kBS9Ln75kUhS5ZpUWNXGH3kZg6fuTnEl5qJz6XobQHzkvlUppLUjfS3quv9 +QUPVodUzI+gp8VjyOE6MN/fxDrzHg3rca7/YrS2Ztmpk/bVQn+fcW5QOcOn4xuPZfqu90PMNrJns +fjdnNYuVrLYLCd6lsjn7995B6wF5jwJ4d7qwC0usZ1OJ4SOtykPJjJDjp0g7wHWY5qvn0qvKLG4O +4cZwm2Txo3JDYte7FAv27GcMx4xXiiZG+CQlmXrzSeCrIW/E6RflhZCSLRebOzgnNe371FiDpz7b +UW6+jq9FTXvOVHipme2j97hGi7RsEm1pYeANZBo5nHLAkx93J00trXTsPE1rao03LeWHAguJzpLC +MVzrqGvyAs5BZiNPaBIgcmK+pSiahN3NjSNZ5UHsSCtCphulEDu7QZFFam2UJZjrFZ89FLPQYf5q +t9ivNzKKypGuJj9lAPJgvZcT4LrXtCqafSYUvb2oHB9Xf+g1mbbZnlTQpRpi/J2hYu/J0ZNH3Xw1 +C5ZRwS4RsLEaijXq6p2Y9cAtCfq+hhnVV56zBWZ06gJLofeDBnldt0SbYaIzw+XUdaW5Y2NnwQYs +hPoLo3deRHY5V+ySBult1zIE1BU3jdy4gNjUe6j9Km7RLrxuiwzE0SHGvHUsg7U4fs/v05laDzuX +ktiap2gOe9zVDX76yAWxLIdSBPkw17nyvOEiJ7/Zk31dFswPPY/pMiKVuHe63v1Qmc87P1fElXAy +e7BV/3k6DRzrG0/Xzsnd737Zo5PD7MCvD+DvtSnY5pkxjL5diMUOugmLn6CNTv8f8aXekwplbmRz +dHJlYW0KZW5kb2JqCjI4IDAgb2JqCjw8Ci9UeXBlIC9Gb250RGVzY3JpcHRvcgovRm9udE5hbWUg +L1RWVUNURStDTVNZNwovRmxhZ3MgNAovRm9udEJCb3ggWy0xNSAtOTUxIDEyNTEgNzgyXQovQXNj +ZW50IDc1MAovQ2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAtMTQKL1N0 +ZW1WIDQ5Ci9YSGVpZ2h0IDQzMQovQ2hhclNldCAoL2Fycm93cmlnaHQvaW5maW5pdHkpCi9Gb250 +RmlsZSAyNyAwIFIKPj4KZW5kb2JqCjI5IDAgb2JqCjw8Ci9MZW5ndGggNDk0ICAgICAgIAovRmls +dGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNptk01vozAQhu/8Cu8hUnqgmI98VQiJxEHKYduq +iVa9JvYkRQoGGZA2/349HkjVVQ5Bj2feGb8Dk8mv972fq/oEfvzM2Qe0dW8k+Jvfx8abTEQt+wp0 +9wqgQI3Z9oW9m1ruoWPTzU7sdNk9WfFOy2uvYFQ9Fq3hUupvCd7Dpgf49GUFf0Pun/ry2pXa5yg+ +lN3Vih7mmQ2yn0Hmiv6Aactav7DwmXNuA1utNnWFY7ReMFhhwWjuXGplBj/shO68MGKqlN1wck9Z +2feBxftb20G10+faS1MWfNhk25mb8/jkBW9GgSn1hU1/WrOpfd80V0AbjHtZxhScbUc7/+uxAhY8 +nPGuOdwaYJE7h+RL1gra5ijBHPUFvJTzjKVFkXmg1X+5oeJ0HqRiYaViaR88zmeuYszFd638Ohov +jV3X5XadWQ4dF3PkiOJb5JjiK+SEmCPPiF3tnPQF8oLiOfKSOEReEW+Qc+IYeU3s7toQR8iCWCBv +iRPkgu5Cn8ngHzXJ4H+JPPjHu5LB/8LyCmujKERvOdZyHuEswnG8Qj8idBqO/UVEcewpYmKcVyTE +6FnM6E27PnNi12dF7Gpx3iiM5sPXcG8fvyTu3X1JZG+M3R+3nG4tcCFKDff9beoGq9zPLf74T8PT +W+H9AwRMHIcKZW5kc3RyZWFtCmVuZG9iago5IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBl +IC9UeXBlMQovQmFzZUZvbnQgL1lRSlNESitDTUVYMTAKL0ZvbnREZXNjcmlwdG9yIDE4IDAgUgov +Rmlyc3RDaGFyIDg4Ci9MYXN0Q2hhciA4OAovV2lkdGhzIDExIDAgUgovVG9Vbmljb2RlIDI5IDAg +Ugo+PgplbmRvYmoKMzAgMCBvYmoKPDwKL0xlbmd0aCA2OTYgICAgICAgCi9GaWx0ZXIgL0ZsYXRl +RGVjb2RlCj4+CnN0cmVhbQp42m1UTW/iMBC951d4D5XaA8UfJIEKIdkJkThsW5VqtVdITDcSSVAI +h/779RsTrFY9EE2e38y88Qtz9+t1O9FVt7cT9cjZmz13l760k+z37hTd3eVdeWlsOzxbW9lqPD0/ +sde+K7d2YPfZJt+09fDgyJu2PF4qO7J+Jhn7UbeBgj7s/t3+nZRNUws+2V/q41C3Ew7yez0cHenH +c+ZA9hVklPTH9ue6a5+YeOScO2DdVlnXYIxzNL1KYdNR3KFuq/6qh+2hLhKSVXU5XN/oWTbuPpC8 +/TwPttm0hy5aLtn0zR2eh/6TND5E05e+sn3dfrD7r9Lc0fZyOh0tZDAerVassgdX0c3/vGssm/44 +443z/nmyTNK78LrKrrLn0660/a79sNGS8xVbFsUqsm317Uxyn7I/jNzUcfkcD6XjlQMM4jUBRjhA +oJqIPZAAQIrwKSYHsACgCcg4ANQQuQcUgMLFUnggdYBEulwQajIASJeGAKqh0FaBwbkCMEN6TF34 +DMJisGN0kUkCHQkYqWckYGh00YswnMZcRoThjAIwD8MZpBsThnPqHJCH4QxqZDwMl0kA6jacu/Xx +emfz8brLf7v+6gxXC6RxyJCSoyuXHp8j9pUWBvHMx2vE3gINDS6JYqpznY9y6RaFpJoF4QXmFsTn +hmLvbY5Y+r6ES983x7VI3zdHHen7FoT7vm5iF6c+Jg5qytiQteR1nIGvvBkS+pXxMdxWmfeV4tzj +BeK1x4lPdSTVn3F/V+gbUy8lMXtc+Bh4QhwhgKfUSyhoSKmXVNCW5p6Du0qpDs+Bz692Atfc68E9 +axH80jL4pVXwS8+CXzoOfukk+KXT4JfWwS+dB7+MDH6ZRfArEze/6MuiLwn/bOyh29IoL33v9gkt +K1oTWBB1a2/77NSdkEU/WoTj5sXbSxH9B3Htg8QKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8 +Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovQmFzZUZvbnQgL0JIR1BLQytDTU1JMTAKL0Zv +bnREZXNjcmlwdG9yIDIwIDAgUgovRmlyc3RDaGFyIDI1Ci9MYXN0Q2hhciAxMDcKL1dpZHRocyAx +NiAwIFIKL1RvVW5pY29kZSAzMCAwIFIKPj4KZW5kb2JqCjMxIDAgb2JqCjw8Ci9MZW5ndGggNjk1 +ICAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJlYW0KeNptVE1v4jAQvedXeA+V2gPF +HySBCiHZCZE4bFuVarVXSEw3EklQCIf++/UbE6xWPRBNnt/MvPELc/frdTvRVbe3E/XI2Zs9d5e+ +tJPs9+4U3d3lXXlpbDs8W1vZajw9P7HXviu3dmD32SbftPXw4MibtjxeKjuyfiYZ+1G3gYI+7P7d +/p2UTVOnk/2lPg51O+HgvtfD0XF+OmYOY18wRil/bH+uu/aJiUfOuQPWbZV1DWY4R9OrDjYdlR3q +tuqvYtge0iIhWVWXw/WNnmXjLgPJ28/zYJtNe+ii5ZJN39zheeg/SeFDNH3pK9vX7Qe7/6LMnWwv +p9PRQgXj0WrFKntwBd3sz7vGsulPA94o758nyyS9C6+q7Cp7Pu1K2+/aDxstOV+xZVGsIttW384k +9yn7w8hNHZfP8VA6XjnAIF4TYIQDBKqJ2AMJAKQIn2JyAAsAmoCMA0ANkXtAAShcLIUHUgdIpMsF +oSYDgHRpCKAaCm0VGJwrADOkx9SFzyAsBjtGF5kk0JGAkXpGAoZGF70Iw2nMZUQYzigA8zCcQbox +YTinzgF5GM6gRsbDcJkEoG7DuVsfr3c2H6+7/Lfrr85wtUAahwwpObpy6fE5Yl9pYRDPfLxG7C3Q +0OCSKKY61/kol25RSKpZEF5gbkF8bij23uaIpe9LuPR9c1yL9H1z1JG+b0G47+smdnHqY+KgpowN +WUtexxn4ypshoV8ZH8NtlXlfKc49XiBee5z4VEdS/Rn3d4W+MfVSErPHhY+BJ8QRAnhKvYSChpR6 +SQVtae45uKuU6vAc+PxqJ3DNvR7csxbBLy2DX1oFv/Qs+KXj4JdOgl86DX5pHfzSefDLyOCXWQS/ +MnHzi74s+pLwz8YWuu2M8tL3bp3QqqI1gQVRt/a2zU7dCVn0ozU4Ll28vRTRf7vhgvIKZW5kc3Ry +ZWFtCmVuZG9iago3IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovQmFzZUZv +bnQgL1ZFSUdWVCtDTU1JNwovRm9udERlc2NyaXB0b3IgMjIgMCBSCi9GaXJzdENoYXIgMTA3Ci9M +YXN0Q2hhciAxMTAKL1dpZHRocyAxMyAwIFIKL1RvVW5pY29kZSAzMSAwIFIKPj4KZW5kb2JqCjMy +IDAgb2JqCjw8Ci9MZW5ndGggNzM5ICAgICAgIAovRmlsdGVyIC9GbGF0ZURlY29kZQo+PgpzdHJl +YW0KeNptVU1v4jAUvOdXeA+V2gPFdkgCVYRk50PisG1VqtVeITHdSJCgEA799+vxI3jZ9gAaP4+f +Z+zB3P14XU9U3W3NJHzk7M2cunNfmUn2c3MM7u7yrjofTDs8G1Obepw9PbHXvqvWZmD32Spftc3w +YMmrttqfazOyvidp89G0noJ92P27+T2pDr3gk+252Q9NO+HgvjfD3nK+m2a2xm5qzC35ZfpT07VP +TDxyzm2haOusO8DDKZhedLDpqGzXtHV/EcO2kBYIyeqmGi4j910d7GFg8frzNJjDqt11QZqy6Zud +PA39p1P4EExf+tr0TfvB7m+U2Zn1+XjcG6hgPFguWW12tqH1/rw5GDb9zuCV8v55NEy6sSBVVVeb +03FTmX7Tfpgg5XzJ0rJcBqat/5tLaMV2N1ITS+VzfIUqWgapDC2WMQrcYlvAZKipMLeFsLQ4ooLF +QRoLixPlChYHaYLJJEMjLtBDoYdaXHexukYFyXxUVP3Z9BftPFxgGUdjKXkMLKkOBTwkrIFnhAvg +iHbgwDFh1+eys1sLnVJI15NMxDE+GGd+vMA49+MM4+If/sgpb2vgCedBhDgLAQ/2JBNgSVzoE84D +1zNg50FmjuM8yBxaBV2DwiGLhOoKeE5rHcd547nj0B0U8CKcNxHBvyBfpeOTp8xxCuJIYPLh9pWC +bhv6paRrzIETwvAdUk8FTkg9Q3BCOiMNPdElAjiTiDgROFFBfqEhKskXesac+NCQ5FQHPyF+jj4J +6XR3qTjpxHkq4XOjpM+NCn1u1MznRkU+Nyr2uVGJz41SPjeKsqKgR128O37u86SK2zyp8jZPmt/m +SYuvedLya5506POkZz5POvJ50rHPk058nvTc50kvfJ608nnS2udJZz5POvd50oXPky59njLu85QJ +n6dM+jxls+uduV+++6XjbcI7en31qnPf2wfRPbbuocMT17Tm+h4fuyNWuY97yMe/DYxeyuAv8fOo +UAplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKPDwKL1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUx +Ci9CYXNlRm9udCAvTEhDQU5BK0NNUjEwCi9Gb250RGVzY3JpcHRvciAyNCAwIFIKL0ZpcnN0Q2hh +ciA0OQovTGFzdENoYXIgMTA5Ci9XaWR0aHMgMTQgMCBSCi9Ub1VuaWNvZGUgMzIgMCBSCj4+CmVu +ZG9iagozMyAwIG9iago8PAovTGVuZ3RoIDc0MCAgICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUK +Pj4Kc3RyZWFtCnjabVVNb+IwFLznV3gPldoDxXZIDFWEZOdD4rDbqlSrvUJiupEgiUI49N+v33sJ +LtseQOPn8fOMPZi7Hy/bma7avZ2Fj5y92nN76Us7S3/uuuDuLmvLy8k2wy9rK1tNs+cn9tK35dYO +7D7dZJumHh4cedOUx0tlJ9b3JGPf68ZTYB92/2b/zMpTr2b7S30c6mbGgfpWD0dH+WaWuRL7XGK4 +4Lftz3XbPDHxyDl3hbyp0vYEBs7BfBTB5pOsQ91U/aiE7UFXICSr6nIYR/hdntxJwOLtx3mwp01z +aIMkYfNXN3ke+g/U9xDMn/vK9nXzzu4/C3MT20vXHS2IYDxYr1llD66f8/1rd7Js/o27K+Pto7NM +4liQprKt7LnblbbfNe82SDhfs6Qo1oFtqv/mFK3YHyaqclS+hK9QR+sgkaHDMoYCd9gVYDI0VFi6 +Qlg4HFHB4SCJhcNKY8HhIFEwqVJoxAX00NBDr667OF2TArWcFJV/d/2onYcrWMahsZQ8BiypDgp4 +SNgAXhDOAUe0AwccE8Y+4864FnRKIbEnmYhj+MA49eMVjDM/TmGcf+JPnOK2BjyBHkQIZyHAgztJ +BVgSF/QJ9MDNAjB6kCly0IPMQKuga9BwyEJRXQNe0lrkoDeeIYfuIAcvAr2JCPwL8lUgnzylyMmJ +IwGTD9xXCrpt0C8lXWMGWBEG3yH11MAJqWcInJDOyICeaIwAnElEnAg4UU5+QUNUkC/oGXPigwaV +UR34ivgZ9FGkE+9Sc9IJ56mFz42WPjc69LnRC58bHfnc6NjnRiufG619bjRlRYMePXpHfubzpPPb +POniNk+G3+bJiK95MvJrnkzo82QWPk8m8nkysc+TUT5PZunzZFY+T0b7PBnj82RSnyeT+TyZ3OfJ +FD5PKfd5SoXPUyp9ntLF9c7wl4+/dHib4BW9Pnrlpe/de4hPLT508MTVjb2+xl3bwSr84DM+/WPA +6LkI/gGkQ6d+CmVuZHN0cmVhbQplbmRvYmoKNSAwIG9iago8PAovVHlwZSAvRm9udAovU3VidHlw +ZSAvVHlwZTEKL0Jhc2VGb250IC9NQVhIS1grQ01SNwovRm9udERlc2NyaXB0b3IgMjYgMCBSCi9G +aXJzdENoYXIgNDkKL0xhc3RDaGFyIDYxCi9XaWR0aHMgMTUgMCBSCi9Ub1VuaWNvZGUgMzMgMCBS +Cj4+CmVuZG9iagozNCAwIG9iago8PAovTGVuZ3RoIDkwMCAgICAgICAKL0ZpbHRlciAvRmxhdGVE +ZWNvZGUKPj4Kc3RyZWFtCnjabVVNb9s6ELzrV7CHAOnBNT8kUi4MA6RkAzn0A03w8K6OxOQJiGVD +tg/594+za5ttkUOM1XC5Ozschneffj7OfL9/jjPzRYpf8bg/T12cNd+2h+Lurt13510cT99j7GN/ +XT1+FT+nffcYT+K+eWgfxuH0OSU/jN3buY/XrI+TQnwdxpyCPuL+Kf4763bHdzd7Pg9vp2GcSeQ+ +Dae3lPPRskiY+AMTtOWfOB2H/fhVqC9SygSsx77Z7zDDsZhfeIj5ldnLMPbThYx4BrVCadEP3eny +Rb/dLomBzY/vx1PcPYwv+2K5FPNfafF4mt6J4edi/mPq4zSMr+L+D2Zp5fF8OLxFsBCyWK1EH19S +wTT79+0uivlHA95Snt4PUWj6Vsyq2/fxeNh2cdqOr7FYSrkSy81mVcSx/2tNO97y/HLNrVOubNKP +1otqVSyVTrEyBNQWQAmgIsCWACwAB8D7DQAPIPAWDQD1VMtbPIA1gA0BDoCmBqis1cIAoAaWAQeA +6hEx1SLDoIbhGh48SpXiCr2lTHGxrJBRcYZGDQshrOItIGYxnKXeRoKHBQVbMVADgB52AcCtAThw +co4FQheHRYe2WmqZAA/A+yyhx+SeedAsAQ2CzZoG1At11jSgRvBZ04AaYZ01DajXyKxpg7kafdM0 +Hfb1VGt1PeXuv+10MYTWCnWkIsECeElNcUsxH7miuCR8QzGffAOW0vJeyCBZEoWjkXTUsm0RE+dq +jTHlhlUiTzCHEjmKj8SijmIVTIN4wTnQXUv2AhTWimPU0Zpj7NXMoSQD1WwVyl9wTPmeY8pveS+4 +6TXHC8R8VgrcDPWVBnsN80zuTTErTSYxrJUMiMnEVSCLVhxTHdLKGMrnGSW4GZ5RUj6b12N2w/dH +wkCGba8IZ84K/EvWxCCn4nwNK1R8fzVmqfja1eBs+bwceFrHMbhZ7utQ317qoKblvmRiy31biteU +X1E+a1ViFnfxFTg40sobmNddtIJ/HGulwcGVfCfgJce+osvvataB8gN7DGfkiI+1lNNyjHNxa47p +Om44Bp/6N894SXX4hqrsf6+z/73J/vdl9r+vsv+9zf73Lvvf19n/QWb/B5X9H3T2fzDZ/6HM/g8h ++z802f+NybM05W1GuuV0q/HPHQ/R7dnoztOUXhR6reilwBsxjPH2oB32B+yiP3oJr+8uvn5siv8B +UH3pTAplbmRzdHJlYW0KZW5kb2JqCjggMCBvYmoKPDwKL1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5 +cGUxCi9CYXNlRm9udCAvVFZVQ1RFK0NNU1k3Ci9Gb250RGVzY3JpcHRvciAyOCAwIFIKL0ZpcnN0 +Q2hhciAzMwovTGFzdENoYXIgNDkKL1dpZHRocyAxMiAwIFIKL1RvVW5pY29kZSAzNCAwIFIKPj4K +ZW5kb2JqCjEwIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovQ291bnQgMQovS2lkcyBbMiAwIFJdCj4+ +CmVuZG9iagozNSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMTAgMCBSCj4+CmVuZG9i +agozNiAwIG9iago8PAovUHJvZHVjZXIgKE1pS1RlWCBwZGZUZVgtMS40MC4yMykKL0NyZWF0b3Ig +KFRlWCkKL0NyZWF0aW9uRGF0ZSAoRDoyMDIyMDMwNTIwMzE0NiswMScwMCcpCi9Nb2REYXRlIChE +OjIwMjIwMzA1MjAzMTQ2KzAxJzAwJykKL1RyYXBwZWQgL0ZhbHNlCi9QVEVYLkZ1bGxiYW5uZXIg +KFRoaXMgaXMgTWlLVGVYLXBkZlRlWCA0LjguMCAoMS40MC4yMykpCj4+CmVuZG9iagp4cmVmCjAg +MzcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwNDk4IDAwMDAwIG4gCjAwMDAwMDAzODYgMDAw +MDAgbiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDUwOTQ4IDAwMDAwIG4gCjAwMDAwNTM4MzUg +MDAwMDAgbiAKMDAwMDA1Mjg1OCAwMDAwMCBuIAowMDAwMDUxODgxIDAwMDAwIG4gCjAwMDAwNTQ5 +NzAgMDAwMDAgbiAKMDAwMDA1MDAxNSAwMDAwMCBuIAowMDAwMDU1MTI2IDAwMDAwIG4gCjAwMDAw +MDA2MjEgMDAwMDAgbiAKMDAwMDAwMDY0NiAwMDAwMCBuIAowMDAwMDAwNzc2IDAwMDAwIG4gCjAw +MDAwMDA4MTkgMDAwMDAgbiAKMDAwMDAwMTE2MiAwMDAwMCBuIAowMDAwMDAxMjU2IDAwMDAwIG4g +CjAwMDAwMDE3MjYgMDAwMDAgbiAKMDAwMDAwODc3NCAwMDAwMCBuIAowMDAwMDA5MDA1IDAwMDAw +IG4gCjAwMDAwMTYzNzAgMDAwMDAgbiAKMDAwMDAxNjU5MyAwMDAwMCBuIAowMDAwMDI0MDA1IDAw +MDAwIG4gCjAwMDAwMjQyMjUgMDAwMDAgbiAKMDAwMDAzNDIzMiAwMDAwMCBuIAowMDAwMDM0NDY3 +IDAwMDAwIG4gCjAwMDAwNDE3MjIgMDAwMDAgbiAKMDAwMDA0MTk1MCAwMDAwMCBuIAowMDAwMDQ5 +MjA0IDAwMDAwIG4gCjAwMDAwNDk0NDEgMDAwMDAgbiAKMDAwMDA1MDE3MiAwMDAwMCBuIAowMDAw +MDUxMTA2IDAwMDAwIG4gCjAwMDAwNTIwMzkgMDAwMDAgbiAKMDAwMDA1MzAxNSAwMDAwMCBuIAow +MDAwMDUzOTkwIDAwMDAwIG4gCjAwMDAwNTUxODQgMDAwMDAgbiAKMDAwMDA1NTIzNSAwMDAwMCBu +IAp0cmFpbGVyCjw8IC9TaXplIDM3Ci9Sb290IDM1IDAgUgovSW5mbyAzNiAwIFIKL0lEIFs8OURD +MTZFMkQ3NUM2MkNBQTM5OTYwOUQ5NTYyODdBNjM+IDw5REMxNkUyRDc1QzYyQ0FBMzk5NjA5RDk1 +NjI4N0E2Mz5dID4+CnN0YXJ0eHJlZgo1NTQ1NAolJUVPRgo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.log" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.log + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KSAocHJlbG9hZGVkIGZvcm1hdD1wZGZsYXRleCAyMDIxLjguMjMpICA1IE1BUiAyMDIyIDIw +OjMxCmVudGVyaW5nIGV4dGVuZGVkIG1vZGUKKipDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1RlbXAvaW5rdG1wZHNyeG1yajcvaW5wdXQudGV4CihDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xv +Y2FsL1RlbXAvaW5rdG1wZHNyeG1yajcvaW5wdXQudGV4CkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDEKTDMgcHJvZ3JhbW1pbmcgbGF5ZXIgPDIwMjEtMDctMTI+CihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYmFzZVxtaW5pbWFs +LmNscwpEb2N1bWVudCBDbGFzczogbWluaW1hbCAyMDAxLzA1LzI1IFN0YW5kYXJkIExhVGVYIG1p +bmltYWwgY2xhc3MKKSAoQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zbWF0aC5zdHkKUGFja2FnZTogYW1zbWF0aCAyMDIxLzA0 +LzIwIHYyLjE3aiBBTVMgbWF0aCBmZWF0dXJlcwpcQG1hdGhtYXJnaW49XHNraXA0NwoKRm9yIGFk +ZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gYW1zbWF0aCwgdXNlIHRoZSBgPycgb3B0aW9uLgooQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21h +dGhcYW1zdGV4dC5zdHkKUGFja2FnZTogYW1zdGV4dCAyMDAwLzA2LzI5IHYyLjAxIEFNUyB0ZXh0 +CgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2Ftc21hdGhcYW1zZ2VuLnN0eQpGaWxlOiBhbXNnZW4uc3R5IDE5OTkvMTEvMzAgdjIuMCBnZW5l +cmljIGZ1bmN0aW9ucwpcQGVtcHR5dG9rcz1cdG9rczE2ClxleEA9XGRpbWVuMTM4CikpCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0 +aFxhbXNic3kuc3R5ClBhY2thZ2U6IGFtc2JzeSAxOTk5LzExLzI5IHYxLjJkIEJvbGQgU3ltYm9s +cwpccG1icmFpc2VAPVxkaW1lbjEzOQopCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFBy +b2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNvcG4uc3R5ClBhY2thZ2U6IGFtc29w +biAyMDE2LzAzLzA4IHYyLjAyIG9wZXJhdG9yIG5hbWVzCikKXGluZkBiYWQ9XGNvdW50MTgyCkxh +VGVYIEluZm86IFJlZGVmaW5pbmcgXGZyYWMgb24gaW5wdXQgbGluZSAyMzQuClx1cHJvb3RAPVxj +b3VudDE4MwpcbGVmdHJvb3RAPVxjb3VudDE4NApMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxvdmVy +bGluZSBvbiBpbnB1dCBsaW5lIDM5OS4KXGNsYXNzbnVtQD1cY291bnQxODUKXERPVFNDQVNFQD1c +Y291bnQxODYKTGFUZVggSW5mbzogUmVkZWZpbmluZyBcbGRvdHMgb24gaW5wdXQgbGluZSA0OTYu +CkxhVGVYIEluZm86IFJlZGVmaW5pbmcgXGRvdHMgb24gaW5wdXQgbGluZSA0OTkuCkxhVGVYIElu +Zm86IFJlZGVmaW5pbmcgXGNkb3RzIG9uIGlucHV0IGxpbmUgNjIwLgpcTWF0aHN0cnV0Ym94QD1c +Ym94NTAKXHN0cnV0Ym94QD1cYm94NTEKXGJpZ0BzaXplPVxkaW1lbjE0MApMYVRlWCBGb250IElu +Zm86ICAgIFJlZGVjbGFyaW5nIGZvbnQgZW5jb2RpbmcgT01MIG9uIGlucHV0IGxpbmUgNzQzLgpM +YVRlWCBGb250IEluZm86ICAgIFJlZGVjbGFyaW5nIGZvbnQgZW5jb2RpbmcgT01TIG9uIGlucHV0 +IGxpbmUgNzQ0LgpcbWFjY0BkZXB0aD1cY291bnQxODcKXGNATWF4TWF0cml4Q29scz1cY291bnQx +ODgKXGRvdHNzcGFjZUA9XG11c2tpcDE2ClxjQHBhcmVudGVxdWF0aW9uPVxjb3VudDE4OQpcZHNw +YnJrQGx2bD1cY291bnQxOTAKXHRhZ0BoZWxwPVx0b2tzMTcKXHJvd0A9XGNvdW50MTkxClxjb2x1 +bW5APVxjb3VudDE5MgpcbWF4ZmllbGRzQD1cY291bnQxOTMKXGFuZGhlbHBAPVx0b2tzMTgKXGVx +bnNoaWZ0QD1cZGltZW4xNDEKXGFsaWduc2VwQD1cZGltZW4xNDIKXHRhZ3NoaWZ0QD1cZGltZW4x +NDMKXHRhZ3dpZHRoQD1cZGltZW4xNDQKXHRvdHdpZHRoQD1cZGltZW4xNDUKXGxpbmVodEA9XGRp +bWVuMTQ2ClxAZW52Ym9keT1cdG9rczE5ClxtdWx0bGluZWdhcD1cc2tpcDQ4ClxtdWx0bGluZXRh +Z2dhcD1cc2tpcDQ5ClxtYXRoZGlzcGxheUBzdGFjaz1cdG9rczIwCkxhVGVYIEluZm86IFJlZGVm +aW5pbmcgXFsgb24gaW5wdXQgbGluZSAyOTIzLgpMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxdIG9u +IGlucHV0IGxpbmUgMjkyNC4KKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFt +c1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc3N5bWIuc3R5ClBhY2thZ2U6IGFtc3N5bWIg +MjAxMy8wMS8xNCB2My4wMSBBTVMgZm9udCBzeW1ib2xzCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc2ZvbnRzLnN0eQpQ +YWNrYWdlOiBhbXNmb250cyAyMDEzLzAxLzE0IHYzLjAxIEJhc2ljIEFNU0ZvbnRzIHN1cHBvcnQK +XHN5bUFNU2E9XG1hdGhncm91cDQKXHN5bUFNU2I9XG1hdGhncm91cDUKTGFUZVggRm9udCBJbmZv +OiAgICBSZWRlY2xhcmluZyBtYXRoIHN5bWJvbCBcaGJhciBvbiBpbnB1dCBsaW5lIDk4LgpMYVRl +WCBGb250IEluZm86ICAgIE92ZXJ3cml0aW5nIG1hdGggYWxwaGFiZXQgYFxtYXRoZnJhaycgaW4g +dmVyc2lvbiBgYm9sZCcKKEZvbnQpICAgICAgICAgICAgICAgICAgVS9ldWYvbS9uIC0tPiBVL2V1 +Zi9iL24gb24gaW5wdXQgbGluZSAxMDYuCikpCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbDNiYWNrZW5kXGwzYmFja2VuZC1wZGYKdGV4LmRl +ZgpGaWxlOiBsM2JhY2tlbmQtcGRmdGV4LmRlZiAyMDIxLTA4LTA0IEwzIGJhY2tlbmQgc3VwcG9y +dDogUERGIG91dHB1dCAocGRmVGVYKQpcbF9fY29sb3JfYmFja2VuZF9zdGFja19pbnQ9XGNvdW50 +MTk0ClxsX19wZGZfaW50ZXJuYWxfYm94PVxib3g1MgopCk5vIGZpbGUgaW5wdXQuYXV4Lgpcb3Bl +bm91dDEgPSBgaW5wdXQuYXV4Jy4KCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVs +dHMgZm9yIE9NTC9jbW0vbS9pdCBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAg +Li4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRl +ZmF1bHRzIGZvciBPTVMvY21zeS9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86 +ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2lu +ZyBkZWZhdWx0cyBmb3IgT1QxL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IElu +Zm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVj +a2luZyBkZWZhdWx0cyBmb3IgVDEvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQg +SW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENo +ZWNraW5nIGRlZmF1bHRzIGZvciBUUzEvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZv +bnQgSW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAg +IENoZWNraW5nIGRlZmF1bHRzIGZvciBPTVgvY21leC9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRl +WCBGb250IEluZm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZv +OiAgICBDaGVja2luZyBkZWZhdWx0cyBmb3IgVS9jbXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFU +ZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5m +bzogICAgVHJ5aW5nIHRvIGxvYWQgZm9udCBpbmZvcm1hdGlvbiBmb3IgVSttc2Egb24gaW5wdXQg +bGluZSA1LgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2Ftc2ZvbnRzXHVtc2EuZmQKRmlsZTogdW1zYS5mZCAyMDEzLzAxLzE0IHYzLjAxIEFN +UyBzeW1ib2xzIEEKKQpMYVRlWCBGb250IEluZm86ICAgIFRyeWluZyB0byBsb2FkIGZvbnQgaW5m +b3JtYXRpb24gZm9yIFUrbXNiIG9uIGlucHV0IGxpbmUgNS4KCihDOlxVc2Vyc1xqb25hdFxBcHBE +YXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zZm9udHNcdW1zYi5mZApGaWxl +OiB1bXNiLmZkIDIwMTMvMDEvMTQgdjMuMDEgQU1TIHN5bWJvbHMgQgopClsxe0M6L1VzZXJzL2pv +bmF0L0FwcERhdGEvTG9jYWwvTWlLVGVYL3BkZnRleC9jb25maWcvcGRmdGV4Lm1hcH1dCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFRlbXBcaW5rdG1wZHNyeG1yajdcaW5wdXQuYXV4KSAp +IApIZXJlIGlzIGhvdyBtdWNoIG9mIFRlWCdzIG1lbW9yeSB5b3UgdXNlZDoKIDEzNjQgc3RyaW5n +cyBvdXQgb2YgNDc4ODY4CiAxODk3MiBzdHJpbmcgY2hhcmFjdGVycyBvdXQgb2YgMjg0ODgwOQog +MzA3NzQzIHdvcmRzIG9mIG1lbW9yeSBvdXQgb2YgMzAwMDAwMAogMTkzMzMgbXVsdGlsZXR0ZXIg +Y29udHJvbCBzZXF1ZW5jZXMgb3V0IG9mIDE1MDAwKzYwMDAwMAogNDA1MTI5IHdvcmRzIG9mIGZv +bnQgaW5mbyBmb3IgMzUgZm9udHMsIG91dCBvZiA4MDAwMDAwIGZvciA5MDAwCiAxMTQxIGh5cGhl +bmF0aW9uIGV4Y2VwdGlvbnMgb3V0IG9mIDgxOTEKIDU2aSw1biw2NnAsMzExYiw5NnMgc3RhY2sg +cG9zaXRpb25zIG91dCBvZiA1MDAwaSw1MDBuLDEwMDAwcCwyMDAwMDBiLDgwMDAwcwo8QzovVXNl +cnMvam9uYXQvQQpwcERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRzL3R5cGUxL3B1Ymxp +Yy9hbXNmb250cy9jbS9jbWV4MTAucGZiPjxDOi9Vc2VyCnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9Q +cm9ncmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ftc2ZvbnRzL2NtL2NtbWkxMC5wZmIK +PjxDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBl +MS9wdWJsaWMvYW1zZm9udHMvY20vYwptbWk3LnBmYj48QzovVXNlcnMvam9uYXQvQXBwRGF0YS9M +b2NhbC9Qcm9ncmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ftc2ZvCm50cy9jbS9jbXIx +MC5wZmI+PEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRz +L3R5cGUxL3B1YmwKaWMvYW1zZm9udHMvY20vY21yNy5wZmI+PEM6L1VzZXJzL2pvbmF0L0FwcERh +dGEvTG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRzL3R5cAplMS9wdWJsaWMvYW1zZm9udHMvY20v +Y21zeTcucGZiPgpPdXRwdXQgd3JpdHRlbiBvbiBDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFRlbXBcaW5rdG1wZHNyeG1yajdcaW5wdXQucGRmICgxCiBwYWdlLCA1NjM1MSBieXRlcykuClBE +RiBzdGF0aXN0aWNzOgogMzYgUERGIG9iamVjdHMgb3V0IG9mIDEwMDAgKG1heC4gODM4ODYwNykK +IDAgbmFtZWQgZGVzdGluYXRpb25zIG91dCBvZiAxMDAwIChtYXguIDUwMDAwMCkKIDEgd29yZHMg +b2YgZXh0cmEgbWVtb3J5IGZvciBQREYgb3V0cHV0IG91dCBvZiAxMDAwMCAobWF4LiAxMDAwMDAw +MCkKCg== + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: inktmpdsrxmrj7 + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.aux" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.aux + +XHJlbGF4IApcZ2RlZiBcQGFic3BhZ2VAbGFzdHsxfQo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/pdflatex/b78a310017b7056b187bd023af227d1e.msg b/share/extensions/tests/data/cmd/pdflatex/b78a310017b7056b187bd023af227d1e.msg new file mode 100644 index 0000000..26ebafb --- /dev/null +++ b/share/extensions/tests/data/cmd/pdflatex/b78a310017b7056b187bd023af227d1e.msg @@ -0,0 +1,493 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: pdflatex +Arguments: -halt-on-error -output-directory=. input.tex + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KQ0KZW50ZXJpbmcgZXh0ZW5kZWQgbW9kZQ0KKEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9j +YWwvVGVtcC9pbmt0bXA3cHFoaHRidy9pbnB1dC50ZXgNCkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDENCkwzIHByb2dyYW1taW5nIGxheWVyIDwyMDIxLTA3LTEyPg0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9iYXNlXG1pbmlt +YWwuY2xzDQpEb2N1bWVudCBDbGFzczogbWluaW1hbCAyMDAxLzA1LzI1IFN0YW5kYXJkIExhVGVY +IG1pbmltYWwgY2xhc3MNCikgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc21hdGguc3R5DQpGb3IgYWRkaXRpb25hbCBpbmZv +cm1hdGlvbiBvbiBhbXNtYXRoLCB1c2UgdGhlIGA/JyBvcHRpb24uDQooQzpcVXNlcnNcam9uYXRc +QXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zdGV4dC5z +dHkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0 +ZXgvYW1zbWF0aFxhbXNnZW4uc3R5KSkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFBy +b2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNic3kuc3R5KQ0KKEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc29w +bi5zdHkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRl +eC9sYXRleC9hbXNmb250c1xhbXNzeW1iLnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9j +YWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1xhbXNmb250cy5zdHkpKQ0KDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2wz +YmFja2VuZFxsM2JhY2tlbmQtcGRmDQp0ZXguZGVmKQ0KTm8gZmlsZSBpbnB1dC5hdXguDQooQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2Zv +bnRzXHVtc2EuZmQpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXHVtc2IuZmQpDQpbMXtDOi9Vc2Vycy9qb25hdC9BcHBEYXRh +L0xvY2FsL01pS1RlWC9wZGZ0ZXgvY29uZmlnL3BkZnRleC5tYXB9XQ0KKEM6XFVzZXJzXGpvbmF0 +XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXA3cHFoaHRid1xpbnB1dC5hdXgpICk8QzovVXNlcnMv +am9uYXQvQQ0KcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90eXBlMS9wdWJsaWMv +YW1zZm9udHMvY20vY21yNy5wZmI+PEM6L1VzZXJzLw0Kam9uYXQvQXBwRGF0YS9Mb2NhbC9Qcm9n +cmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ftc2ZvbnRzL2NtL2Ntc3k3LnBmYj4NCk91 +dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXA3 +cHFoaHRid1xpbnB1dC5wZGYgKDENCiBwYWdlLCAxODQ2NSBieXRlcykuDQpUcmFuc2NyaXB0IHdy +aXR0ZW4gb24gQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlua3RtcDdwcWhodGJ3 +XGlucHV0LmxvDQpnLg0K + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.log" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.log + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KSAocHJlbG9hZGVkIGZvcm1hdD1wZGZsYXRleCAyMDIxLjguMjMpICA1IE1BUiAyMDIyIDIw +OjMyCmVudGVyaW5nIGV4dGVuZGVkIG1vZGUKKipDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1RlbXAvaW5rdG1wN3BxaGh0YncvaW5wdXQudGV4CihDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xv +Y2FsL1RlbXAvaW5rdG1wN3BxaGh0YncvaW5wdXQudGV4CkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDEKTDMgcHJvZ3JhbW1pbmcgbGF5ZXIgPDIwMjEtMDctMTI+CihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYmFzZVxtaW5pbWFs +LmNscwpEb2N1bWVudCBDbGFzczogbWluaW1hbCAyMDAxLzA1LzI1IFN0YW5kYXJkIExhVGVYIG1p +bmltYWwgY2xhc3MKKSAoQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zbWF0aC5zdHkKUGFja2FnZTogYW1zbWF0aCAyMDIxLzA0 +LzIwIHYyLjE3aiBBTVMgbWF0aCBmZWF0dXJlcwpcQG1hdGhtYXJnaW49XHNraXA0NwoKRm9yIGFk +ZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gYW1zbWF0aCwgdXNlIHRoZSBgPycgb3B0aW9uLgooQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21h +dGhcYW1zdGV4dC5zdHkKUGFja2FnZTogYW1zdGV4dCAyMDAwLzA2LzI5IHYyLjAxIEFNUyB0ZXh0 +CgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2Ftc21hdGhcYW1zZ2VuLnN0eQpGaWxlOiBhbXNnZW4uc3R5IDE5OTkvMTEvMzAgdjIuMCBnZW5l +cmljIGZ1bmN0aW9ucwpcQGVtcHR5dG9rcz1cdG9rczE2ClxleEA9XGRpbWVuMTM4CikpCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0 +aFxhbXNic3kuc3R5ClBhY2thZ2U6IGFtc2JzeSAxOTk5LzExLzI5IHYxLjJkIEJvbGQgU3ltYm9s +cwpccG1icmFpc2VAPVxkaW1lbjEzOQopCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFBy +b2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXNvcG4uc3R5ClBhY2thZ2U6IGFtc29w +biAyMDE2LzAzLzA4IHYyLjAyIG9wZXJhdG9yIG5hbWVzCikKXGluZkBiYWQ9XGNvdW50MTgyCkxh +VGVYIEluZm86IFJlZGVmaW5pbmcgXGZyYWMgb24gaW5wdXQgbGluZSAyMzQuClx1cHJvb3RAPVxj +b3VudDE4MwpcbGVmdHJvb3RAPVxjb3VudDE4NApMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxvdmVy +bGluZSBvbiBpbnB1dCBsaW5lIDM5OS4KXGNsYXNzbnVtQD1cY291bnQxODUKXERPVFNDQVNFQD1c +Y291bnQxODYKTGFUZVggSW5mbzogUmVkZWZpbmluZyBcbGRvdHMgb24gaW5wdXQgbGluZSA0OTYu +CkxhVGVYIEluZm86IFJlZGVmaW5pbmcgXGRvdHMgb24gaW5wdXQgbGluZSA0OTkuCkxhVGVYIElu +Zm86IFJlZGVmaW5pbmcgXGNkb3RzIG9uIGlucHV0IGxpbmUgNjIwLgpcTWF0aHN0cnV0Ym94QD1c +Ym94NTAKXHN0cnV0Ym94QD1cYm94NTEKXGJpZ0BzaXplPVxkaW1lbjE0MApMYVRlWCBGb250IElu +Zm86ICAgIFJlZGVjbGFyaW5nIGZvbnQgZW5jb2RpbmcgT01MIG9uIGlucHV0IGxpbmUgNzQzLgpM +YVRlWCBGb250IEluZm86ICAgIFJlZGVjbGFyaW5nIGZvbnQgZW5jb2RpbmcgT01TIG9uIGlucHV0 +IGxpbmUgNzQ0LgpcbWFjY0BkZXB0aD1cY291bnQxODcKXGNATWF4TWF0cml4Q29scz1cY291bnQx +ODgKXGRvdHNzcGFjZUA9XG11c2tpcDE2ClxjQHBhcmVudGVxdWF0aW9uPVxjb3VudDE4OQpcZHNw +YnJrQGx2bD1cY291bnQxOTAKXHRhZ0BoZWxwPVx0b2tzMTcKXHJvd0A9XGNvdW50MTkxClxjb2x1 +bW5APVxjb3VudDE5MgpcbWF4ZmllbGRzQD1cY291bnQxOTMKXGFuZGhlbHBAPVx0b2tzMTgKXGVx +bnNoaWZ0QD1cZGltZW4xNDEKXGFsaWduc2VwQD1cZGltZW4xNDIKXHRhZ3NoaWZ0QD1cZGltZW4x +NDMKXHRhZ3dpZHRoQD1cZGltZW4xNDQKXHRvdHdpZHRoQD1cZGltZW4xNDUKXGxpbmVodEA9XGRp +bWVuMTQ2ClxAZW52Ym9keT1cdG9rczE5ClxtdWx0bGluZWdhcD1cc2tpcDQ4ClxtdWx0bGluZXRh +Z2dhcD1cc2tpcDQ5ClxtYXRoZGlzcGxheUBzdGFjaz1cdG9rczIwCkxhVGVYIEluZm86IFJlZGVm +aW5pbmcgXFsgb24gaW5wdXQgbGluZSAyOTIzLgpMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxdIG9u +IGlucHV0IGxpbmUgMjkyNC4KKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFt +c1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc3N5bWIuc3R5ClBhY2thZ2U6IGFtc3N5bWIg +MjAxMy8wMS8xNCB2My4wMSBBTVMgZm9udCBzeW1ib2xzCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc2ZvbnRzLnN0eQpQ +YWNrYWdlOiBhbXNmb250cyAyMDEzLzAxLzE0IHYzLjAxIEJhc2ljIEFNU0ZvbnRzIHN1cHBvcnQK +XHN5bUFNU2E9XG1hdGhncm91cDQKXHN5bUFNU2I9XG1hdGhncm91cDUKTGFUZVggRm9udCBJbmZv +OiAgICBSZWRlY2xhcmluZyBtYXRoIHN5bWJvbCBcaGJhciBvbiBpbnB1dCBsaW5lIDk4LgpMYVRl +WCBGb250IEluZm86ICAgIE92ZXJ3cml0aW5nIG1hdGggYWxwaGFiZXQgYFxtYXRoZnJhaycgaW4g +dmVyc2lvbiBgYm9sZCcKKEZvbnQpICAgICAgICAgICAgICAgICAgVS9ldWYvbS9uIC0tPiBVL2V1 +Zi9iL24gb24gaW5wdXQgbGluZSAxMDYuCikpCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbDNiYWNrZW5kXGwzYmFja2VuZC1wZGYKdGV4LmRl +ZgpGaWxlOiBsM2JhY2tlbmQtcGRmdGV4LmRlZiAyMDIxLTA4LTA0IEwzIGJhY2tlbmQgc3VwcG9y +dDogUERGIG91dHB1dCAocGRmVGVYKQpcbF9fY29sb3JfYmFja2VuZF9zdGFja19pbnQ9XGNvdW50 +MTk0ClxsX19wZGZfaW50ZXJuYWxfYm94PVxib3g1MgopCk5vIGZpbGUgaW5wdXQuYXV4Lgpcb3Bl +bm91dDEgPSBgaW5wdXQuYXV4Jy4KCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVs +dHMgZm9yIE9NTC9jbW0vbS9pdCBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAg +Li4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRl +ZmF1bHRzIGZvciBPTVMvY21zeS9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86 +ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2lu +ZyBkZWZhdWx0cyBmb3IgT1QxL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IElu +Zm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVj +a2luZyBkZWZhdWx0cyBmb3IgVDEvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQg +SW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIENo +ZWNraW5nIGRlZmF1bHRzIGZvciBUUzEvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZv +bnQgSW5mbzogICAgLi4uIG9rYXkgb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAg +IENoZWNraW5nIGRlZmF1bHRzIGZvciBPTVgvY21leC9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRl +WCBGb250IEluZm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZv +OiAgICBDaGVja2luZyBkZWZhdWx0cyBmb3IgVS9jbXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFU +ZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5m +bzogICAgVHJ5aW5nIHRvIGxvYWQgZm9udCBpbmZvcm1hdGlvbiBmb3IgVSttc2Egb24gaW5wdXQg +bGluZSA1LgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2Ftc2ZvbnRzXHVtc2EuZmQKRmlsZTogdW1zYS5mZCAyMDEzLzAxLzE0IHYzLjAxIEFN +UyBzeW1ib2xzIEEKKQpMYVRlWCBGb250IEluZm86ICAgIFRyeWluZyB0byBsb2FkIGZvbnQgaW5m +b3JtYXRpb24gZm9yIFUrbXNiIG9uIGlucHV0IGxpbmUgNS4KCihDOlxVc2Vyc1xqb25hdFxBcHBE +YXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zZm9udHNcdW1zYi5mZApGaWxl +OiB1bXNiLmZkIDIwMTMvMDEvMTQgdjMuMDEgQU1TIHN5bWJvbHMgQgopClsxe0M6L1VzZXJzL2pv +bmF0L0FwcERhdGEvTG9jYWwvTWlLVGVYL3BkZnRleC9jb25maWcvcGRmdGV4Lm1hcH1dCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFRlbXBcaW5rdG1wN3BxaGh0YndcaW5wdXQuYXV4KSAp +IApIZXJlIGlzIGhvdyBtdWNoIG9mIFRlWCdzIG1lbW9yeSB5b3UgdXNlZDoKIDEzNjQgc3RyaW5n +cyBvdXQgb2YgNDc4ODY4CiAxODk3MiBzdHJpbmcgY2hhcmFjdGVycyBvdXQgb2YgMjg0ODgwOQog +MzA2NzQzIHdvcmRzIG9mIG1lbW9yeSBvdXQgb2YgMzAwMDAwMAogMTkzMzMgbXVsdGlsZXR0ZXIg +Y29udHJvbCBzZXF1ZW5jZXMgb3V0IG9mIDE1MDAwKzYwMDAwMAogNDA1MTI5IHdvcmRzIG9mIGZv +bnQgaW5mbyBmb3IgMzUgZm9udHMsIG91dCBvZiA4MDAwMDAwIGZvciA5MDAwCiAxMTQxIGh5cGhl +bmF0aW9uIGV4Y2VwdGlvbnMgb3V0IG9mIDgxOTEKIDU2aSw1biw2NnAsMzExYiw5NnMgc3RhY2sg +cG9zaXRpb25zIG91dCBvZiA1MDAwaSw1MDBuLDEwMDAwcCwyMDAwMDBiLDgwMDAwcwo8QzovVXNl +cnMvam9uYXQvQQpwcERhdGEvTG9jYWwvUHJvZ3JhbXMvTWlLVGVYL2ZvbnRzL3R5cGUxL3B1Ymxp +Yy9hbXNmb250cy9jbS9jbXI3LnBmYj48QzovVXNlcnMvCmpvbmF0L0FwcERhdGEvTG9jYWwvUHJv +Z3JhbXMvTWlLVGVYL2ZvbnRzL3R5cGUxL3B1YmxpYy9hbXNmb250cy9jbS9jbXN5Ny5wZmI+Ck91 +dHB1dCB3cml0dGVuIG9uIEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXA3 +cHFoaHRid1xpbnB1dC5wZGYgKDEKIHBhZ2UsIDE4NDY1IGJ5dGVzKS4KUERGIHN0YXRpc3RpY3M6 +CiAxNiBQREYgb2JqZWN0cyBvdXQgb2YgMTAwMCAobWF4LiA4Mzg4NjA3KQogMCBuYW1lZCBkZXN0 +aW5hdGlvbnMgb3V0IG9mIDEwMDAgKG1heC4gNTAwMDAwKQogMSB3b3JkcyBvZiBleHRyYSBtZW1v +cnkgZm9yIFBERiBvdXRwdXQgb3V0IG9mIDEwMDAwIChtYXguIDEwMDAwMDAwKQoK + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: inktmp7pqhhtbw + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.aux" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.aux + +XHJlbGF4IApcZ2RlZiBcQGFic3BhZ2VAbGFzdHsxfQo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.pdf + +JVBERi0xLjUKJdDUxdgKMyAwIG9iago8PAovTGVuZ3RoIDE2NSAgICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjafY+xCsJADIb3e4qMihCTS+9ytxbs0E28rXSyOFnQydc3LVYL +BcmWfPm/pC7u2HCCiFklQblBFmTPoFGwkghlgG7Hh31f2mPjqxXIhJQUAqp+sMdEuVNxT8dAVmxQ +Rg1icRklebiOrusJBhu2QCiS4TWjI4glT2t3uLizqzeH/aJWl4Wt8vsAY04bobUWoSeMJH+NbCYF +DRHJzLPRL8Y3EVBCLQplbmRzdHJlYW0KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL0Nv +bnRlbnRzIDMgMCBSCi9SZXNvdXJjZXMgMSAwIFIKL01lZGlhQm94IFswIDAgNTk1LjI3NiA4NDEu +ODldCi9QYXJlbnQgNiAwIFIKPj4KZW5kb2JqCjEgMCBvYmoKPDwKL0ZvbnQgPDwgL0YxOCA0IDAg +UiAvRjI0IDUgMCBSID4+Ci9Qcm9jU2V0IFsgL1BERiAvVGV4dCBdCj4+CmVuZG9iago3IDAgb2Jq +Cls5MzguNV0KZW5kb2JqCjggMCBvYmoKWzg3NyAzMjMuNCAzODQuOSAzMjMuNCA1NjkuNSA1Njku +NSA1NjkuNSA1NjkuNSA1NjkuNSA1NjkuNSA1NjkuNV0KZW5kb2JqCjkgMCBvYmoKPDwKL0xlbmd0 +aDEgMTQwNwovTGVuZ3RoMiA2NDA0Ci9MZW5ndGgzIDAKL0xlbmd0aCA3MzYzICAgICAgCi9GaWx0 +ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42o12BVQTbPs3AhKjQxqZhDTbSEG6u1tqjAEDtsEY +OUBCKUFBUkFSWhFBWloEREpCuktJA6SE/9TnfZ7/837fOd93ds52X78r7it+133Gd83YTFTFBe0M +10SjsKIQMbAcUM3AVAYIBkuIgcHiAD4+cwTWC/4HBfBZwjG+CDRK7n/p1TBwKBaPqUOxeDMDNAqo +6+cFhEgAIdJyEBk5MBgoDgbL/scQjZEDqkP9ES5AAzGgLhoF9wXwqaG9gzAIN3cs/pb/HIECMEEg +RFZWRuS3O1AFCccgYFAU0ACKdYcj8TfCoF5AMzQMAccG/SuEgLw7FustBwIFBASIQZG+YmiMm6Kg +CDAAgXUHmsJ94Rh/uAvwV7lAQygS/rswMQAf0Nwd4fsHNkO7YgOgGDgQD3ghYHCUL97BD+UCxwDx +dwPNdPSBRt5w1B9j/T8GIsC/WgOEiEH+DveX969ACNRvZygMhkZ6Q1FBCJQb0BXhBQcaaeqLYQOx +IkAoyuWXIdTLF433h/pDEV5QZ7zB78ShQE0VEyAUX99f1fnCMAhvrK+YL8LrV4WgX2HwTdZAuaih +kUg4CusL+JWfOgIDh+G7HgT6PVZPFDoAhftzdkWgXFx/leDi5w2yQCF8/OA66n9Z4CHAP5gbHAuU +AoPBMrJgINwHCA+EuYN+BTcP8ob/VkJ+wfj8Q3HeaG+gK74EeCjCFY7/AeB8of5wIBbjBw/F/W/F +vyUABAJ0QcCwQGe4GwIF+Cc6Hoa7/pHxk8cgAoG3wHjiQYDgX5+/T/Z4brmgUV5B/5j/Hi7IRF9X +T1VL+HfBf6tUVdGBQJyouAxQVFwKDIRAxMWBMvhD6L+jGEMRf2UB/sdXB+WKBsr+SRbfpf8k7P/X +9AX+WgxB4L9jGaLxjIUDBf4huB1YCgzDf0H+v2n+2+X/xu5fUf4fBP/vfDT9vLx+awV+qf8PLRSJ +8Ar6S4/nqx8Wz30DNH4DUP9tagX/s64GcBeEH/K/tTpYKH4HVFBuXn83EeGriQiEuxgjsDD3P1T5 +g1v8WjAvBApujPZF/HpQgKIQMPi/dPitgnniHw1fPB9/q+D4pfn3lRooGNrl13aJS0kDoRgMNAiA +HzFekgLiIPg1dIEH/mYwECSGQmPxLkB8eaFAVzQG8GueUhJAkCsCT1k8+huQlAWC8O/UPzLewNvL +z/dvAJ8JCBuA/i3/KxWYHwaDX8TfVMHn+R/599bD4YFwGGBqAg27ecej+s7royoV9gDRtUGFUb41 +q0xBUdwUpsXvhJo0TfBFduQC5lAlra+TdnZFQ+BAeZrrJ26r8RVpTFOKSfNpyJljsunIWjNgcpjp +7dDTLZWabk5yDlFz5fWQnz4hlhGeRI2X2nT58nz8blAbFzAcBbzRCqzpLp95Hz2xZrL+QlqP4qz8 +g2iiRYJdRMkYX77zk3EWbhKsKCeZEP1+IM3YweEofe7QBZdusjAgdDtRoghnuyh+/3g8eO6Zubhv +Oysvqy0LJ9EB/fuR6zjVzXRd5o+40qL5wjE7v+I4idl2AnutsIllchn5IETyjZdKvUTX1t2Wfmy3 +UTT0o0S0Yiun05+u/xSpuF3pTSi1vnEGPsjtvU27i5vgLKevq+ZuO3sqo3b06tGVZem4cF2ea2wK +Cgf8qVz7mHvT/lyK01xa31nTK69Fg6i4TKg0qQ1ehXW7gpBX2YXyEfcEcrivIco6cgF64VIMipTd +hWfkLikiug4VtXfZWYlF9ofsIx0KAMEbzMxsH4TYyb/WCsd6upeNEnoYBWy2zPpsE5Lve14XSVl3 +VAp/9P68LxZ2lTsFpXRYPDhuFZsimJOSPn6Pi6GdbZCTqJg80bMrfT0+zWkn0fZ5fWoX6PsDM3oq +inShAaW0WpLbsBDS1dQ1q243dGvybvLPcbZ3ldXOHYgb7nDfo9YqExrEyZ2+JklBzfzkYwb/hneH +j8ONKS1310qZJpPavRGeyQ1OHnvj+6tO7Vm1HRoVFoJost3PtVb7FB6qhq73OmbaG6KM+8wTJkma +ij9AHXn3PtE+p+rzU3dhjJ6UuG9Cdpihympr5hrkJ0m5mVMa2LlY3LS0MGJ4LH+emwCZZP+wnG+9 +5Jkmwzyqk9WoyMd+thk6ehswyT+zZv7oQrAs7AqvDt/ghc/iQ2MdnhpRA/qUoU3LQM9B6s7A7m3l ++ddjM9kMtgu60u7he8+XpxXcVaarFgbfk8jRtvEkoZ0n/JvmGcHwVrufXN9p8ncudeZ3c4JT+jYv +H8CMX6gG47rZClwJFBaO6lwg8Z/ntB7z47ogH9uVXQbVw4KsMa1p6pVGtkmlGn1iQ0mzClspAnwO +pS0gccv2BmbBhla2J58/dPesCizs7yD3mlhdm1hJL9NzmN4XB7M4zcfVm+sjv4MuHa6aMNzXf/iO +I5IqWG/SgBP5kmug6GVR9v7ZJLmww6eGCX+VmtcAtEb/uVYgV7k/x/aOdb1OoAph3zerV7lPSXtP +xhUDp9U6y9u2pEaIo1K/710LyB91+JRCecw4+aZo0j9VgOj7iKSIaGEkvPPL69HmQjIlkGncynaG +0n31Gh+4T0d6J92TxAoOshrR/LxSskCNnV0g78FsZiJTUoGQBPr1UmVmpM2YMBgnbCh28rM2vFtx +KDaWXyEvor5HR/eUowvgav8+Ro3b1xsVWZUnHgkhx0mcKGicTXtUbhFKHozZGr4TBxC8ONALEwqI +aFI6v/Sd6enmLk/6q7xoYtlytpvfAa+IVS4LPjYOoqaQiQ2ddahF+rFr7mZP9oifxOenPqsKDENK +d5LIWzroeRFxDQZbPgj6UfmUW6PoBo0W7VH+evfqm/o3raqxHi3UG6/ju8wynZLsHGjYLh6fChfZ +5/BCu635jdU8Uqe1SFXgwgBZG15W59Pyuo+Dw2mZe9Q0uR+3OLTX3T66ntF0CSuU0wXtXURg1/rf +Z9unSHw6p3hkETqMPs1XTiD/dotaa84+sLBXSrb6cV0owrsE+p30NO8ojPtdG3CawaWbnM7RPmcE +noYrME9zjJ1xHeRgcxzcTy6Wvt5uLcq2h1mJezmYdqS4WkHDJXmdTKtbCVNkFyKdVUr9qFdfEB7Q +WcySPNuVqSqMGVNNgm3M5ORJ3O3wB2RlLF579UwOjPNj1Qdc7SoYVrlKOuMRivORsHJQJSjjfzIn +8JOBxaaIoNcdBZ6wemO6+cBsSYnAj/6YYPoN5U/C7Qzbbq6qurTYB4hk1KuV8XcKUy0N03k9mYJb +Kbha3xcKm0i7yIjItDY/Oi8HLXfDXq5JEuXTrUUBjowkX6pA4uYT6SspUxwviZ1PDGIi+OmFPpPV +8ROVF3dLrymtrm2h2lTyGnHZOVWPuESaH0FicVkah7HbYhOmgUhDSdYmz4V1AUaCAIasRi8JsMEx +bTlRW+7M+pKdBkE8aw0GcLFJ+GqB7NGB98+dAexO0Bw52wJ6h0bxGHAJV3IOdcx4UW922N5RDril +/qhCLH0XO6JDl8miMdqye6mfIs4+ItG1+2TD8nPleErFvIeMJdQR2tf+7YBbFMezM7rDvF7CLhpx +cgVwKLfB4WyUMXPriyDdrvbz16RjKtaE0xpbzalvLkp+WLjlynvW+pQQ6LN21ahWrE+8E/J4NtpE +5049oZPAT8l7uVV5Wg4pJhYN8sngK/f2AqqGg9ip7Fw/rfnpwq5mtFDr5a7tP3ZPTfQPtEcSpkpR +7mwIcWN2j9Lr2xJu2t3Yk/IL2127JcclrKUWLve9WlOY25AWMDzKdnsrxjYTyZqhglU2GwrZPhzK +Rc4IK1SVW75h0CaxyjMeXpT4GnJKmOeNfATmbi5qtXCR2aj72Mrae8vSOmcvTawY2/JC811rKGa8 +LqjRJiyv8BWL63Rty/A435XeqKNgroO7WgaLJmFjCveN+/fUh7wIVr/r05l799i89dZdOaRkjXWE +zZs8kdtdIPBI+bRSuiA3fgIcrMjJi6Pd7LeTkpO1thgBesQTmmYtuPHY7xFa+dRm79k2lCavNIc/ +7uhHjY7mqRE92dwL4s6JI9uq9uAR7lnu6bV7NIFLGUi9HZS2UZ5mP9xCY3RUzDYToAF/6E1mefrt +NAT4IuRMx97W5dlGNri2Ft267mKpy6tcGbJ372pLNHMChdDnUrbWrKCAfaaftHSUerk0Q9e+FoxT +gys3tySOiHz8iTPENCsdOa1V0vM1Qw/vSVmpBjkQ0oYmWCmOjYoHG6X5rBOXlNz2qYoqTGDnzgHe +Pcfo9IX1zXLxlij6rpPO7xwUklwGV9kolx439ZZKnZRt0tbjdFruTxIqMrwPurwRWY0eVns1tx3F +pSKu0K56rLRb+LqD2zSWrgrQ4ebYJxJWd/rDR0wjBIhCvx/KMJe+iVCyjnd+Lxk19z0U+wOe035O +xEI4Nn1Rrz8ECdu6nqLvYjsQ+l082upbFp3YlmTJ/Six3WYHvgGhomHOGqZ+9amQPVulmp07Mnfu +W0H2Lz2nFKJSlzdegfR72B/HLVIE67YyHKXlzZF8fqjI+YVRnS1XydjxYg87jM4f+KYXn5akH88P +K48/qOckOJgnn+VYiMm7h2RhNCNRZOwQfZIwyROSfJ/y5u3B5VumEKK16YJ7aU7fAbXKyui6QdSR +O8f+a7GxbsuJOU3h/gAJhrncjFVBU2saHs6G4uMC2SLfYMkv1nHc1TzOyzQBRPq4HBhBtGa44XMC +giUPMv6stwl5JvFjydjGQ45jcfaP5tOosF2xnYoo4J22fva0kHLH7qsM+ywLSQ3nnkMCzzUvkADU +yg2hnDMOGwKJY24xN4KwTxJmqpPPrg1kfB3wnb/xmlx4cGUumio9DZHZMPVJXaaxj0n9rPm48hvP +2ouDmXa0xqmBMXgU7F2GKn9/T8Mu4s1U5anwJKdM+jtHimaTH2TBUaZv4qiGWBDqaNWH2QoheXko +XiJx5yuWXVmtVlzf92oZTff99h87bDfav5IR54l+3haz/wwQKMO4Vm+mwdQsVVWYZpQzObxn8U5O +Cf3ch7KG1sqO5vzdlS9rXLk+8YTFzMzGCwTvsPIHV9wvrdR29gwsmYr4v5C5R6PhTBDZvd5kK8Wo +wHag2JV1nEH6aL97IpvxqJDnSrO7Gb2pSs22ovibeZIoMqNxJS8abp95AZoR9c9G0TEHfp4HRJKO +oVwzPTk8ZZQERU6GbbEnYMMK0kjaZke1tWdTqvLLChVuW3pG1BDQCbTl2s61mLEUASfd/ucfWWXF +YnpMC/tLgyCkHqTFX7xQGfo1P5xOXI+HmMLLI1meT4QNlPs1x+u+9AhQH2KByO736jlYyehfXBKo +/dDmqb15A9N9m3lbDZTA1EPiSHa34tPIyjUGypY70RC3LjcnYP0H5y+X6/zSyetOly1d0OaNjhUa +vNEl0cARen1bta0I58/Ui7SDD5JYBEt4/M7hhZtzi6SbQvIFtEiS7lB2kouroXH35G/bvqqHUD/7 +fpRmL1OXsYLavPszbb2NWoFWOu5wCxZ2lcfpOTHawKlBZ3H1oZZaPCuse1En0bRTwJXu0itKCI3S +ctonRWFSGz1SdjVbxrt85am+jILeH4Z+zAfuH15oGzGrm350v6N/ShiXEDNDt1xWpgTQFPl8qDxT +n/S4p8tLdJkvkJqh1mrRb+OtPmG7eUZeeqwMNG9ACrA2wtp7HuessIw+GrnP1FAKS8yOg54D1jHG +Nj519ZwMna7sV3InJSzgxTkm0h4PSf1od+Ou1VIlF2Nvr9noi/BofD73j+qf+NlwQymcRnlY/hPd +BVKpbK/rzuPlzoafo202uxnM7TLjDhbgmJ4vBk6tU9YiU32HaMLg4sfklDOG9tGl57OnJNRqZvsF +3s4T/aNtvRd2vUO42ONuFnERyEKh+XVd0z01v+vkP0HqiTxV8NbBlJD+09Cruqd3Pi2PiqKfsGQF +Gw3amKer2a8jxnpAJ28/nwL1WB1qi2NMSKC9alcR+bgEkpuXlp6W0ZPecSqJ2bkJUK6xUpvr/+EZ +J26jvUibmqTFu6U79eZgLCXDqFZRTziCikNYc+abGAWf3uxOwcVHq2ka6ulP81a2lynT/GAcJrQF +p+Om9xmLkzbMn0Jyap8C5xT3MJtRh1npO/EJNzWHr2pNlHzh/9nKKVfdXVbocmWbyTpmCBWi8/rA +fqC0MNAHtMECIYs5a/JFFBvyOnunh3/wrpe3cD4A8/Qll2lrbu0f1/D3zF6yYX7wondYpKQ/v/AN +07vITvNi/hvNfd5pT/2BvmklIIII2TcKJCo/iWXJxvgn1JxtQaSyxedxqOu8nt0VEIZ535HEjZTo +pUDByat03ox10PFrdjvtXMPurZcavw9kmGEYieauoKnIyf1sZwxaif3Vqh0LzkHm0ehhJlErCdyd +i/SlsjqF7o6JgEOx4QTf7k7TJdF0ztggSPtw1fycq3y/oKR/iUspV9J8W4cmScJUxvb+rZ39Vqcp +wKLEuH/7UcLNKFz6NjtLGPejLcTYjynY/NYAi7an21LmlxkFUP+SOhXaGUfAe93XQcjx/vFmDeie ++4zdHNMeLzPyuq27YQTpTdKaOp5XKlrSqkp1XN09IPoLuMM1xuvFRGffheMcy7aHMqinVFoudWgX +d+ya36b5CqR9o1nj9DWyKa3SGzjtzUB9NVG2HisCLYPNlASRTj5MH39WMO0RsAI4uypGdzo1ILVO +8R67VIAcmN726t/wsyiFYRnju0RB3f2qUr4UHBIi6YMvtWCT62Ps6NddWCbW6J9SKiMEHA+CWYSr +hJegGlcoe1MgvUSLh3tKair7zrVXyAOt+SHw99LLReGjsib6G/mXvaDGmk7q9+1jSUNzrizb/kiu +Fnz24IZ3ZPGtGOqATw0DQgIV3M23rlf4Fcj1CRE9wTz22xUdII9XyCyt5caoqaJ83cbZD+/sZw+4 +jR4NoarLyjWCp+WdqwcroBTfgoKnYpbZhemr8f9xLoKHnozNgDQlU5I2d6MVGqWfoV+WPmP+evx0 +nLqS03VswDElyWarA2ytXcYnWSVsMKNNhA3YYQEOJ3TcGycTCD32Cv/2Zvo1NEy18KdDICxZAoUT +LsVlOg99SwN3lT6uhEY/0GGArHoUr9gx0dITuTeSW4x4kBdpX+p/U/YgVUc/0mTiLDHfXXDztuHg +YOkM00q5niIFuBZb7LhCJeRkVEImJ/WaIs5gO+fxSmhyyNGarWGzRc+P+1vXeBaoTD600KhVpefo +tAEaw9bR7D8ogCE5xPHLvHoQBlRPSKBsdlPszrjs0yXSrziocVKt82VmPWaQKx1yhIRFBPxA6cxV +1rsUeSNJVDqY1mKwl8WN8DNtptiGlkvBJvW9cC42Fd2NK3yS5PIzw2GlXqMTDI7i/TupVrUe5c0u +BkZdbVyrBPFrZjNIeBl7J3dXywLFkEIB8lK5bEo87Jtrn3PI3RilBcq1tDqADacJiXJ7FKF91sEr +VmNx9yLQR6utSEHrL/4zbSk2gL4zoq9Twu0pN1F62QuyDfoRHQwJlUKMFU5NookQynDhl0QdXzOy +9lgqPbqH389of/1mhbVL+LH7dvirVrtulKsX6/Za65bKo6+u310VoVLqarS8ZdKNy15uSa0/0+qE +JPdA+UIMmRwrvAaL7BXF58hlF17SmpRSXnpwAjF8fcJLBgqdPauMpRJg3w2QiLX79MjOOmdFpbct +67ZkltN7+xc76SEp/tErUdPikDbBBxQ5P+/murRIE4vJaDZ5qq2DFgkgk7pSLlnrLPBsra6XcSds +UT6RlemN4VxLBP6R5uwL7Qs5hj1DmyHKdi18RG9Jo+FqjtuKXQy81gc3YKpfG/hdcZRFuahck6vV +toZvMeSmNQ9QucWhpi1JkHlS1WCq9U+PmB2HsxM+Pt7o3BClGSXTKDzw9Fgf2ppFojy5H7J/lCrx +OASJJ4Q9W3G+9+BAo/Ku7LdYng7NdKTNTNlGWIihuvfzDHMOc2lbvi+nw9rkMNqzbqxH+ddgidzs +absrQKFU2hoQuImjSNaU81bW2wKJrnHQIuyT5NRE+U4ygd782QuHmtsUSxLOe3yqbMq85QYuddu8 +NwS2fFPuGb+zghXbXOzLiaeNGF7/6kNHPDArmXmQxJsPKLW08a/pfKtdR9LIbAaMZNXCUAgrPago +k+5bVVz2xe1fr68sU6ayDqajXD2t5lkNpNfWFlbnS/C3DbMySlSyJJPoliAypNC8OxqRLTt8iTQP +cIubkru5FoN8Bs+OzdjK7MdNjp1L6HOxyTzYcMt+0lOT8XrLlNjJRO/GSy67o/3d6bRwV7D7Qd5L +YLh85cUNxvy7VEFRk28BsrH9dq+NF4631aMbHZ73QPTnIe/v2N3lJaCtUmvVdN775mVgcik4UYyr +qX85f19n5gVB1Y0GV3/KCtGpwUVCvumcIqOIUVVzy4fEzNplMzbMwu3euqFmgIW+aqR3qy6rRHRp +n83dn9ACX8q53E7iWiEzExv9JlVjx1uR2lbEqvRvTNxc14FO+60cYex0pfe3bwW+nyF6ACImDPJe +AST75yEoGhSzglkD39FP9qz5Dfd7O7xpVX7E4xcwLC+54kwrchkpFFru/bzzrmEyrtn1e55GeKyy +q2Heoht1vhinkwt3d20UPUvpMwzF8hrdJJsvpklSijXBTLTLgrGPltkx8DHh4oXTe00e6oW1tiTc +IMEDeYv5UosiX/htIa5h9Eu9rpGZYgFPp6rwk5f1yDCiKrmjlShw92WvBdz91KUBCWnRGAavijEl +5oj9qSj7RELK8Uvdr75dj4+FfGsc0BEzM3hkZ5QMf7nHjKRAp9awre5s8nz9MGOal3r7pMxb7Nbq +rsVLHo8wHholkI2AHJH9xPiCFO/JbBxP/24HlFf6CMbSXugrmjmyfdp1eNKpFBJUbFD7UnRs0L+5 +XLOh8sPlueL2Z/ozV146dS1XX37GDgzlcP1qJ+Z1StisvdohLPZuPeUb/4eY5skmZj01pfDy21t0 ++sUNqZnvmmh5nLlMGvO9tOG9FxuzibZWpu2TTBvk9MmupNqeovUW3V6UjrYnJHsmjOfQ9VljYk4N +Yc+d0CeTLGyvLaoENlg29WUfh1nKokWeeax9kIAtFL6s/mE4aF8awP5Wf7WJFZrrXSxnr75vNGHl +Zj43CrfaXSVObQyuA5lSRWMKYmjsYIbWCgO8bNfqm0Eix5DsuLhj9ajHm5OKg0RYu9ZG4Yie15KZ +j/OzJSufO67dCUJz6kYllfOWW6KjyiSH/V+pps/fxEBM9Wb1Mn5sZKpOGD6fhQtLNOWYTvUmWWff +PstFgR8YkpVGGkUcCzgs6EG/zBzYhsNDEpCYhzQ/lqm4e0ZzCQYiPqiTnH1oqYebBEt25LkY3PBr +5IPf600u6j3vMe/kl2mzlqk+KSw0es2679Jl/iH9Y6YwYYyN4NJE7WwpfxM9/OnDBglTiVvLmU6X +fcjSrJg2r4pXsCR10CxHtjaEfWiuJC20iuJBfWi9DBFYLIfNGt1IMKo/vHbTt13waaU22ToNQtVU +P0sn0zwDGSCfwCUglaHnOFg9O3nQNh8gm+Y0Nb3nsAQpdqRZJpNzOQKc43baunvhhUpPCxi8fmT6 +sjtu6BNHel7m/qEhdV18u7VHpnCmwf2zLgFzSMZ1QqoTj6AvvelgPoGmsZurUaWfx4f6cnU/NkBy +mp8KqZATGTApVLR2ik4k7rvdU9KlF9Ec+XgylczFtHAqvi68stYGUgwUGRhzAO9NBwUlYkDolJQE +OYlQZgvpJw914ICiDTdW1tAxjddeRHM7gor6toWXPY8bYfty4JcGUMLSlPd2UU9m7/K/EFjIpHtr +/rnEQ74ddOPLnk0KlfyTGNnnromRGyEd2dZGK3m3/weq+y1/CmVuZHN0cmVhbQplbmRvYmoKMTAg +MCBvYmoKPDwKL1R5cGUgL0ZvbnREZXNjcmlwdG9yCi9Gb250TmFtZSAvUUxKS0JHK0NNUjcKL0Zs +YWdzIDQKL0ZvbnRCQm94IFstMjcgLTI1MCAxMTIyIDc1MF0KL0FzY2VudCA2OTQKL0NhcEhlaWdo +dCA2ODMKL0Rlc2NlbnQgLTE5NAovSXRhbGljQW5nbGUgMAovU3RlbVYgNzkKL1hIZWlnaHQgNDMx +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 +XYfnjJQZ3REgidDtGONODx2RPpnUg2zLsfUKkxVTiVyIaFtDnM7JGEGxNhb75vUhzu5m1B45SwzK +51CMiUgR9xIQnj+I51FrKGHFk3TQRRp/+E67aymkmPLTPdt3hD7vqbhIYzVLD23leHL886sKxs4N +PtK+Ke6zFlFRoDTb461iDhhHnHjm6wf95BR47t7KuNP+fh2zpYpwe5Lf4fCz0NszAHLDNrtuIHnd +xfW9hL2qvlseg6a6U8aqwly0C98J4fWrvRvHJ7Oxnu3ESlU2ebniO0rNylW3GIlmj7V/pjenrxng +0nDV0FNjZJSyRpPJt49rg048i4nwCEZku0WxaJasKyOPvMoNj3z4A2/IJS73hPZn14lvdaq8PtCy +ObUnLvjWcZOQz5RhXFDfHkr7YiOLx9QU4kPFwONcUJTHuGA6nq4gcSN5VnG916ev3L98agA9uTWc +NIIT5cV5tA3vdKca8dwrdG1OoqkYXHsr0O0xXYTSAi4c3bib7zXZCbxcx5rM7HF1UjFbymi+EONe +KJm2++gVuOaf88Sfe7sdO/+d1VTKZG6n8GLIOaWu7BnV19V5EiSFyJuJT55ITKnEAJI3hbhtE/Y5 +eVSs3vNukLirm6N3pwGE5AOPvCi5po8w9ENzCoGFd+5Es+3GkZT73GcG2YmgdAOjSs4JRvQMZb8N +OZegSD499/Ek/op8xVdvDbNc4nmatASSsWUcUgt39tg4TpVkg8byvJm49yZiP9Vz2+VA1/wFpvZN +h+IhZ5UA//kjCuPErxe1QzHg0kyxx2JjSjULYa680XR5m+bj5x1NHyauS0Me5O3ENUHKAgexp/qa +hSBP/bim6u7qFzGh5f3VtSOo+U6XLo3TQxIBNVTDNCIz29XDtmWOSbQuRi2BOseAMGBMCL++3XrZ +Rsa0XZHjfwDzBXFmCmVuZHN0cmVhbQplbmRvYmoKMTIgMCBvYmoKPDwKL1R5cGUgL0ZvbnREZXNj +cmlwdG9yCi9Gb250TmFtZSAvTUdLVllFK0NNU1k3Ci9GbGFncyA0Ci9Gb250QkJveCBbLTE1IC05 +NTEgMTI1MSA3ODJdCi9Bc2NlbnQgNzUwCi9DYXBIZWlnaHQgNjgzCi9EZXNjZW50IC0xOTQKL0l0 +YWxpY0FuZ2xlIC0xNAovU3RlbVYgNDkKL1hIZWlnaHQgNDMxCi9DaGFyU2V0ICgvcmFkaWNhbCkK +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 +ataB8gN7DGfkiI+1lNNyjHNxa47pOm44Bp/6N894SXX4hqrsf6+z/73J/vdl9r+vsv+9zf73Lvvf +19n/QWb/B5X9H3T2fzDZ/6HM/g8h+z802f+NybM05W1GuuV0q/HPHQ/R7dnoztOUXhR6reilwBsx +jPH2oB32B+yiP3oJr+8uvn5siv8BUH3pTAplbmRzdHJlYW0KZW5kb2JqCjUgMCBvYmoKPDwKL1R5 +cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvTUdLVllFK0NNU1k3Ci9Gb250RGVz +Y3JpcHRvciAxMiAwIFIKL0ZpcnN0Q2hhciAxMTIKL0xhc3RDaGFyIDExMgovV2lkdGhzIDcgMCBS +Ci9Ub1VuaWNvZGUgMTQgMCBSCj4+CmVuZG9iago2IDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovQ291 +bnQgMQovS2lkcyBbMiAwIFJdCj4+CmVuZG9iagoxNSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwov +UGFnZXMgNiAwIFIKPj4KZW5kb2JqCjE2IDAgb2JqCjw8Ci9Qcm9kdWNlciAoTWlLVGVYIHBkZlRl +WC0xLjQwLjIzKQovQ3JlYXRvciAoVGVYKQovQ3JlYXRpb25EYXRlIChEOjIwMjIwMzA1MjAzMjA1 +KzAxJzAwJykKL01vZERhdGUgKEQ6MjAyMjAzMDUyMDMyMDUrMDEnMDAnKQovVHJhcHBlZCAvRmFs +c2UKL1BURVguRnVsbGJhbm5lciAoVGhpcyBpcyBNaUtUZVgtcGRmVGVYIDQuOC4wICgxLjQwLjIz +KSkKPj4KZW5kb2JqCnhyZWYKMCAxNwowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAzNzAgMDAw +MDAgbiAKMDAwMDAwMDI1OSAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMTYzNTEg +MDAwMDAgbiAKMDAwMDAxNzQ4NSAwMDAwMCBuIAowMDAwMDE3NjQyIDAwMDAwIG4gCjAwMDAwMDA0 +NDkgMDAwMDAgbiAKMDAwMDAwMDQ3MiAwMDAwMCBuIAowMDAwMDAwNTUzIDAwMDAwIG4gCjAwMDAw +MDgwMzQgMDAwMDAgbiAKMDAwMDAwODI2NSAwMDAwMCBuIAowMDAwMDE1MzA2IDAwMDAwIG4gCjAw +MDAwMTU1MzEgMDAwMDAgbiAKMDAwMDAxNjUwNSAwMDAwMCBuIAowMDAwMDE3Njk5IDAwMDAwIG4g +CjAwMDAwMTc3NDkgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSAxNwovUm9vdCAxNSAwIFIKL0lu +Zm8gMTYgMCBSCi9JRCBbPEIwMjk0RTRENkE5RDVEOEJCQjQ0NDE0QTQ2QUNBM0YyPiA8QjAyOTRF +NEQ2QTlENUQ4QkJCNDQ0MTRBNDZBQ0EzRjI+XSA+PgpzdGFydHhyZWYKMTc5NjgKJSVFT0YK + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/pdflatex/fa0bf1f8c5a5eafc88832c60950b0a40.msg b/share/extensions/tests/data/cmd/pdflatex/fa0bf1f8c5a5eafc88832c60950b0a40.msg new file mode 100644 index 0000000..41592eb --- /dev/null +++ b/share/extensions/tests/data/cmd/pdflatex/fa0bf1f8c5a5eafc88832c60950b0a40.msg @@ -0,0 +1,543 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: pdflatex +Arguments: -halt-on-error -output-directory=. input.tex + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KQ0KZW50ZXJpbmcgZXh0ZW5kZWQgbW9kZQ0KKEM6L1VzZXJzL2pvbmF0L0FwcERhdGEvTG9j +YWwvVGVtcC9pbmt0bXB3N2FhMXI0di9pbnB1dC50ZXgNCkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDENCkwzIHByb2dyYW1taW5nIGxheWVyIDwyMDIxLTA3LTEyPg0KKEM6XFVzZXJz +XGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25l +XHN0YW5kYWxvbmUuYw0KbHMNCkRvY3VtZW50IENsYXNzOiBzdGFuZGFsb25lIDIwMTgvMDMvMjYg +djEuM2EgQ2xhc3MgdG8gY29tcGlsZSBUZVggc3ViLWZpbGVzIHN0YW4NCmRhbG9uZQ0KKEM6XFVz +ZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xz +aGVsbGVzYy5zdHkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZsdWF0ZXguc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0 +YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2dlbmVyaWMvaWZ0ZXhcaWZ0ZXguc3R5KSkNCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtl +eXZhbFx4a2V5dmFsLnN0eQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxceGtleXZhbC50ZXgNCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxz +LnRleA0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9n +ZW5lcmljL3hrZXl2YWxca2V5dmFsLnRleCkpKQ0KKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYw0K +ZmcpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xh +dGV4L2tvbWEtc2NyaXB0XHNjcnJlcHJ0LmNsDQpzDQpEb2N1bWVudCBDbGFzczogc2NycmVwcnQg +MjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBkb2N1bWVudCBjbGFzcyAocmVwb3J0KQ0KDQoo +QzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tv +bWEtc2NyaXB0XHNjcmtiYXNlLnN0DQp5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmJhc2Uuc3R5DQoNCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1z +Y3JpcHRcc2NybGZpbGUuc3QNCnkNCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dy +YW1zXE1pS1RlWFx0ZXgvbGF0ZXgva29tYS1zY3JpcHRcc2NybGZpbGUtaG8NCm9rLTMuMzQuc3R5 +DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5DQopKSkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFx0b2NiYXNpYy5zdA0K +eSkgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRl +eC9leHRzaXplc1xzaXplOC5jbG8pDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9n +cmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHR5cGVhcmVhLnN0DQp5DQoNClBhY2th +Z2UgdHlwZWFyZWEgV2FybmluZzogRElWIGZvciA4LjBwdCBhbmQgdXNlZCBwYXBlcnNpemUNCih0 +eXBlYXJlYSkgICAgICAgICAgICAgICAgbm90IGRlZmluZWQhDQoodHlwZWFyZWEpICAgICAgICAg +ICAgICAgIFVzaW5nIERJVj1jYWxjLg0KDQpESVYgY2FsY3VsYXRpb24gZm9yIHR5cGVhcmVhIHdp +dGggZ29vZCBsaW5ld2lkdGguDQoNClBhY2thZ2UgdHlwZWFyZWEgV2FybmluZzogVmVyeSBsb3cg +RElWIHZhbHVlIQ0KKHR5cGVhcmVhKSAgICAgICAgICAgICAgICBESVYgdmFsdWVzIGxlc3MgdGhh +biA2IHJlc3VsdCBpbiB0ZXh0d2lkdGgvLWhlaWdodA0KKHR5cGVhcmVhKSAgICAgICAgICAgICAg +ICBzbWFsbGVyIHRoYW4gdG90YWwgbWFyZ2lud2lkdGgvLWhlaWdodC4NCih0eXBlYXJlYSkgICAg +ICAgICAgICAgICAgWW91IHNob3VsZCBlLmcuIGluY3JlYXNlIERJViwgaW5jcmVhc2UgZm9udHNp +emUgb3INCih0eXBlYXJlYSkgICAgICAgICAgICAgICAgY2hhbmdlIHBhcGVyc2l6ZS4NCg0KKSkg +KEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9w +cmV2aWV3XHByZXZpZXcuc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFt +c1xNaUtUZVhcdGV4L2xhdGV4L2x1YXRleDg1XGx1YXRleDg1LnN0eSkNCihDOlxVc2Vyc1xqb25h +dFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvcHJldmlld1xwcnRpZ2h0 +cGFnZS5kZWYNCikpKSAoQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtU +ZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zbWF0aC5zdHkNCkZvciBhZGRpdGlvbmFsIGluZm9ybWF0 +aW9uIG9uIGFtc21hdGgsIHVzZSB0aGUgYD8nIG9wdGlvbi4NCihDOlxVc2Vyc1xqb25hdFxBcHBE +YXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0aFxhbXN0ZXh0LnN0eQ0K +KEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9h +bXNtYXRoXGFtc2dlbi5zdHkpKQ0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3Jh +bXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc2JzeS5zdHkpDQooQzpcVXNlcnNcam9uYXRc +QXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zb3BuLnN0 +eSkpDQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xh +dGV4L2Ftc2ZvbnRzXGFtc3N5bWIuc3R5DQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQ +cm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc2ZvbnRzXGFtc2ZvbnRzLnN0eSkpDQoNCihDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbDNiYWNr +ZW5kXGwzYmFja2VuZC1wZGYNCnRleC5kZWYpDQpObyBmaWxlIGlucHV0LmF1eC4NClByZXZpZXc6 +IEZvbnRzaXplIDhwdA0KUHJldmlldzogUERGb3V0cHV0IDENCihDOlxVc2Vyc1xqb25hdFxBcHBE +YXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zZm9udHNcdW1zYS5mZCkNCihD +OlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1z +Zm9udHNcdW1zYi5mZCkNClByZXZpZXc6IFRpZ2h0cGFnZSAwIDAgMCAwDQpbMXtDOi9Vc2Vycy9q +b25hdC9BcHBEYXRhL0xvY2FsL01pS1RlWC9wZGZ0ZXgvY29uZmlnL3BkZnRleC5tYXB9XQ0KKEM6 +XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0bXB3N2FhMXI0dlxpbnB1dC5hdXgp +ICk8QzovVXNlcnMvam9uYXQvQQ0KcHBEYXRhL0xvY2FsL1Byb2dyYW1zL01pS1RlWC9mb250cy90 +eXBlMS9wdWJsaWMvYW1zZm9udHMvY20vY21taTgucGZiPg0KT3V0cHV0IHdyaXR0ZW4gb24gQzpc +VXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlua3RtcHc3YWExcjR2XGlucHV0LnBkZiAo +MQ0KIHBhZ2UsIDExMDgxIGJ5dGVzKS4NClRyYW5zY3JpcHQgd3JpdHRlbiBvbiBDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFRlbXBcaW5rdG1wdzdhYTFyNHZcaW5wdXQubG8NCmcuDQo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.aux" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.aux + +XHJlbGF4IApccHJvdmlkZWNvbW1hbmQqXG5ld0B0cG9AbGFiZWxbMl17fQpcZ2RlZiBcQGFic3Bh +Z2VAbGFzdHsxfQo= + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.log" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.log + +VGhpcyBpcyBwZGZUZVgsIFZlcnNpb24gMy4xNDE1OTI2NTMtMi42LTEuNDAuMjMgKE1pS1RlWCAy +MS44KSAocHJlbG9hZGVkIGZvcm1hdD1wZGZsYXRleCAyMDIxLjguMjMpICA1IE1BUiAyMDIyIDIw +OjMxCmVudGVyaW5nIGV4dGVuZGVkIG1vZGUKKipDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xvY2Fs +L1RlbXAvaW5rdG1wdzdhYTFyNHYvaW5wdXQudGV4CihDOi9Vc2Vycy9qb25hdC9BcHBEYXRhL0xv +Y2FsL1RlbXAvaW5rdG1wdzdhYTFyNHYvaW5wdXQudGV4CkxhVGVYMmUgPDIwMjEtMDYtMDE+IHBh +dGNoIGxldmVsIDEKTDMgcHJvZ3JhbW1pbmcgbGF5ZXIgPDIwMjEtMDctMTI+CihDOlxVc2Vyc1xq +b25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvc3RhbmRhbG9uZVxz +dGFuZGFsb25lLmMKbHMKRG9jdW1lbnQgQ2xhc3M6IHN0YW5kYWxvbmUgMjAxOC8wMy8yNiB2MS4z +YSBDbGFzcyB0byBjb21waWxlIFRlWCBzdWItZmlsZXMgc3RhbgpkYWxvbmUKKEM6XFVzZXJzXGpv +bmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC90b29sc1xzaGVsbGVz +Yy5zdHkKUGFja2FnZTogc2hlbGxlc2MgMjAxOS8xMS8wOCB2MS4wYyB1bmlmaWVkIHNoZWxsIGVz +Y2FwZSBpbnRlcmZhY2UgZm9yIExhVGVYClBhY2thZ2Ugc2hlbGxlc2MgSW5mbzogUmVzdHJpY3Rl +ZCBzaGVsbCBlc2NhcGUgZW5hYmxlZCBvbiBpbnB1dCBsaW5lIDc3LgopCihDOlxVc2Vyc1xqb25h +dFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZmx1YXRl +eC5zdHkKUGFja2FnZTogaWZsdWF0ZXggMjAxOS8xMC8yNSB2MS41IGlmbHVhdGV4IGxlZ2FjeSBw +YWNrYWdlLiBVc2UgaWZ0ZXggaW5zdGVhZC4KCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2Fs +XFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy9pZnRleFxpZnRleC5zdHkKUGFja2FnZTogaWZ0 +ZXggMjAyMC8wMy8wNiB2MS4wZCBUZVggZW5naW5lIHRlc3RzCikpCihDOlxVc2Vyc1xqb25hdFxB +cHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgveGtleXZhbFx4a2V5dmFsLnN0 +eQpQYWNrYWdlOiB4a2V5dmFsIDIwMjAvMTEvMjAgdjIuOCBwYWNrYWdlIG9wdGlvbiBwcm9jZXNz +aW5nIChIQSkKCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0 +ZXgvZ2VuZXJpYy94a2V5dmFsXHhrZXl2YWwudGV4CihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExv +Y2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvZ2VuZXJpYy94a2V5dmFsXHhrdnV0aWxzLnRleApcWEtW +QHRva3M9XHRva3MxNgpcWEtWQHRlbXBhQHRva3M9XHRva3MxNwoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9nZW5lcmljL3hrZXl2YWxca2V5dmFsLnRl +eCkpClxYS1ZAZGVwdGg9XGNvdW50MTgyCkZpbGU6IHhrZXl2YWwudGV4IDIwMTQvMTIvMDMgdjIu +N2Ega2V5PXZhbHVlIHBhcnNlciAoSEEpCikpClxzYUBpbnRlcm5hbD1cY291bnQxODMKXGNAc2Fw +YWdlPVxjb3VudDE4NAoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9zdGFuZGFsb25lXHN0YW5kYWxvbmUuYwpmZwpGaWxlOiBzdGFuZGFsb25l +LmNmZyAyMDE4LzAzLzI2IHYxLjNhIERlZmF1bHQgY29uZmlndXJhdGlvbiBmaWxlIGZvciAnc3Rh +bmRhbG9uCmUnIGNsYXNzCikKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNc +TWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JyZXBydC5jbApzCkRvY3VtZW50IENsYXNz +OiBzY3JyZXBydCAyMDIxLzExLzEzIHYzLjM1IEtPTUEtU2NyaXB0IGRvY3VtZW50IGNsYXNzIChy +ZXBvcnQpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmtiYXNlLnN0CnkKUGFja2FnZTogc2Nya2Jhc2UgMjAyMS8x +MS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChLT01BLVNjcmlwdC1kZXBlbmRlbnQgYgph +c2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JiYXNlLnN0eQpQYWNrYWdlOiBz +Y3JiYXNlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFja2FnZSAoS09NQS1TY3JpcHQt +aW5kZXBlbmRlbnQgCmJhc2ljcyBhbmQga2V5dmFsIHVzYWdlKQoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmls +ZS5zdAp5ClBhY2thZ2U6IHNjcmxmaWxlIDIwMjEvMTEvMTMgdjMuMzUgS09NQS1TY3JpcHQgcGFj +a2FnZSAoZmlsZSBsb2FkIGhvb2tzKQoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJv +Z3JhbXNcTWlLVGVYXHRleC9sYXRleC9rb21hLXNjcmlwdFxzY3JsZmlsZS1obwpvay0zLjM0LnN0 +eQpQYWNrYWdlOiBzY3JsZmlsZS1ob29rLTMuMzQgMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlw +dCBwYWNrYWdlICh1c2luZyBMYVRlWCBoCm9va3MpCgooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxM +b2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHNjcmxvZ28uc3R5ClBh +Y2thZ2U6IHNjcmxvZ28gMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChsb2dv +KQopKSkKQXBwbHlpbmc6IFsyMDIxLzA1LzAxXSBVc2FnZSBvZiByYXcgb3IgY2xhc3NpYyBvcHRp +b24gbGlzdCBvbiBpbnB1dCBsaW5lIDI1Mi4KQWxyZWFkeSBhcHBsaWVkOiBbMDAwMC8wMC8wMF0g +VXNhZ2Ugb2YgcmF3IG9yIGNsYXNzaWMgb3B0aW9uIGxpc3Qgb24gaW5wdXQgbGluZQogMzY4Lgop +KQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4 +L2tvbWEtc2NyaXB0XHRvY2Jhc2ljLnN0CnkKUGFja2FnZTogdG9jYmFzaWMgMjAyMS8xMS8xMyB2 +My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlIChoYW5kbGluZyB0b2MtZmlsZXMpClxzY3JAZHRlQHRv +Y2xpbmVAbnVtYmVyd2lkdGg9XHNraXA0Nwpcc2NyQGR0ZUB0b2NsaW5lQG51bWJveD1cYm94NTAK +KQpQYWNrYWdlIHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3IgYHRvYycgb21pdHRl +ZAoodG9jYmFzaWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBcYmJsQHNldEBsYW5n +dWFnZSBvbiBpbnB1dCBsaW5lIDEzNy4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogRmlsZSBgc2l6ZTgu +Y2xvJyB1c2VkIHRvIHNldHVwIGZvbnQgc2l6ZXMgb24gaW5wdXQgbGluZSAyNAo4Ny4KIChDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvZXh0c2l6 +ZXNcc2l6ZTguY2xvCkZpbGU6IHNpemU4LmNsbyAxOTk5LzExLzExIHYxLjRhIE5PTi1TdGFuZGFy +ZCBMYVRlWCBmaWxlIChzaXplIG9wdGlvbikKKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2Nh +bFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2tvbWEtc2NyaXB0XHR5cGVhcmVhLnN0CnkKUGFj +a2FnZTogdHlwZWFyZWEgMjAyMS8xMS8xMyB2My4zNSBLT01BLVNjcmlwdCBwYWNrYWdlICh0eXBl +IGFyZWEpClx0YUBiY29yPVxza2lwNDgKXHRhQGRpdj1cY291bnQxODUKXHRhQGhibGs9XHNraXA0 +OQpcdGFAdmJsaz1cc2tpcDUwClx0YUB0ZW1wPVxza2lwNTEKXGZvb3RoZWlnaHQ9XHNraXA1MgoK +ClBhY2thZ2UgdHlwZWFyZWEgV2FybmluZzogRElWIGZvciA4LjBwdCBhbmQgdXNlZCBwYXBlcnNp +emUKKHR5cGVhcmVhKSAgICAgICAgICAgICAgICBub3QgZGVmaW5lZCEKKHR5cGVhcmVhKSAgICAg +ICAgICAgICAgICBVc2luZyBESVY9Y2FsYy4KCkRJViBjYWxjdWxhdGlvbiBmb3IgdHlwZWFyZWEg +d2l0aCBnb29kIGxpbmV3aWR0aC4KClBhY2thZ2UgdHlwZWFyZWEgV2FybmluZzogVmVyeSBsb3cg +RElWIHZhbHVlIQoodHlwZWFyZWEpICAgICAgICAgICAgICAgIERJViB2YWx1ZXMgbGVzcyB0aGFu +IDYgcmVzdWx0IGluIHRleHR3aWR0aC8taGVpZ2h0Cih0eXBlYXJlYSkgICAgICAgICAgICAgICAg +c21hbGxlciB0aGFuIHRvdGFsIG1hcmdpbndpZHRoLy1oZWlnaHQuCih0eXBlYXJlYSkgICAgICAg +ICAgICAgICAgWW91IHNob3VsZCBlLmcuIGluY3JlYXNlIERJViwgaW5jcmVhc2UgZm9udHNpemUg +b3IKKHR5cGVhcmVhKSAgICAgICAgICAgICAgICBjaGFuZ2UgcGFwZXJzaXplLgoKUGFja2FnZSB0 +eXBlYXJlYSBJbmZvOiBUaGVzZSBhcmUgdGhlIHZhbHVlcyBkZXNjcmliaW5nIHRoZSBsYXlvdXQ6 +Cih0eXBlYXJlYSkgICAgICAgICAgICAgRElWICA9IDUKKHR5cGVhcmVhKSAgICAgICAgICAgICBC +Q09SID0gMC4wcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICBccGFwZXJ3aWR0aCAgICAgID0gNTk3 +LjUwNzkzcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXHRleHR3aWR0aCAgICAgID0gMjM5LjAw +MzE3cHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgRElWIGRlcGFydHVyZSAgID0gMTQlCih0eXBl +YXJlYSkgICAgICAgICAgICAgIFxldmVuc2lkZW1hcmdpbiA9IDEwNi45ODIzOXB0Cih0eXBlYXJl +YSkgICAgICAgICAgICAgIFxvZGRzaWRlbWFyZ2luICA9IDEwNi45ODIzOXB0Cih0eXBlYXJlYSkg +ICAgICAgICAgICAgXHBhcGVyaGVpZ2h0ICAgICA9IDg0NS4wNDY5NHB0Cih0eXBlYXJlYSkgICAg +ICAgICAgICAgIFx0ZXh0aGVpZ2h0ICAgICA9IDM0MC41cHQKKHR5cGVhcmVhKSAgICAgICAgICAg +ICAgXHRvcG1hcmdpbiAgICAgID0gNzAuNjE0NHB0Cih0eXBlYXJlYSkgICAgICAgICAgICAgIFxo +ZWFkaGVpZ2h0ICAgICA9IDExLjg3NXB0Cih0eXBlYXJlYSkgICAgICAgICAgICAgIFxoZWFkc2Vw +ICAgICAgICA9IDE0LjI1cHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXHRvcHNraXAgICAgICAg +ID0gOC4wcHQKKHR5cGVhcmVhKSAgICAgICAgICAgICAgXGZvb3Rza2lwICAgICAgID0gMzMuMjVw +dAoodHlwZWFyZWEpICAgICAgICAgICAgICBcYmFzZWxpbmVza2lwICAgPSA5LjVwdAoodHlwZWFy +ZWEpICAgICAgICAgICAgICBvbiBpbnB1dCBsaW5lIDE3NDMuCikKXGNAcGFydD1cY291bnQxODYK +XGNAY2hhcHRlcj1cY291bnQxODcKXGNAc2VjdGlvbj1cY291bnQxODgKXGNAc3Vic2VjdGlvbj1c +Y291bnQxODkKXGNAc3Vic3Vic2VjdGlvbj1cY291bnQxOTAKXGNAcGFyYWdyYXBoPVxjb3VudDE5 +MQpcY0BzdWJwYXJhZ3JhcGg9XGNvdW50MTkyClxzY3JAZHRlQGNoYXB0ZXJAbWF4bnVtd2lkdGg9 +XHNraXA1MwpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQg +YGFmdGVyaW5kZW50PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcY2hhcHRlciBv +biBpbnB1dCBsaW5lIDU3MTcuClxzY3JAZHRlQHNlY3Rpb25AbWF4bnVtd2lkdGg9XHNraXA1NApD +bGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmluPWJ5 +c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc2VjdGlvbiBvbiBpbnB1dCBsaW5lIDU3 +MjguCkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0 +ZXJpbmRlbnQ9YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzZWN0aW9uIG9uIGlu +cHV0IGxpbmUgNTcyOC4KXHNjckBkdGVAcGFydEBtYXhudW13aWR0aD1cc2tpcDU1CkNsYXNzIHNj +cnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0ZXJpbmRlbnQ9dHJ1 +ZScKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBccGFydCBvbiBpbnB1dCBsaW5lIDU3MzcuClxz +Y3JAZHRlQHN1YnNlY3Rpb25AbWF4bnVtd2lkdGg9XHNraXA1NgpDbGFzcyBzY3JyZXBydCBJbmZv +OiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmluPWJ5c2lnbicKKHNjcnJlcHJ0KSAg +ICAgICAgICAgZm9yIGBcc3Vic2VjdGlvbiBvbiBpbnB1dCBsaW5lIDU3NDcuCkNsYXNzIHNjcnJl +cHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgYWZ0ZXJpbmRlbnQ9YnlzaWdu +Jwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJzZWN0aW9uIG9uIGlucHV0IGxpbmUgNTc0 +Ny4KXHNjckBkdGVAc3Vic3Vic2VjdGlvbkBtYXhudW13aWR0aD1cc2tpcDU3CkNsYXNzIHNjcnJl +cHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgcnVuaW49YnlzaWduJwooc2Ny +cmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJzdWJzZWN0aW9uIG9uIGlucHV0IGxpbmUgNTc1Ny4K +Q2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBhZnRlcmlu +ZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHN1YnN1YnNlY3Rpb24gb24g +aW5wdXQgbGluZSA1NzU3Lgpcc2NyQGR0ZUBwYXJhZ3JhcGhAbWF4bnVtd2lkdGg9XHNraXA1OApD +bGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRlZmF1bHQgYHJ1bmluPWJ5 +c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBccGFyYWdyYXBoIG9uIGlucHV0IGxpbmUg +NTc2OC4KQ2xhc3Mgc2NycmVwcnQgSW5mbzogdXNpbmcgY29tcGF0aWJpbGl0eSBkZWZhdWx0IGBh +ZnRlcmluZGVudD1ieXNpZ24nCihzY3JyZXBydCkgICAgICAgICAgIGZvciBgXHBhcmFncmFwaCBv +biBpbnB1dCBsaW5lIDU3NjguClxzY3JAZHRlQHN1YnBhcmFncmFwaEBtYXhudW13aWR0aD1cc2tp +cDU5CkNsYXNzIHNjcnJlcHJ0IEluZm86IHVzaW5nIGNvbXBhdGliaWxpdHkgZGVmYXVsdCBgcnVu +aW49YnlzaWduJwooc2NycmVwcnQpICAgICAgICAgICBmb3IgYFxzdWJwYXJhZ3JhcGggb24gaW5w +dXQgbGluZSA1Nzc4LgpDbGFzcyBzY3JyZXBydCBJbmZvOiB1c2luZyBjb21wYXRpYmlsaXR5IGRl +ZmF1bHQgYGFmdGVyaW5kZW50PWJ5c2lnbicKKHNjcnJlcHJ0KSAgICAgICAgICAgZm9yIGBcc3Vi +cGFyYWdyYXBoIG9uIGlucHV0IGxpbmUgNTc3OC4KXGFib3ZlY2FwdGlvbnNraXA9XHNraXA2MApc +YmVsb3djYXB0aW9uc2tpcD1cc2tpcDYxClxjQHB0aUBuYkBzaWRAYkB4PVxib3g1MQpQYWNrYWdl +IHRvY2Jhc2ljIEluZm86IGJhYmVsIGV4dGVuc2lvbiBmb3IgYGxvZicgb21pdHRlZAoodG9jYmFz +aWMpICAgICAgICAgICAgIGJlY2F1c2Ugb2YgbWlzc2luZyBcYmJsQHNldEBsYW5ndWFnZSBvbiBp +bnB1dCBsaW5lIDY5NTguCgpcc2NyQGR0ZUBmaWd1cmVAbWF4bnVtd2lkdGg9XHNraXA2MgpcY0Bm +aWd1cmU9XGNvdW50MTkzClBhY2thZ2UgdG9jYmFzaWMgSW5mbzogYmFiZWwgZXh0ZW5zaW9uIGZv +ciBgbG90JyBvbWl0dGVkCih0b2NiYXNpYykgICAgICAgICAgICAgYmVjYXVzZSBvZiBtaXNzaW5n +IFxiYmxAc2V0QGxhbmd1YWdlIG9uIGlucHV0IGxpbmUgNjk3NC4KClxzY3JAZHRlQHRhYmxlQG1h +eG51bXdpZHRoPVxza2lwNjMKXGNAdGFibGU9XGNvdW50MTk0CkNsYXNzIHNjcnJlcHJ0IEluZm86 +IFJlZGVmaW5pbmcgYFxudW1iZXJsaW5lJyBvbiBpbnB1dCBsaW5lIDcxNDIuClxiaWJpbmRlbnQ9 +XGRpbWVuMTM4CikgKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVY +XHRleC9sYXRleC9wcmV2aWV3XHByZXZpZXcuc3R5ClBhY2thZ2U6IHByZXZpZXcgMjAxNy8wNC8y +NCAxMy4xIChBVUNUZVgvcHJldmlldy1sYXRleCkKCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExv +Y2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvbHVhdGV4ODVcbHVhdGV4ODUuc3R5ClBhY2th +Z2U6IGx1YXRleDg1IDIwMTYvMDYvMTUgdjEuNCBwZGZ0ZXggYWxpYXNlcyBmb3IgbHVhdGV4CikK +KEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9w +cmV2aWV3XHBydGlnaHRwYWdlLmRlZgpcUHJldmlld0JvcmRlcj1cZGltZW4xMzkKKQpccHJAc25p +cHBldD1cY291bnQxOTUKXHByQGJveD1cYm94NTIKXHByQG91dHB1dD1cdG9rczE4CikpIChDOlxV +c2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0ZXgvYW1zbWF0 +aFxhbXNtYXRoLnN0eQpQYWNrYWdlOiBhbXNtYXRoIDIwMjEvMDQvMjAgdjIuMTdqIEFNUyBtYXRo +IGZlYXR1cmVzClxAbWF0aG1hcmdpbj1cc2tpcDY0CkZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9u +IG9uIGFtc21hdGgsIHVzZSB0aGUgYD8nIG9wdGlvbi4KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc3RleHQuc3R5ClBhY2th +Z2U6IGFtc3RleHQgMjAwMC8wNi8yOSB2Mi4wMSBBTVMgdGV4dAoKKEM6XFVzZXJzXGpvbmF0XEFw +cERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNtYXRoXGFtc2dlbi5zdHkK +RmlsZTogYW1zZ2VuLnN0eSAxOTk5LzExLzMwIHYyLjAgZ2VuZXJpYyBmdW5jdGlvbnMKXEBlbXB0 +eXRva3M9XHRva3MxOQpcZXhAPVxkaW1lbjE0MAopKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxM +b2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xhdGV4L2Ftc21hdGhcYW1zYnN5LnN0eQpQYWNrYWdl +OiBhbXNic3kgMTk5OS8xMS8yOSB2MS4yZCBCb2xkIFN5bWJvbHMKXHBtYnJhaXNlQD1cZGltZW4x +NDEKKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4L2xh +dGV4L2Ftc21hdGhcYW1zb3BuLnN0eQpQYWNrYWdlOiBhbXNvcG4gMjAxNi8wMy8wOCB2Mi4wMiBv +cGVyYXRvciBuYW1lcwopClxpbmZAYmFkPVxjb3VudDE5NgpMYVRlWCBJbmZvOiBSZWRlZmluaW5n +IFxmcmFjIG9uIGlucHV0IGxpbmUgMjM0LgpcdXByb290QD1cY291bnQxOTcKXGxlZnRyb290QD1c +Y291bnQxOTgKTGFUZVggSW5mbzogUmVkZWZpbmluZyBcb3ZlcmxpbmUgb24gaW5wdXQgbGluZSAz +OTkuClxjbGFzc251bUA9XGNvdW50MTk5ClxET1RTQ0FTRUA9XGNvdW50MjY2CkxhVGVYIEluZm86 +IFJlZGVmaW5pbmcgXGxkb3RzIG9uIGlucHV0IGxpbmUgNDk2LgpMYVRlWCBJbmZvOiBSZWRlZmlu +aW5nIFxkb3RzIG9uIGlucHV0IGxpbmUgNDk5LgpMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxjZG90 +cyBvbiBpbnB1dCBsaW5lIDYyMC4KXE1hdGhzdHJ1dGJveEA9XGJveDUzClxzdHJ1dGJveEA9XGJv +eDU0ClxiaWdAc2l6ZT1cZGltZW4xNDIKTGFUZVggRm9udCBJbmZvOiAgICBSZWRlY2xhcmluZyBm +b250IGVuY29kaW5nIE9NTCBvbiBpbnB1dCBsaW5lIDc0My4KTGFUZVggRm9udCBJbmZvOiAgICBS +ZWRlY2xhcmluZyBmb250IGVuY29kaW5nIE9NUyBvbiBpbnB1dCBsaW5lIDc0NC4KXG1hY2NAZGVw +dGg9XGNvdW50MjY3ClxjQE1heE1hdHJpeENvbHM9XGNvdW50MjY4Clxkb3Rzc3BhY2VAPVxtdXNr +aXAxNgpcY0BwYXJlbnRlcXVhdGlvbj1cY291bnQyNjkKXGRzcGJya0Bsdmw9XGNvdW50MjcwClx0 +YWdAaGVscD1cdG9rczIwClxyb3dAPVxjb3VudDI3MQpcY29sdW1uQD1cY291bnQyNzIKXG1heGZp +ZWxkc0A9XGNvdW50MjczClxhbmRoZWxwQD1cdG9rczIxClxlcW5zaGlmdEA9XGRpbWVuMTQzClxh +bGlnbnNlcEA9XGRpbWVuMTQ0Clx0YWdzaGlmdEA9XGRpbWVuMTQ1Clx0YWd3aWR0aEA9XGRpbWVu +MTQ2Clx0b3R3aWR0aEA9XGRpbWVuMTQ3ClxsaW5laHRAPVxkaW1lbjE0OApcQGVudmJvZHk9XHRv +a3MyMgpcbXVsdGxpbmVnYXA9XHNraXA2NQpcbXVsdGxpbmV0YWdnYXA9XHNraXA2NgpcbWF0aGRp +c3BsYXlAc3RhY2s9XHRva3MyMwpMYVRlWCBJbmZvOiBSZWRlZmluaW5nIFxbIG9uIGlucHV0IGxp +bmUgMjkyMy4KTGFUZVggSW5mbzogUmVkZWZpbmluZyBcXSBvbiBpbnB1dCBsaW5lIDI5MjQuCikK +KEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9h +bXNmb250c1xhbXNzeW1iLnN0eQpQYWNrYWdlOiBhbXNzeW1iIDIwMTMvMDEvMTQgdjMuMDEgQU1T +IGZvbnQgc3ltYm9scwoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWlL +VGVYXHRleC9sYXRleC9hbXNmb250c1xhbXNmb250cy5zdHkKUGFja2FnZTogYW1zZm9udHMgMjAx +My8wMS8xNCB2My4wMSBCYXNpYyBBTVNGb250cyBzdXBwb3J0ClxzeW1BTVNhPVxtYXRoZ3JvdXA0 +ClxzeW1BTVNiPVxtYXRoZ3JvdXA1CkxhVGVYIEZvbnQgSW5mbzogICAgUmVkZWNsYXJpbmcgbWF0 +aCBzeW1ib2wgXGhiYXIgb24gaW5wdXQgbGluZSA5OC4KTGFUZVggRm9udCBJbmZvOiAgICBPdmVy +d3JpdGluZyBtYXRoIGFscGhhYmV0IGBcbWF0aGZyYWsnIGluIHZlcnNpb24gYGJvbGQnCihGb250 +KSAgICAgICAgICAgICAgICAgIFUvZXVmL20vbiAtLT4gVS9ldWYvYi9uIG9uIGlucHV0IGxpbmUg +MTA2LgopKQooQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxQcm9ncmFtc1xNaUtUZVhcdGV4 +L2xhdGV4L2wzYmFja2VuZFxsM2JhY2tlbmQtcGRmCnRleC5kZWYKRmlsZTogbDNiYWNrZW5kLXBk +ZnRleC5kZWYgMjAyMS0wOC0wNCBMMyBiYWNrZW5kIHN1cHBvcnQ6IFBERiBvdXRwdXQgKHBkZlRl +WCkKXGxfX2NvbG9yX2JhY2tlbmRfc3RhY2tfaW50PVxjb3VudDI3NApcbF9fcGRmX2ludGVybmFs +X2JveD1cYm94NTUKKQpObyBmaWxlIGlucHV0LmF1eC4KXG9wZW5vdXQxID0gYGlucHV0LmF1eCcu +CgpMYVRlWCBGb250IEluZm86ICAgIENoZWNraW5nIGRlZmF1bHRzIGZvciBPTUwvY21tL20vaXQg +b24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIC4uLiBva2F5IG9uIGlucHV0IGxp +bmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2luZyBkZWZhdWx0cyBmb3IgT01TL2Ntc3kv +bS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBpbnB1 +dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVsdHMgZm9yIE9UMS9j +bXIvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4gb2theSBvbiBp +bnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVsdHMgZm9yIFQx +L2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIC4uLiBva2F5IG9u +IGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2luZyBkZWZhdWx0cyBmb3Ig +VFMxL2Ntci9tL24gb24gaW5wdXQgbGluZSA0LgpMYVRlWCBGb250IEluZm86ICAgIC4uLiBva2F5 +IG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICBDaGVja2luZyBkZWZhdWx0cyBm +b3IgT01YL2NtZXgvbS9uIG9uIGlucHV0IGxpbmUgNC4KTGFUZVggRm9udCBJbmZvOiAgICAuLi4g +b2theSBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgQ2hlY2tpbmcgZGVmYXVs +dHMgZm9yIFUvY21yL20vbiBvbiBpbnB1dCBsaW5lIDQuCkxhVGVYIEZvbnQgSW5mbzogICAgLi4u +IG9rYXkgb24gaW5wdXQgbGluZSA0LgpQYWNrYWdlIHNjcmJhc2UgSW5mbzogYWN0aXZhdGluZyBl +bmdsaXNoIFxjb250ZW50c25hbWUgb24gaW5wdXQgbGluZSA0LgpQYWNrYWdlIHNjcmJhc2UgSW5m +bzogYWN0aXZhdGluZyBlbmdsaXNoIFxsaXN0ZmlndXJlbmFtZSBvbiBpbnB1dCBsaW5lIDQuClBh +Y2thZ2Ugc2NyYmFzZSBJbmZvOiBhY3RpdmF0aW5nIGVuZ2xpc2ggXGxpc3R0YWJsZW5hbWUgb24g +aW5wdXQgbGluZSA0LgpQYWNrYWdlIHR5cGVhcmVhIEluZm86IHBhY2thZ2UgYHByZXZpZXcnIHdp +dGggb3B0aW9uIGB0aWdodHBhZ2UnIGRldGVjdGVkLgoodHlwZWFyZWEpICAgICAgICAgICAgIGlu +aXRpYWwgcGFnZSBzaXplIHNwZWNpYWwgZGVhY3RpdmF0ZWQgb24gaW5wdXQgbGluZSA0LgpQcmV2 +aWV3OiBGb250c2l6ZSA4cHQKUHJldmlldzogUERGb3V0cHV0IDEKTGFUZVggRm9udCBJbmZvOiAg +ICBUcnlpbmcgdG8gbG9hZCBmb250IGluZm9ybWF0aW9uIGZvciBVK21zYSBvbiBpbnB1dCBsaW5l +IDUuCihDOlxVc2Vyc1xqb25hdFxBcHBEYXRhXExvY2FsXFByb2dyYW1zXE1pS1RlWFx0ZXgvbGF0 +ZXgvYW1zZm9udHNcdW1zYS5mZApGaWxlOiB1bXNhLmZkIDIwMTMvMDEvMTQgdjMuMDEgQU1TIHN5 +bWJvbHMgQQopCkxhVGVYIEZvbnQgSW5mbzogICAgVHJ5aW5nIHRvIGxvYWQgZm9udCBpbmZvcm1h +dGlvbiBmb3IgVSttc2Igb24gaW5wdXQgbGluZSA1LgoKKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFc +TG9jYWxcUHJvZ3JhbXNcTWlLVGVYXHRleC9sYXRleC9hbXNmb250c1x1bXNiLmZkCkZpbGU6IHVt +c2IuZmQgMjAxMy8wMS8xNCB2My4wMSBBTVMgc3ltYm9scyBCCikKUHJldmlldzogVGlnaHRwYWdl +IDAgMCAwIDAKWzF7QzovVXNlcnMvam9uYXQvQXBwRGF0YS9Mb2NhbC9NaUtUZVgvcGRmdGV4L2Nv +bmZpZy9wZGZ0ZXgubWFwfV0KKEM6XFVzZXJzXGpvbmF0XEFwcERhdGFcTG9jYWxcVGVtcFxpbmt0 +bXB3N2FhMXI0dlxpbnB1dC5hdXgpICkgCkhlcmUgaXMgaG93IG11Y2ggb2YgVGVYJ3MgbWVtb3J5 +IHlvdSB1c2VkOgogNTE1OCBzdHJpbmdzIG91dCBvZiA0Nzg4NjgKIDEwMzEwNSBzdHJpbmcgY2hh +cmFjdGVycyBvdXQgb2YgMjg0ODgwOQogNTI4MjUwIHdvcmRzIG9mIG1lbW9yeSBvdXQgb2YgMzAw +MDAwMAogMjMwNTAgbXVsdGlsZXR0ZXIgY29udHJvbCBzZXF1ZW5jZXMgb3V0IG9mIDE1MDAwKzYw +MDAwMAogNDA3MTc1IHdvcmRzIG9mIGZvbnQgaW5mbyBmb3IgNDIgZm9udHMsIG91dCBvZiA4MDAw +MDAwIGZvciA5MDAwCiAxMTQxIGh5cGhlbmF0aW9uIGV4Y2VwdGlvbnMgb3V0IG9mIDgxOTEKIDEy +MmksOG4sMTI4cCwxMDcyN2IsMjgwcyBzdGFjayBwb3NpdGlvbnMgb3V0IG9mIDUwMDBpLDUwMG4s +MTAwMDBwLDIwMDAwMGIsODAwMDBzCjxDOi9Vc2Vycy9qb25hdC9BCnBwRGF0YS9Mb2NhbC9Qcm9n +cmFtcy9NaUtUZVgvZm9udHMvdHlwZTEvcHVibGljL2Ftc2ZvbnRzL2NtL2NtbWk4LnBmYj4KT3V0 +cHV0IHdyaXR0ZW4gb24gQzpcVXNlcnNcam9uYXRcQXBwRGF0YVxMb2NhbFxUZW1wXGlua3RtcHc3 +YWExcjR2XGlucHV0LnBkZiAoMQogcGFnZSwgMTEwODEgYnl0ZXMpLgpQREYgc3RhdGlzdGljczoK +IDExIFBERiBvYmplY3RzIG91dCBvZiAxMDAwIChtYXguIDgzODg2MDcpCiAwIG5hbWVkIGRlc3Rp +bmF0aW9ucyBvdXQgb2YgMTAwMCAobWF4LiA1MDAwMDApCiAxIHdvcmRzIG9mIGV4dHJhIG1lbW9y +eSBmb3IgUERGIG91dHB1dCBvdXQgb2YgMTAwMDAgKG1heC4gMTAwMDAwMDApCgo= + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Filename: inktmpw7aa1r4v + +TWlzc2luZyBGaWxl + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="input.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: input.pdf + +JVBERi0xLjUKJdDUxdgKMyAwIG9iago8PAovTGVuZ3RoIDEwOCAgICAgICAKL0ZpbHRlciAvRmxh +dGVEZWNvZGUKPj4Kc3RyZWFtCnjaNcohEoQwDEBR31NEBkE3KYUQywwIdByDYBdYuP8FaKeD+uK/ +wdxnagjEqxCDnUAQ2EvXg+2w4FbV3ATFb2okxV+12gzkSaBWH7tY2J4ZKx65iZ0vC1xcW9w//aCC +V3Y94Z2dG8094qgdzAplbmRzdHJlYW0KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL0Nv +bnRlbnRzIDMgMCBSCi9SZXNvdXJjZXMgMSAwIFIKL01lZGlhQm94IFswIDAgMzQuMjUgMjguMzkz +XQovUGFyZW50IDUgMCBSCj4+CmVuZG9iagoxIDAgb2JqCjw8Ci9Gb250IDw8IC9GMzAgNCAwIFIg +Pj4KL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0KPj4KZW5kb2JqCjYgMCBvYmoKWzU2NC40IDQ1NC41 +IDQ2MC4yIDU0Ni43IDQ5Mi45IDUxMC40IDUwNS42IDYxMi4zIDM2MS43XQplbmRvYmoKNyAwIG9i +ago8PAovTGVuZ3RoMSAxNTAzCi9MZW5ndGgyIDc2MTcKL0xlbmd0aDMgMAovTGVuZ3RoIDg2Mjkg +ICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjajbYFVJRbGzZMiJQ0SuNDN8zQ +Jd3SDVIDDDDEDDBDS3dJSEmnICggIKhIhzRIg4C0gArSDR/qed9zzvv/a33fmrVm9nXXvq+9r3uv +YWHQ1uORtUVYQ5UQcBQPmBckDshraKiKAiCQAC8IxI/HwqIPQzlD/zLjsRhC3ZEwBFz8HwHy7lAI +6samAEHdxGkg4ICahzMAFgDAwuJgEXEQCOAHgcT+E4hwFwcUIJ4wW0CDF1BDwKFIPBZ5hKuPO8ze +AXWzzX+WALsNBwAWExPh/p0OyLpA3WE2EDigAUE5QF1udrSBOAN6CBsYFOXzrxLskg4olKs4H5+X +lxcvxAXJi3C3l+LgBrxgKAdAF4qEuntCbYFfhAFNiAv0DzNePBZA3wGG/GPXQ9ihvCDuUODG4Ayz +gcKRNxkecFuoO3CzOaCnqg5ouULhf4LV/wRwA3+dDQDmBf+33F/ZvwrB4L+TITY2CBdXCNwHBrcH +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 +s3JL+HV2Dtkthv07ciW+7zPJD0rA3u0WAbfbNFfs2YMka421JvkWixBx8tORdeZ4hIOsEcH/B1MT +v6gKZW5kc3RyZWFtCmVuZG9iago4IDAgb2JqCjw8Ci9UeXBlIC9Gb250RGVzY3JpcHRvcgovRm9u +dE5hbWUgL0lJQ1pJSStDTU1JOAovRmxhZ3MgNAovRm9udEJCb3ggWy0yNCAtMjUwIDExMTAgNzUw +XQovQXNjZW50IDY5NAovQ2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9JdGFsaWNBbmdsZSAt +MTQKL1N0ZW1WIDc4Ci9YSGVpZ2h0IDQzMQovQ2hhclNldCAoL2EvYi9jL2QvZS9mL2cvaC9pKQov +Rm9udEZpbGUgNyAwIFIKPj4KZW5kb2JqCjkgMCBvYmoKPDwKL0xlbmd0aCA2OTUgICAgICAgCi9G +aWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0cmVhbQp42m1UTW/iMBC951d4D5XaA8UfJIEKIdkJkThs +W5VqtVdITDcSSVAIh/779RsTrFY9EE2e38y88Qtz9+t1O9FVt7cT9cjZmz13l760k+z37hTd3eVd +eWlsOzxbW9lqPD0/sde+K7d2YPfZJt+09fDgyJu2PF4qO7J+Jhn7UbeBgj7s/t3+nZRNU88n+0t9 +HOp2wsF9r4ej4/x0zBzGvmCMUv7Y/lx37RMTj5xzB6zbKusazHCOplcdbDoqO9Rt1V/FsD2kRUKy +qi6H6xs9y8ZdBpK3n+fBNpv20EXLJZu+ucPz0H+Swodo+tJXtq/bD3b/RZk72V5Op6OFCsaj1YpV +9uAKutmfd41l058GvFHeP0+WSXoXXlXZVfZ82pW237UfNlpyvmLLolhFtq2+nUnuU/aHkZs6Lp/j +oXS8coBBvCbACAcIVBOxBxIASBE+xeQAFgA0ARkHgBoi94ACULhYCg+kDpBIlwtCTQYA6dIQQDUU +2iowOFcAZkiPqQufQVgMdowuMkmgIwEj9YwEDI0uehGG05jLiDCcUQDmYTiDdGPCcE6dA/IwnEGN +jIfhMglA3YZztz5e72w+Xnf5b9dfneFqgTQOGVJydOXS43PEvtLCIJ75eI3YW6ChwSVRTHWu81Eu +3aKQVLMgvMDcgvjcUOy9zRFL35dw6fvmuBbp++aoI33fgnDf103s4tTHxEFNGRuylryOM/CVN0NC +vzI+htsq875SnHu8QLz2OPGpjqT6M+7vCn1j6qUkZo8LHwNPiCME8JR6CQUNKfWSCtrS3HNwVynV +4Tnw+dVO4Jp7PbhnLYJfWga/tAp+6VnwS8fBL50Ev3Qa/NI6+KXz4JeRwS+zCH5l4uYXfVn0JeGf +jS102xnlpe/dOqFVRWsCC6Ju7W2bnboTsuhHa3Bcunh7KaL/1N6C9wplbmRzdHJlYW0KZW5kb2Jq +CjQgMCBvYmoKPDwKL1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUxCi9CYXNlRm9udCAvSUlDWklJ +K0NNTUk4Ci9Gb250RGVzY3JpcHRvciA4IDAgUgovRmlyc3RDaGFyIDk3Ci9MYXN0Q2hhciAxMDUK +L1dpZHRocyA2IDAgUgovVG9Vbmljb2RlIDkgMCBSCj4+CmVuZG9iago1IDAgb2JqCjw8Ci9UeXBl +IC9QYWdlcwovQ291bnQgMQovS2lkcyBbMiAwIFJdCj4+CmVuZG9iagoxMCAwIG9iago8PAovVHlw +ZSAvQ2F0YWxvZwovUGFnZXMgNSAwIFIKPj4KZW5kb2JqCjExIDAgb2JqCjw8Ci9Qcm9kdWNlciAo +TWlLVGVYIHBkZlRlWC0xLjQwLjIzKQovQ3JlYXRvciAoVGVYKQovQ3JlYXRpb25EYXRlIChEOjIw +MjIwMzA1MjAzMTUxKzAxJzAwJykKL01vZERhdGUgKEQ6MjAyMjAzMDUyMDMxNTErMDEnMDAnKQov +VHJhcHBlZCAvRmFsc2UKL1BURVguRnVsbGJhbm5lciAoVGhpcyBpcyBNaUtUZVgtcGRmVGVYIDQu +OC4wICgxLjQwLjIzKSkKPj4KZW5kb2JqCnhyZWYKMCAxMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAw +MDAwMDAzMTEgMDAwMDAgbiAKMDAwMDAwMDIwMiAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4g +CjAwMDAwMTAyMDQgMDAwMDAgbiAKMDAwMDAxMDM1OCAwMDAwMCBuIAowMDAwMDAwMzc5IDAwMDAw +IG4gCjAwMDAwMDA0NTAgMDAwMDAgbiAKMDAwMDAwOTE5NyAwMDAwMCBuIAowMDAwMDA5NDMwIDAw +MDAwIG4gCjAwMDAwMTA0MTUgMDAwMDAgbiAKMDAwMDAxMDQ2NSAwMDAwMCBuIAp0cmFpbGVyCjw8 +IC9TaXplIDEyCi9Sb290IDEwIDAgUgovSW5mbyAxMSAwIFIKL0lEIFs8Q0ZCRkU1NDU3OENCRTFE +MkUxRDlBNTQ0NjgxQ0YwNzE+IDxDRkJGRTU0NTc4Q0JFMUQyRTFEOUE1NDQ2ODFDRjA3MT5dID4+ +CnN0YXJ0eHJlZgoxMDY4NAolJUVPRgo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/ps2pdf/754c0d01b6fab11719df7fe755bd3be8.msg b/share/extensions/tests/data/cmd/ps2pdf/754c0d01b6fab11719df7fe755bd3be8.msg new file mode 100644 index 0000000..99fdf4c --- /dev/null +++ b/share/extensions/tests/data/cmd/ps2pdf/754c0d01b6fab11719df7fe755bd3be8.msg @@ -0,0 +1,63 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: ps2pdf +Arguments: -dAutoRotatePages=/None test.eps output.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.pdf + +JVBERi0xLjQKJcfsj6IKJSVJbnZvY2F0aW9uOiBwYXRoL2dzIC1QLSAtZFNBRkVSIC1kQ29tcGF0 +aWJpbGl0eUxldmVsPTEuNCAtZEF1dG9Sb3RhdGVQYWdlcz0vTm9uZSAtcSAtUC0gLWROT1BBVVNF +IC1kQkFUQ0ggLXNERVZJQ0U9cGRmd3JpdGUgLXNzdGRvdXQ9PyAtc091dHB1dEZpbGU9PyAtUC0g +LWRTQUZFUiAtZENvbXBhdGliaWxpdHlMZXZlbD0xLjQgLWRBdXRvUm90YXRlUGFnZXM9L05vbmUg +Pwo1IDAgb2JqCjw8L0xlbmd0aCA2IDAgUi9GaWx0ZXIgL0ZsYXRlRGVjb2RlPj4Kc3RyZWFtCnic +XY9LDgIxCIb3nIITIPQ5HEM3HqDRcdExGb1/Ih3bxhjSlo/CD+zIJMjN+ls2OF0yrm/YobEGOwvj +64ZXfAJTis6HYPkLu+ybE0WyKL5WkERB2B0FG6hksoQGFdTZX9CD1HvKETU7SqoTk6eoWKCzO+46 +UAKlsJhcFzJtr42/XQaWOcSIVDCPOS8zwlOMe5diu/b+tbl9slHYhv7drcDjb9c7nM0+x5xBzGVu +ZHN0cmVhbQplbmRvYmoKNiAwIG9iagoxNzEKZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01l +ZGlhQm94IFswIDAgNTk1IDg0Ml0KL1BhcmVudCAzIDAgUgovUmVzb3VyY2VzPDwvUHJvY1NldFsv +UERGXQovRXh0R1N0YXRlIDggMCBSCj4+Ci9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKMyAwIG9i +ago8PCAvVHlwZSAvUGFnZXMgL0tpZHMgWwo0IDAgUgpdIC9Db3VudCAxCj4+CmVuZG9iagoxIDAg +b2JqCjw8L1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDMgMCBSCi9NZXRhZGF0YSA5IDAgUgo+PgplbmRv +YmoKNyAwIG9iago8PC9UeXBlL0V4dEdTdGF0ZQovT1BNIDE+PmVuZG9iago4IDAgb2JqCjw8L1I3 +CjcgMCBSPj4KZW5kb2JqCjkgMCBvYmoKPDwvVHlwZS9NZXRhZGF0YQovU3VidHlwZS9YTUwvTGVu +Z3RoIDEzNjY+PnN0cmVhbQo8P3hwYWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJl +U3pOVGN6a2M5ZCc/Pgo8P2Fkb2JlLXhhcC1maWx0ZXJzIGVzYz0iQ1JMRiI/Pgo8eDp4bXBtZXRh +IHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJyB4OnhtcHRrPSdYTVAgdG9vbGtpdCAyLjkuMS0xMywg +ZnJhbWV3b3JrIDEuNic+CjxyZGY6UkRGIHhtbG5zOnJkZj0naHR0cDovL3d3dy53My5vcmcvMTk5 +OS8wMi8yMi1yZGYtc3ludGF4LW5zIycgeG1sbnM6aVg9J2h0dHA6Ly9ucy5hZG9iZS5jb20vaVgv +MS4wLyc+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFm +Ny0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6cGRmPSdodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8x +LjMvJyBwZGY6UHJvZHVjZXI9J0dQTCBHaG9zdHNjcmlwdCA5LjUwJy8+CjxyZGY6RGVzY3JpcHRp +b24gcmRmOmFib3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScg +eG1sbnM6eG1wPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvJz48eG1wOk1vZGlmeURhdGU+ +MjAyMi0wMy0wOFQyMTowOTo0MCswMTowMDwveG1wOk1vZGlmeURhdGU+Cjx4bXA6Q3JlYXRlRGF0 +ZT4yMDIyLTAzLTA4VDIxOjA5OjQwKzAxOjAwPC94bXA6Q3JlYXRlRGF0ZT4KPHhtcDpDcmVhdG9y +VG9vbD5jYWlybyAxLjE1LjEwIChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmcpPC94bXA6Q3JlYXRv +clRvb2w+PC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSd1dWlk +OjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6eGFwTU09J2h0dHA6 +Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8nIHhhcE1NOkRvY3VtZW50SUQ9J3V1aWQ6M2M1ZjIw +ZjUtZDczOC0xMWY3LTAwMDAtODMwZGI0OGE4ZGRlJy8+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFi +b3V0PSd1dWlkOjNjNWYyMGY1LWQ3MzgtMTFmNy0wMDAwLTgzMGRiNDhhOGRkZScgeG1sbnM6ZGM9 +J2h0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvJyBkYzpmb3JtYXQ9J2FwcGxpY2F0aW9u +L3BkZic+PGRjOnRpdGxlPjxyZGY6QWx0PjxyZGY6bGkgeG1sOmxhbmc9J3gtZGVmYXVsdCc+VW50 +aXRsZWQ8L3JkZjpsaT48L3JkZjpBbHQ+PC9kYzp0aXRsZT48L3JkZjpEZXNjcmlwdGlvbj4KPC9y +ZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hw +YWNrZXQgZW5kPSd3Jz8+CmVuZHN0cmVhbQplbmRvYmoKMiAwIG9iago8PC9Qcm9kdWNlcihHUEwg +R2hvc3RzY3JpcHQgOS41MCkKL0NyZWF0aW9uRGF0ZShEOjIwMjIwMzA4MjEwOTQwKzAxJzAwJykK +L01vZERhdGUoRDoyMDIyMDMwODIxMDk0MCswMScwMCcpCi9DcmVhdG9yKGNhaXJvIDEuMTUuMTAg +XChodHRwOi8vY2Fpcm9ncmFwaGljcy5vcmdcKSk+PmVuZG9iagp4cmVmCjAgMTAKMDAwMDAwMDAw +MCA2NTUzNSBmIAowMDAwMDAwNjgwIDAwMDAwIG4gCjAwMDAwMDIyNTYgMDAwMDAgbiAKMDAwMDAw +MDYyMSAwMDAwMCBuIAowMDAwMDAwNDkwIDAwMDAwIG4gCjAwMDAwMDAyMzAgMDAwMDAgbiAKMDAw +MDAwMDQ3MSAwMDAwMCBuIAowMDAwMDAwNzQ0IDAwMDAwIG4gCjAwMDAwMDA3ODUgMDAwMDAgbiAK +MDAwMDAwMDgxNCAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDEwIC9Sb290IDEgMCBSIC9JbmZv +IDIgMCBSCi9JRCBbPDFCMTc4NTEyQUMzRTA0QkM2OUE4RTdFNUZFMjM3OEJCPjwxQjE3ODUxMkFD +M0UwNEJDNjlBOEU3RTVGRTIzNzhCQj5dCj4+CnN0YXJ0eHJlZgoyNDMyCiUlRU9GCg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/ps2pdf/82b68f6250bfc65d80157a71522c62fb.msg b/share/extensions/tests/data/cmd/ps2pdf/82b68f6250bfc65d80157a71522c62fb.msg new file mode 100644 index 0000000..d20581f --- /dev/null +++ b/share/extensions/tests/data/cmd/ps2pdf/82b68f6250bfc65d80157a71522c62fb.msg @@ -0,0 +1,63 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: ps2pdf +Arguments: -dAutoRotatePages=/None test.ps output.pdf + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="output.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: output.pdf + +JVBERi0xLjQKJcfsj6IKJSVJbnZvY2F0aW9uOiBwYXRoL2dzIC1QLSAtZFNBRkVSIC1kQ29tcGF0 +aWJpbGl0eUxldmVsPTEuNCAtZEF1dG9Sb3RhdGVQYWdlcz0vTm9uZSAtcSAtUC0gLWROT1BBVVNF +IC1kQkFUQ0ggLXNERVZJQ0U9cGRmd3JpdGUgLXNzdGRvdXQ9PyAtc091dHB1dEZpbGU9PyAtUC0g +LWRTQUZFUiAtZENvbXBhdGliaWxpdHlMZXZlbD0xLjQgLWRBdXRvUm90YXRlUGFnZXM9L05vbmUg +Pwo1IDAgb2JqCjw8L0xlbmd0aCA2IDAgUi9GaWx0ZXIgL0ZsYXRlRGVjb2RlPj4Kc3RyZWFtCnic +XY9NDkIhDIT3PUVPUId/egy9AonPBW+h3j8REIgxBOhXwsz0yRDD6Gve5aTLLfHxJogCTltbwtiv +g0wUb2BZM/gkNUmcH1BJbXvzOkidkxRYk5WoujE6CcqFJttx1oXGS/S5yU2hpu2089dlYdkhVqdS +q4CUdwdbDNOlEJZ/7eVMtj720L+zFXr8zXqnK30ALt066mVuZHN0cmVhbQplbmRvYmoKNiAwIG9i +agoxNTAKZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01lZGlhQm94IFswIDAgOTQgOThdCi9Q +YXJlbnQgMyAwIFIKL1Jlc291cmNlczw8L1Byb2NTZXRbL1BERl0KL0V4dEdTdGF0ZSA4IDAgUgo+ +PgovQ29udGVudHMgNSAwIFIKPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRz +IFsKNCAwIFIKXSAvQ291bnQgMQo+PgplbmRvYmoKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nIC9Q +YWdlcyAzIDAgUgovTWV0YWRhdGEgOSAwIFIKPj4KZW5kb2JqCjcgMCBvYmoKPDwvVHlwZS9FeHRH +U3RhdGUKL09QTSAxPj5lbmRvYmoKOCAwIG9iago8PC9SNwo3IDAgUj4+CmVuZG9iago5IDAgb2Jq +Cjw8L1R5cGUvTWV0YWRhdGEKL1N1YnR5cGUvWE1ML0xlbmd0aCAxMzY2Pj5zdHJlYW0KPD94cGFj +a2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPD9hZG9iZS14 +YXAtZmlsdGVycyBlc2M9IkNSTEYiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRh +LycgeDp4bXB0az0nWE1QIHRvb2xraXQgMi45LjEtMTMsIGZyYW1ld29yayAxLjYnPgo8cmRmOlJE +RiB4bWxuczpyZGY9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMn +IHhtbG5zOmlYPSdodHRwOi8vbnMuYWRvYmUuY29tL2lYLzEuMC8nPgo8cmRmOkRlc2NyaXB0aW9u +IHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHht +bG5zOnBkZj0naHR0cDovL25zLmFkb2JlLmNvbS9wZGYvMS4zLycgcGRmOlByb2R1Y2VyPSdHUEwg +R2hvc3RzY3JpcHQgOS41MCcvPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJm +NjFmNS1kNzM4LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHhtbG5zOnhtcD0naHR0cDovL25zLmFk +b2JlLmNvbS94YXAvMS4wLyc+PHhtcDpNb2RpZnlEYXRlPjIwMjItMDMtMDhUMjE6MDg6NDYrMDE6 +MDA8L3htcDpNb2RpZnlEYXRlPgo8eG1wOkNyZWF0ZURhdGU+MjAyMi0wMy0wOFQyMTowODo0Nisw +MTowMDwveG1wOkNyZWF0ZURhdGU+Cjx4bXA6Q3JlYXRvclRvb2w+Y2Fpcm8gMS4xNS4xMCAoaHR0 +cDovL2NhaXJvZ3JhcGhpY3Mub3JnKTwveG1wOkNyZWF0b3JUb29sPjwvcmRmOkRlc2NyaXB0aW9u +Pgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4LTExZjctMDAw +MC1lYTcwYWVjZmY4MGUnIHhtbG5zOnhhcE1NPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAv +bW0vJyB4YXBNTTpEb2N1bWVudElEPSd1dWlkOjFjMmY2MWY1LWQ3MzgtMTFmNy0wMDAwLWVhNzBh +ZWNmZjgwZScvPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0ndXVpZDoxYzJmNjFmNS1kNzM4 +LTExZjctMDAwMC1lYTcwYWVjZmY4MGUnIHhtbG5zOmRjPSdodHRwOi8vcHVybC5vcmcvZGMvZWxl +bWVudHMvMS4xLycgZGM6Zm9ybWF0PSdhcHBsaWNhdGlvbi9wZGYnPjxkYzp0aXRsZT48cmRmOkFs +dD48cmRmOmxpIHhtbDpsYW5nPSd4LWRlZmF1bHQnPlVudGl0bGVkPC9yZGY6bGk+PC9yZGY6QWx0 +PjwvZGM6dGl0bGU+PC9yZGY6RGVzY3JpcHRpb24+CjwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0ndyc/PgplbmRzdHJl +YW0KZW5kb2JqCjIgMCBvYmoKPDwvUHJvZHVjZXIoR1BMIEdob3N0c2NyaXB0IDkuNTApCi9DcmVh +dGlvbkRhdGUoRDoyMDIyMDMwODIxMDg0NiswMScwMCcpCi9Nb2REYXRlKEQ6MjAyMjAzMDgyMTA4 +NDYrMDEnMDAnKQovQ3JlYXRvcihjYWlybyAxLjE1LjEwIFwoaHR0cDovL2NhaXJvZ3JhcGhpY3Mu +b3JnXCkpPj5lbmRvYmoKeHJlZgowIDEwCjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDY1NyAw +MDAwMCBuIAowMDAwMDAyMjMzIDAwMDAwIG4gCjAwMDAwMDA1OTggMDAwMDAgbiAKMDAwMDAwMDQ2 +OSAwMDAwMCBuIAowMDAwMDAwMjMwIDAwMDAwIG4gCjAwMDAwMDA0NTAgMDAwMDAgbiAKMDAwMDAw +MDcyMSAwMDAwMCBuIAowMDAwMDAwNzYyIDAwMDAwIG4gCjAwMDAwMDA3OTEgMDAwMDAgbiAKdHJh +aWxlcgo8PCAvU2l6ZSAxMCAvUm9vdCAxIDAgUiAvSW5mbyAyIDAgUgovSUQgWzw0MjBGREMzQkUx +QTY5NDY2MzI5Q0NGMjFBRDkyNjVBQT48NDIwRkRDM0JFMUE2OTQ2NjMyOUNDRjIxQUQ5MjY1QUE+ +XQo+PgpzdGFydHhyZWYKMjQwOQolJUVPRgo= + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/scribus/cbaa8e934937d1d6b0355b525b5351e5.msg b/share/extensions/tests/data/cmd/scribus/cbaa8e934937d1d6b0355b525b5351e5.msg new file mode 100644 index 0000000..2c60ed4 --- /dev/null +++ b/share/extensions/tests/data/cmd/scribus/cbaa8e934937d1d6b0355b525b5351e5.msg @@ -0,0 +1,261 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: scribus +Arguments: -g -py in.svg out.pdf scribus.py + +----CALLDATA--//--CALLDATA-- +Content-Type: application/octet-stream; Name="out.pdf" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment +Filename: out.pdf + +JVBERi0xLjMKJcfsj6IKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMyAwIFIKL1Bh +Z2VMYXlvdXQgL1NpbmdsZVBhZ2UKL1ZpZXdlclByZWZlcmVuY2VzCjw8Ci9QYWdlRGlyZWN0aW9u +IC9MMlIKID4+Cj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9DcmVhdG9yIChTY3JpYnVzIDEuNS41KQov +UHJvZHVjZXIgKFNjcmlidXMgUERGIExpYnJhcnkgMS41LjUpCi9UaXRsZSA8PgovQXV0aG9yIDw+ +Ci9TdWJqZWN0IDw+Ci9LZXl3b3JkcyA8PgovQ3JlYXRpb25EYXRlIChEOjIwMjAwODE0MTIyOTU3 +WikKL01vZERhdGUgKEQ6MjAyMDA4MTQxMjI5NTdaKQovVHJhcHBlZCAvRmFsc2UKPj4KZW5kb2Jq +CjQgMCBvYmoKPDwKL1dpZHRoIDEwMAovSGVpZ2h0IDEwMAovQ29sb3JTcGFjZSAvRGV2aWNlUkdC +Ci9CaXRzUGVyQ29tcG9uZW50IDgKL0xlbmd0aCAyNjM5Ci9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+ +CnN0cmVhbQp42u1cCVQT1xpGfVoFK+L6XFpa2dSqYIIJ+tDiWl+hT21PVaCivudeVLSWJZFEXAFl +daOICyoKtg8QEBCVfZFFwYW1koogm4QAgRCWhP44HmwDDJNBoiT3O/fMmZn8/8y5X+7/3++fuUlb +GwICAgICAgICguzQ0NAAW4FAANumpibssPk1sE9ra2pqeLzy8nLYSvjW19eDmVAohC12BeIQiUT9 +jiu/q1dioqPv3rkD27jY2OvX/G6FhUXfu5eYmACfBgcHwXloEeHh/tevSfj+9tuvYaGhVy775ufl +xcfHYZYE7xsWFgq3C791C658OzLyTlQUl1slx2MSRlTHljT4fL4ixG9oSAiMKxgSJHyxGOyPkUgO +HA4Hog+2kOik9YXog8CPjIhQEK5yc3Lu30/Jyc6G/I9mSQQEBAQEhQLXfGM5ZR7pBu4911/NjT5p +QUZem6ke5jgNDMAMjPu6y/+csBan4ThCf0uUx5AjCnPEuzifuzvkuCrLUMmaouM4k3JiKk7TOjYT +zEayDa1CTlTwuR8mV/j97Y0vEDXYjrreVz35kXJzuVKPLSlLxcJXHVyALoXiCqIJBgn0nQhLf20/ +XPpMjT2/74LxA+TqXGoQxBQMFWm5SsxUAUfIXYrDFeRqSEHSEoU1cAR3xeHqS8RV38cguChaDLbn +dhbK7UR9YeoHAbDukjrB0QVmYAwue0JdFFCLQq/VWPMhprSPzcLXotqOM8AMRtTeUNc+1aLyUeOc +TwsWNAvbEBAQEBD6DxrvJghuRr2TJvdc1bn71LBd3klDXCGu5JYrkUgYG8939eTtseGabahcsAwa +7MAhnBTGJbT1YulCvovHYeYmK8Y6iebJ3FHKdpIxV8nJOessnHX1tkGDnZSUHOK+zVmPebv2lU7U +KFZSxlrJ8HFlU/WgwU7HSTAAMzAmfmVhS1PAo6ivL+wcZEOBKqbLpmpL+5Fh9pB1QDZcubkFTpxk ++tcyEA7dPQg82RCL65zdSgarFg8cXmm4hO95piWvQFxf/zeT+vqW3Hy+x+mKfy0GMzCuO+4OjvgX +bhG17gtzG3VgQXuhx9Lb7vcJVMcVRYOwxn85AOrlpjKl6Izhm69+OoqlO8Casoi1+Ib9T9XsE33H +VVpangRRHXTBYMP3rVq1FgZM5cLlLX88J3IvMKs0+gpcqr4zwzFrFYnMrjGApWVnNAPiR2LMdNly +cj9iBk5QP9T+HgfG3hI7kwh7277jCiKuu4cM69cfx3FsSk2HXvOsrNtaW6W4X2srRCI4NqU/6M7k +WmYE9H13wOTuKIKhdTpqjIGbDhaG02yNDjE35bIO93UMQoLqjqtZuttwHKs3/wjpSFRbJ+0dxXX8 +lyPGV2+x7M5gww32x/azGzoNJzgTlKz6nc/nH9m1UzTWdu42hmk8a7/McjsOV3qzd/TMVU0tCa5K +Ph6Hw9XqqzZqLErn0OMVD/SLU1vlM2UYYzZwNcxaf4Xdqov7d0k1Fb6fGEzLaI/BXfukjkHLvfgx +GJwdA1RYBUyG7N1lDFYXD7wap7by3FvSVtqtvLR/dxkB0nqZ2ydNNusyt/eoHCBFt+d2o69aCjmE +cnshp/LL17n9+x/wJ0EYWkCCsZfGzRTVhu5zO5B2JVZt+RlNLHEpW9NcmVv7VDOAPOisGTw8gwlp +hhMe7ZphgErFvEV891PN2bniv68rhkM4yXc7WTF3IZi1awYXjx41g0gs2hvqOoxJxzTDxsvq4akj +GkvbSYNth3hIfzzM8vpkNXtdmARX2Rvfs2fIQIvev59rYeGsp7cdGoReamqeFFr00ROYDUsnab7V +oipjy3R0ocHOWy06SRPMmh8/JX5lflPD1YfhJhd3D7HR706LDrWh/o+xJpPl0M9qnPhEGD81P9ly +zTe+qXHMN8IhnBQmJPWmxilyPQ3lzAbGmi0M044Cx46xwZm5pZB9FNXO6DkD4gpxhbjqjxAmpDXe +jnsnDb28QEDovygqKiLnmJiYgP12VTYQi8UvXryIiYn28fH28joTERmek5Pd2CiQJVHa2lNIdBlc +wJGcL+DUaU97eyZxex6PZ2q6Wlfvi+9Xf2tts8+OYWNmvtZw/lwNTXXYJ/11S4uUlGRtHY34eCkm +iOSUJMyFhC+GoKBAi/XmxO2XLF3o5HSs849YKyrKDx12gK/M3//aB0hXB1GkqQZwudwpGp8KhYQW +KwoEAmADx+D58+czZk6Ni4v9oOiSIKo3dP1nhXHUndtELNPT07755mt8m8zMh9Oma0MG+0Do6pIo +0nR5e3tZ7txBxPLipQs//7y3R7OQkJtUqi6M2PdOFw5R5OiCTkHXoIM9WgJRQBeRawL58BXIbGbs +sss9EkWOroKC/Olf6KSlpeKbmZj8+8GDDCIXhKCG0Jal4pLoMkGiyNGVlJwIdHE4hTg2cEGCf8Ai +bBKCinhV9eq90CUVUeTogukepjmY+kEASHwEIgGkAggG4ncHKQKCRMZ6vjdqE/MlLhHBEiQlDAmQ +lyAyYR8EJ8hOEJ8gQXmd/vMHByBxQejKvvzpTRVDQktDwQKTPhQvUMJAIQPlDBQ14p7e+CAgICAg +ICC8L5xLDaptrCfnm1GSo1BcGZ01NTy9pr6JzONZ4wtbmRFuisPVhIOGJr9MW/zLusYWqf9ZTstp +8cRD1CN3zyoCURB9Ksw5gtIBay9MMz6/6WVtZUxhxtmUXy2DDi72/m9WaT6Ob1Nr81CGfuHvQ7SO +zXFL8MVOvuCV385PcUvwyy4vlDOu0oqfznahN5crAV0rfWaMOkAz9KRt8ps631Nnuc8GfN+cCo6W +owH4cn4f8tlRGsXdZASLPuEgXf0wVdNxWXNrizwRVVlfvTGAufrCDGyFYcdyzerigdDlzJc9LGDz +Tg009qZgLkBX3EOVyueD4CI0d6p/VqTcsASxtifk2Ci2wVY/HQgiiWWZ7JufmPlZ4bhHP0tf5GX+ ++VF6YPJICV//hJFU9xXyUQK3itpXZg610ze7qFX0bHDn9aswNkayaIXcki7db+Umzju1WseRfj56 +jKBUchEsnNFxokUV3JenQbUr+PBotsGeG1NKOP+Q6G9j6YDpzrTwvMQueb78IEzLaemCk5S7GcM7 +81xVNGg0m1bwqqhNvlBSU2EZ5DCaTT9/b5xElwPi8eIIGPPNCNVwXGp0ipL6WPKvvQ6GTMaP3/6L +61mRK330sG5mPBn2/yTVgvwhwjKl2a76gU/w/kO7RdRqG+5pdunNvFBTMrD+dUjCvDDegfak7Jn8 +cfXwZd7ME+2aIfmR8jgHg+U+Fp8cWTDCfs54B+oMFxORGG8tceIfWXR3Gpbi9F2poLWmOxusvThL +32Xat77b5VWLpjxSHu9AD8t98wC5WlAbW5hxMsmf002Gx1BWVzX2AP1V0SCaO8Uq5AhIU5AZkND2 +hTkvO7f5WVWx/NE15sA8SMghOVIvD4CENnw/nepK2Rl8UEGeky84sz44O5qc7yy3FTsC2YrzQqG4 +ppy0b9DTGPTmBQEBAQEBAUHu8SdcfV4NCmVuZHN0cmVhbQplbmRvYmoKNSAwIG9iago8PAovVHlw +ZSAvWE9iamVjdAovU3VidHlwZSAvRm9ybQovRm9ybVR5cGUgMQovQkJveCBbIDAuMDAwMDAgLTQx +LjcxNTAzIDEwMDAuMDAwMDAgNDEuNzE1MDMgXQovUmVzb3VyY2VzIDw8IC9Qcm9jU2V0IFsvUERG +IC9UZXh0IC9JbWFnZUIgL0ltYWdlQyAvSW1hZ2VJXQo+PgovTGVuZ3RoIDMyNTgKL0ZpbHRlciAv +RmxhdGVEZWNvZGUgPj4Kc3RyZWFtCnjapVnNjhy9DbzPU8w5wDYkkRSlV8gt5yCnDYIg8R6+U14/ +VVR3U+OZnGLDdrtWP/xnSfrjUZ8Fv/H3oSq9P7UeXq3I8/vn8cejHK5WMeLoo4nxX9PJ/89SZ3/+ ++1GPwl/P/zz++jcs9PdHef4Zf/6FyeOoNjDpax6zWZ/Pn4T6MbuU9vz1sMNbKfUjhA/pVgHNo0vH +Dz9BFbK7jB5Y6YXrAxujlfEchzZq8FXrUWeFpI4VSvNAtJRen98PPzBLJbBeS2vPfrQpwwJZBrHD +imHnRL4fcvgocx/VDpXW1kqt1tqf2MWmaMjUiqhiHiQeXcM0dZo3GHSZ8QvSzTZrAnbMaaXGpBPS +0CR8tlZpEMOqbVsd7q4Nk2554Mo+vTxvkSFNhzNSrwv4fkD5pnUkBN8U9xgDO7nBiGadZi2HSbOB +SQPaqc7YqRZsPo5R6oidptfuz3mIjjopntQuNMQNNexgQ+HDAQt0xNYXRXcXrNNqgUkAlGFYGJvP +Ep4/ho7ZQmLMqTQ7/NeU/hOEGj1z6NTqUBPRRZ0u4PuhRxtlaEICdV1qLOwFC7fDxrQQrzcNg9Zj +1joQPnJAOoyphyGgwi3wk1oC6bobcrisKYPiXGUcCNimuRMsgrEWwXVJUw5EkvozBabrh7VNqwuh +LaD5C9Yh/SznPJVIAnjIPRCxOjWSQK3TgQzUXsbAqNHGmU4Qd5TnW05/P/75qFgNmipNoBPLIdMr +PKLde2ARX0AQeWuUaEG2Aeml0ApQbI7WaamOhK0tzIkNyuQoBPCJCO0JBHl7zpPTwoZPBPY2So+u +oywJYIVOpEn3QWQO89hPoKNZeAvZxFGCEJooJ6hIiOguG+JHVcTgmndiSHQrxQShWxtkbhHhn0Ch +IoW1K2d/whhIdGBg8FsPm5XID+rgndbAcMEnERfFVozIsdIB1qizrShFSNKKKJwaASZHaYJgp6WL +eklkWX+icL6MQpHVcxTWDD9WY9kBotXqmodIYREBZuLhW0REWfuhnENORklra8zsa95b5PxCPLUo +zGZR6ZyF4ufR0HqcMXljQMpEMMdchCsycXKMT/oSsi7/zqOpt8BsDtQwICj23BM1wgeGJ+JAWFli +3omNA22mxOrI3OJRtGVqzOvdWXXmAdmislOqcWUfMkwGBe3d5kosVE24ODW8IUxtB0pXrfs41J3p +82we3tFOGjzaWrG1qTrdBsyUPwzRhHuizNtAH6P4yD7ZkFQysc7QMX/mSsZGOGXbD0bFxLkkPcWi +6aWFoKfst3venPj94torwH64GoSA9W6MUtRaIqS1uGF9LDL6cva1GrDRUY4inUFTUK4Z9nPpUxBj +Y0M2rW8MrQa9Qp+5Emw6oNq2H31hbFHLzEsspLc0tIxnyp4MIH2bRAExgKr2AjKeMHVfrY5gH/Vl +V+TIFJ8zhQPSy9k9lgKJbBF8Y5cxcqXLYLlhmjXluo1/C3876M2N4VxsXivJBlq2CBrPz4ZlpWvY +FTbwzxhazGC5fMVQMFCJgVA0pS0MxAMuR8S3CUrKjgT6EYExwRwQxqu7gdV2DhvUfVkWjKU9BR+F +ZDYh9FywNuR238eBDNTpyyloU+jDgpKOXhn5NqQIsxcYhO0hiHTwJ44aQ21zUyLwBBiQrXknlsYQ +FHnoUj9jW2/JyZ9BCCwlODVAVLMTdEEfpDTVq64VKzqzUldwj7LWE2W5XzZB5VwxDn6JLIftQH18 +D3thkPg59Q57xFLvUQ3v9BioMGgbi3+jSxmhgh61auZAmYtkI8X0cZpdOkvYHUswcUj+HnGMQ4mS +7au6NkjcEYgbGMRAnFZBl5pSxv8AN+vfsz9hqII+grwCAyNfzRi9HH1HJsnKaoTo2+goQEAlta2G +XY3aAhvoRX01bJDupxamWNmqovKsRYayJZ2CE0eZzlGNJpSQXhupv+IDbH0RKJ5AOA98YsiIAxWK +BAIeiKCmS5SLTo6XSBaVxJibZc07V0J5Qp7oth9zqHo0txSLkQWlQ9JT9js4UsUtiNISGWy3uSIk +DZUorcoNkJx1mfU0PkMcFQ5Rf3uIiQDqW58f4oVhBPlmMMJb/58NQ8fsOARTC9Ba1CYSjAFGRQQ/ +ktUxq0XHhGLTRgnKqmiwRlVlNl2EBh130OPdm81EQoFpGJcYELI8y5Ug/nTH+WrbDxhMIDOlSiUv +yRNJ/ybGjwnGnyuh0prWvu0HjzeWg5DzlCqKJPlCis4w8I7kTA1vKExzGiLH3da6V0uj5qZp+ku0 +dM8l/rsT6VoD8ZGqgaL9waw/LxgOF8G/FWcin+6/YSYke0yBJqhCynNSWfQL7QY8QrF9YzNig0AF +jBBg75q+7IHzL4VDFxN5YXxW2LteoO8HwGleyj6uknmdp0OdrJlWg3KvyKaxYipO0aq+GhoYGgwA +CEXc1lR0QFRW6K4oO4tjYCLlTQy5U1DfeMHCudBnZVkbHUcT7tD6mXjKkAxJqvi6dTFrzlC24Axz +VYCOpFQqC67c9gpgccOgr+xJScbZ7bdKgQ46XNYWIgWCAIIr+3wxnXZmSRmnZvhQ1rfiqy2b2I44 +j8fRlhPDBw4JhaNYmM+SCcdzQ5DGEsnJnaklYwF5sNhT4y0N/Q7m7lmijadpny/syUg8qmznM9gV +ra3UbBNAHIUzCgQMqXJ6CfkahQWDEOgZxzjyDfK+92iPHGhsojXIMvhKlDdi6LTKuSiw0JpSGBk+ +EJzwLJzrep6+h6J3LOl5pI9iJpPHH7oWesxkltQaC71wTWUjlx2DtVClq6+V2C6ZSwjbsTQEizut +bLrKG4530ugLA6cP7wzjIZBIk+VBNOLw6rvOPG92RuZUz0b+k9h16/br0Ruv0Eb9BO38K5f7DF49 +JkAGkm+9qPOeLqx0dyxAsNuYL53NSGh5vZgd0Eg83V/uLBnivctLNpkTfL3b5G1NO6HVnY03aNrl +pYsbToWja8lmD0S8sUpchCCRrLiJXeQiV7oISG6YNCXlushMCn/nya3jlk23Ke5Rt70ugpVmTRqW +1r/IWrroInTv0RLZ1A93HWUnC4ld3Yj6oK9pdizog+63etjV14CNota29mfXCtkkoVEZ4wyeq5lS +TdCxvoHUE7HVt9Wo5hhj7ptCLeQDVb9ES0WvzRNJ1yZ28Ypc6eIeuV8ylBTr4jEp+8V1UsVkRGmJ +e9Rtrnul26i5X5r+kirdc0n+7kS69h9/evwlfv+xvZasCsDzivIs9f+/lrDyWsmlf27kCx/GfODL +CNqM2EeIjaAHdE/8AMFWcyJ9NggEDw2EV9A4H7bolLwv4FtGj/oOAH3I1nMC6MzKf5nkPkJfryOZ +DhZZYUVcJ/QFfKeIF7RJDQv25sEt7pkb1lhmdB8HajH1PCuqNDqB9e/kmUX5tMMLdxh8BCPDsc7o +izldgrRBAtCAG7gswgeWE0q73W8uH6D0wT3xHcpe8buD2Xlw6sTwFiFYlSH484KNyrj+9UDRG7yL +eIHQfHmyZkFkXA/e083wJ6ooPkhPyQupMnhhi+cWtGAN5g6mBuLH+ws77YT6OJ9xO+A7AmNWdiy3 +bVRll16XkL0Zb0d5yx1361h6LsYLzNXtvBJh1a8IF+i2Hr68QxIgXr3EgXK2um6ubiyezHpcBnFq +m2dlg+i8B8P60PiqgHzFoBi16xlEo0Rpo7RFTuaNQoQIYXMdXOPrTmFO4CIbFO9TYi/DBmpoKSsi +kS/4GXgGtpbdYqgjGtfoVKogTVhheL3NaBt8zLqBDslLVLYbAqdBtvHVDeq1Vf2ERM550e3r7Uk1 +3j0GL/o5ph2mAwFHw471WobKZ1GjEE19JhIWMWSvbqMa2b5HaUF68F0LrRO+PW/u7tcSr0WitKAx +o2dmtCo4v693l99iOt6IeD3GR9qveIhALPwEhmIyokxjLwkprK/HNK1thENxRFkdmU98Y0nfNY4D +AooXb0txgVUjdXkf56G1mPRE6MwOjrlBfC4e65qNDMeZMpVv0KFejwcpvnjFHT/4KHgvnz4HClB0 +qek4vcQr2XkuIBEZK/J/0zbeNRpJNeW+6sQPb1vR4XgvEq8RccJsQguW1+rIK9c2x3gB+UrR4lWE +DcuiMPDFZr0t7gNpYffyCiKWEWnxEoKTaby+8B1txJtc1jK+7oBTv9Q37uzxcmO8HQwNIWLzkDvH +vescluCGEw7fut0F7ZMRzMg1/4xt3e2e+wnbWt6N3T0PVp91laiz6TEhe+kvXQ+ZCKhl22s4+sn5 +gr96GhAUGet740tZs/Mltjv3nryDcKQxTBNshnoyW9m6HyCTUvWl/fGJA4emkf2vaRz6ezbARLID +JrYZErmAfG6fsc0x99wP2NYGf3f9r51i/RdK3KXLCmVuZHN0cmVhbQplbmRvYmoKNiAwIG9iago8 +PCAvTGVuZ3RoIDY1NzQKL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCnja7Vw7ky65bc2/ +X/HFqpo2H+ArtxI7khU4cDkal2vLmpFrI/19nwM2CfR8ffdhXSnR7q3dO3umSYIgAOLV/eMjPgP+ +4L9H4D/77/fPx48P/k/r8oz7l330IPuhPz3iEeNI7fmXx3/8J+b5r0d4/gv+/Z89by3xyKGP8KxS +j9ByHja3X/DzkaQfdcSYNvbhsLcU4iGjxwh4PXAL2ugfHv/9u8cf8OfHh21hpCG639I7lxLJUXQr +84lvbiWGNXMNFzbZL96KbcehrR01lpSf+4c3++0e4rD3R0pH7qU1j77O97ruu+PNnKI+91wvS9qo +lykd+Xuiu42+ey7vwV/+Xvi/PmL9OTbnb7H5D490y+h0w+hYypFykAv/HPme1SJHa7Hk78HqPdfr +mjbMiFtYumF2+gaz/7g4fcrvPaf/9KCkFxlAkkq4PYH9DPlFZ1HGOMYYbZxnkaWcIt/zEXotVTnU +U0uVIl/60bG78Xwb5RgC5X/GmA/sJ3eyV2AuAmhq8Ri9B2CjY9pYO7aWQVnsjWCEoUmd/MHiBcrf +EnYTSuH+Ugk41kLT0xPoebzhMdEV0jhyLNhcqoeUnHGm42gx5/qs7Wi5ZsFDR20NP+AgwjhCHPhZ +jlw6qIhFjloD2I/H2iihPGMPBwQgcmTAYwXm7n1pd4rn6ZAzH7dsUTOEM/uNZb+KZUvMsWBXsZYW +KoVXRkhbmCHE4ZfbbflqUF4voVsb8eFsjGH5/tHvR3j5NYR/RW5o+4b9S+Enn321UTY0v2C3TMn3 +C39HS/bzQhAHpLTF/kyxH/BZsOK0ZKkcEfKbSFs7cqYSfT7aoCzGAm0YeLwLPQxphyT+/i1mqGOm +2gCFWklvmKBX+DpJkvdQajlgO0ufD0qNCVoh5Sg5jkawH5IlRSdY0B6SgQlz1ouCq5DONmKgmulP +Opr2Ab+HTr9VLA5PKJ3Pvuxp26F/pA3/PUUsOxEDOQP0/CZi/zgi1qRECkztKfPSrZAnjTdwXdZf +Fl9gLx1G/4mA58DfcCMvoRIubfgHlaxk1COxGfRhkNBRKORtPbAlUnwD2UAwCx5HuYU2IW7kHVah +NzV2T8YN5EbahXCDGSE/wD84JOC84B7Aj6Hb83nBam9zkQRVjbl+wRIuHLg0iCJThrwBkREbRRBH +WCFCQMaoRd2enmod9FQyaII48qjhHVXc41GOxJtcoYJ9IRqCQIR6gejbY6VOd86eq0fMlAVCMhqW +AFRTqWkuUEfWoQ3umbpbkWYo0lvAXkKOcyi8wIjIBt5fL9QXuGkYqPRuDNxExN7pQmFsGZ3eFsDU +axVOR6dkQiI4HlJSOkzcPAg4anQrGRi0RJcMIGQeKol94bd9DoUOB8ZYOJBK7m5IWdeCXJ+D9wjz +O5fIOZAQeKswyP3KOrqnrdZzZ3B18cuWE8+0H63k4pHGwD0X9SsXBrJ7A6PJBU0KvIHEiIPXBdPA +fqEKECJ1nkEXluZTGSYI2vfkuUujdMAnhf/aeOytD0rHQvSIIfOju6cqnso89IzgDd40OY17JKs2 +ghTJ5ynBxhRieAh+rslx4TJ0pl+knSEfz01gObnDmhIE41OxnEbmWEQA3HXFHqXrbBDBoocrsctc +kT+dZxsTTZ6obaMDfyAU4H4QazQKIHbdsWAwBONoFIvHwC3Jyi3OFIqoLnUepu6wj3xyOZXRlCqs +k/hUqrnr6cDcIbik7oLJde5vzFN92TOtAcKJerHsCP9xawyZcc7y1hfkrcseegv6pFEC9bmr074X +qbyw8vCLLOgy3xp6C/pFMrhQgl5cJz8/H7gAweHSDMuM0/IYRKQG3F+ZoRUDQsp2gjWZYWAYdSgG +nQfTENXB4DPRhBusQSkcgsurIQyj57+xDitETGdi9gE6GPPAMlwPcphUK0MXmesNzDrVNzXGkSQ9 +luo12nbolBzgwPPeaGbVuprP2WpUaLTYZC4KleRISlnpJ2mZayLwpEYp+ZD37BDbpGFgBbbbnjYT +jDXCtOzWA1MxkEbVyCLrc9INnbTv43k5xPfL0S4D8cnZJKfoDAmpAGFJzU9osLaZi9dwUTtgLcak +ygmRhiuSocCCWF/NXaDRMMTtemMwnXCf5Gkzgae9QiNtPZ5F6XGcbJ5k0VprrtRo3zbdna3ZfshA +gKp6kAkKDPWzQeikjHFdNYHK3qojDohQomwDhjgJ3thihs20GGYLOrZuujbzN/H7gF6OkYcrsFW9 +U0PMG5N8gOR68VyY7Y61uXta/dKsrqd7TlMhbVzcr5LAqz6KH8ssi6R68dwKTFCpo14wXkEyrrav +8MchV1CgR13vP5hLHK9MqnsO7eqrCThZssgVfOEDrVqFOzNwd3urVhgWjeqUBAi0LhSzaqXzGVps +s2rA4EGGYlYNSMjC2ZdVM8RkwrBl1XQm6dmsmq5XevdWjVRB9MRZNSVdeMVta2U7dFatwnVBEFP9 +c/CcxvIOp1WrYFkKvPjMqgErIiOZVQMCeeR1vKyaIbZJw5ZVs5mWVbP1zKoZWcuqGe3reF4P8f1y +tGbVMBYKnBxGKsJo3RSrZghKCdXPBqzDcxRT0opfjjb3MxXZELfrjS2jYDMtw2HrOftiZG07ZLRv +a+XO1qwaZCAhGPIg5QmaM9xshZ56H9dVoZ/Q3uaIAwKJrNk2YIiT4I0tZthMi2G2oLHV6FrMN+L3 +Ab0cIw+3RTpnUWcTOGCR4Tq9aMlqSSXQn2xMk/T5VJYAr7Yx7u2i/glc4kRlaFSB3vXiRBABsQOC +rZ1IRmhFJFJaDcEZDa18RMNqZ0J52nJExhTWTusmcYa0Re1EbbyWo3rC0muaiWswa2gQGiDmDkGQ +JQiW5rgT8xEtI/7R0zfAfKSUgwbSe/QdJhjbNQYFxaGkNCOBUOCDA5GU52zQwKa7QjREvtJ489ae +3JAw548C4X0C6aOlaCdHTsN9u0QnwKpUkctTrVCwFMEBEumVARYRQdg8x8Hsng5KyS2z4oCgaDoo +cAigUZQSBArzmVHnuBfJ4T3QWDHAGToXumH/sG/ZecEb8szeQ29B70J3XpMSp3MMd5SXzcZc6gds +RhCU7iC/hk13D8KMF0bqCobcT7CVCOeyRy2RzBlnGNvJmVjnRnKplezqYH3Qi4eL4MYrT0AJgVt1 +Bqbh3mkrAbMMUesES/PPNRaKTohlnEYopXFmEUpsej81GhStorO2M2BHgKTegvrOuA6wuiFmiAyD +IaoIcZ82E0PrznF7QahtCmqIjC6G1omV7038Fsu9RxNeY8XCjF9Ug1SLY+sKtjFucx8HmxiK2hHB +tYdRGM9XaVHDx2zRKG7Xnw6jA8EqDvcziqhDBrsFacd+4Ced9w4ojfOAwNx0BjIsvnGTCYI2M0kw +VxC5rrWv2B2kG8csofnnmLUZK8jS2QA1eux+UWwL4jbLdpM02+gi3xA7WsMqn8IZ20zwtzpsj1uP +h13CyeqTLLBRalT5PWnHTVSZs7AtLuT9YZxYmLFrzWRMtfWM9YsqO55F+eshfulK+Ktzs+wzyZqc +Y24WQk61um9jYbYTHpazNgsBvY05FA9hd70yMcmaKzN4YEqm65ko7kklLpWmDip8mMbsGU+/8ZrB +zQMjPIUGDh5mpgryjjEEXgH8odSLw5gxKsVNxBx7HtkvVjWploygqtXpZCRvYG2LgybkLK0e7bhB +MAzxQy8ewvknhty4M4cWihG6RboJPNee5k6j9JPCWmueOVRcnxlePXs1ypnxFNpq48dCyMae0+Up +MB9OZXMzMRhsI13W00r2aEbUzlcvsq1AcW7t/bYpKcJ3xzVKgw/yugZJhhVsdV6jESEf7t9wwfBj +hGQYBqRLT5r8ibiAhWk/OBxNLV3PWS0kM864xE/rl2FHmbQcLaijMGpk04xD0jjTfhvDDazNADYT +w4tam1sv0v+Z4zZVEPXQWXTblK9d2/4W8n7DG+UYTwrhjlezNdjpGfOJswfirPMxL8uGgjeGYIP5 +Y1abQtbCSYe+lTMvi/BWSc2Dpw6EZkQ3nWKLHnGs2ZjQceWG9kwFfidz77ZeAWtkZkQ3VVA7eH3l +uQl/U8efmejNmoV41izsw7NrmaUP49YteMl0RjiCNSUviYaZ1KUME5pneL4x0fRvNwwIXIsqJokJ +v8KdJF4SWWnLeaYDpiQCwTWQh0miRxa7DVuSaDMtSbT1TBKNqiWJRvnate3PJPGVN2cCOjfexS43 +vAb7tsWDgmSGkMTHzPrDksRUEa6DRC+JCcEJDJGYJAKRUSWYJBriWLOxJYk205JEW88k0ahakrgJ +3zJmrDFJNNaYJDp2mdBtbt2CF0kc7OMUf5HmCvlAjOtbbhbEM4Gb1LQN5xgjqQ98gyEQw+HJHAvP +cqR7jAWYoHJtY+8w3phDixGZe58NWTeY3+/a2i3omSAMorPMmk6NkbVOoSXIVS8G5vi1xxC05Fl1 +DfSppVBCGfPhkBFx84xmOXye24h08IHAg+8zoTI6Qj2puNwix3U2danfJPClwMV4oZbJzJ0B3CAz +krGpz4IoO46J4SbgqhDJKgg0BDqdZNaIoYcgG0jp3Nyb+hgqicKiPOMLYDLgxz4lsZMylpnrY8TO +jGMbNRiCcYyAy2lLFftwmCM2D9zoMYx70A4Bi4DG6s9Fs7v0jnY3lrBo1DSNmyqW1QMoZZbV2VAw +5gFAqzVvhIsPl6GyuxeZ9gpsLw7J3Ns8OId1+mB8KrAePB1l+rmYG1GZzHSQtmjresyJqtxCXsBf +CkoYokYAwdsUnS8CpiltY9i+BQyDLRcYAM8bj2WW3f1zyi6ZNZHR2DyBVQObaIlUKRoOAJPUZy0l +R90lBT2JJhcQA7LD0CGbOxuDNwzj3542U2Kv3ZzpXI9eNd3s94dRRdOaEDoZ5WvXtj+7BV558/Gd +Q4v8K9o+Et3Zemn7KMzgVFXq0YpaITjoLV0bOqJWCOli32E+34ETCl8TIxs7oLfKAnbLlKi2L7cx +JYGiVS8Qmwy6piL2QIP+P70gcN3LmP0ccAVKmo7ziVkejs0acEDaPdYZD6m18tjAKpl+F+6mqKFR +gY1N6okhSNKYG7o0zlr46DnNZC+EsGoziEhcfR+ILxK9T3Bt9Yco5J0/ew7muLYzR5BwKTRCYKFo +rbMjNKvT3QSxooRkrVSxWQCa47LhhkAaEK6e7u2JOWawrqTF9TvMHYMNvgcDe6lU6NhVGVKeQdTs +x+AuEODPGWOgTQOUejo7VeApp7PdpOOQT6EYzGsAyhKKXNtN4Lf0dm03YaOB9i7Yc+y4iGcBDLcS +Ymj2dQxtk2aAl9pq8gFN9WR7ZurTZIkyHGe/0BeJo8FMsD1wktLVCRwlXZ3ABV16AdbQW/DiEXVe +zqeDCIlR/d+YndtsEQjtHuN9PKaDtsfeYZCgljQ1YdigrrJiy71L0HCc4XHQUiwuqSnFocmq4bJZ +aQbNcMeDFmNH00Km9jmxiwOOD/zQM9M1oXdH7wb9JjyrbLgDO/3f6KUUDjDch3YmX+H+VELQ7TqJ +GTGpKid6JXnpbYo4BECtSZjKF/CjQxabdOCJOXZCRFv9wuKN2fHY2DtsHffHjQicnSMth+IO/JNV ++4C7/qLQhjlW2eBb0Ea7dZxLvqZ0LrmtwjSgGnm3yCt2cXgj78/g43pRtZR8dcAmdKk/r6G34GUR +vlfRh3h+wcvNgS+uuR0b5mfcg29Bz6+Nus2sKd1mbJXNG7fIK+a3Utj0lWcBvECoGSAY5gv+8Pha +GvUbIGNBvrvhMZrXwoJksQaj2DoMLl9XipovnN1wWtoURhV1+qQhwK0HIuWMuRDdsWiZ2XUm1ZB3 +tidg2GzGOJ9ig1jrOk4Q9WYiCFhm89zybkuEhxX69G5bAcGFnb8jzj6YmL8guOE1QDDMM4JvZ8Qv +7RAG2qHa6DvMinzAGrxLVfwQw7mHxpK7FvmUi4kpnTbrFriVxuRGKH3WLcCoHMkzeDvB1UnA1yjc +nquT4ETg2HdXOwHSYSvUzOD/SQGTurHNrEqok4v0PoacxboCw2zSw6gBMeDzVca0+k+Wllh8G67H +VsttZfkiS/uC1axO1WrDrTTAefZyzTbcyru6z+T2asOt7EvJklwbbgUTU+3RN1qAY/D/47UhA+dQ +wqU3F1ApWsvabbiVzjN55dtwKwNnbZrcbbiVAVhJ0bXhVjJHOxGsDdcw14arY8NZGJxtuFU17JTJ +2YZLSnCPhksbbuUhSW2uDbeyUU2bPKxpIfOajtdWLG39qNfnQFOPp5s923DZCxBDHhfWFdywUMNm +bbhFK0vSrA3XEGvDNWy14XImXOXJ2nAra6haUrY2XMpCp6e923B57lWTmrtpIbONoV5ascAduM9T +w86nmOsqzVUGKxOrCPZ9G66eksZ9qw3X5Hi14b5Ku+pAYU6jJ9+GSwyRv1gbLqmAgSjWhlvZfRtK +9W24PNt8tuvPNlx2sgx2S1gfDo0OjYLvnEGMCm/CYeAWXNRerQ2XuoRTbb4Nl1wWzUytNlxqJQYm +a8MlEts8wdWG+7rn7x//Bjar4JE+EN8OrSQx/k1QSXaBOCf7RBDp5xLOQBRixFj3BmITTFVoD7yB +WF8cmjjaUD9YvIbfh7Nts2OSbTjwKpnx6mqkmHlLs5qU6hmVDdo2HFpgxZvucycTMy7WMSvFE3g3 +EhfkqIYq1tRmfmqNdFhiTCX+OW12HjO4QVym7zfBtJ/VqyBhvn3JN5KmxcV5aqAyhtZaO9+60TTr +CSyOsHp1Qsa3HZjfQHYGe+Ar5AKkLwesIT5bQmQWPvjGZJylno3B0JWZ42g9zeKjQVCuqLFvgzzL +s7OxbbYH425lkwY5VrXOOIpo5MGuuySzqCe8P4cmSSefOuLI+cpB84i+qsCe9uKeYsFBmxUHX+0I +s80dV7lKD6KTGXPi9KSVM4ZnvjMy8Smzzgt9ZuyPU0fgojEZgmel0jDeSaHO7EXWxosZhIF0KDzn +x45XG0Ec2pMPAyanEPWgTQNRC/ttSgguKkgIQ/SuRoMxsmj8Tm1uZ5vLhMgw1nH8Y4gORwhTIqEv +7EE5CpbOnmOVfWI9zU0FrR7nmmfJvnfGDxuoWubWq2FB6oBCpyq3N3up6PH1J7PM2q4Kiy+iGUJ9 +u5PPsB+SqSYytg+1GrgIC99tZVGuDkOUI7goorinEsu8TU0L1INlwcwW4XKGcrP5TE8mZDUt8AD5 +6seWVrrIbRbzvsj0+0xmwZDPim9j59RMZsFBmFY6YC1NSUg5e8IlsmoRmebUV1lYLRuaw6V/IOcd +ypRDfM6MS1TVZQKp6a6zvmSxEB5mxR3iICbE+wwj2TvUqDIxz94xuCLa3wcGQyrU181NEE/TXsjs +RJwJX77HrZ0BhU2q62WbL7v9mIkUXJqke9mJT+ahete2Q23yVQ8yZXIwXK1jwjWXVoPMAjEa7tZZ +5GhlNlvg6uJr8tcH1eM6PcQNQpYTqw8srYy2Ku5pRh5my5ix6iVc7BtXbqPMktvoukOQmJrSbc+9 +7lk5wQWH+87Ep0F+MIQ5aGR9h7nbbY+9w9yVt7F957HXMU4TdV56VMg68yH71oMmAkp27bHimKu4 +O40pmJBL9Ref0Wo3n2H+cPdgD+IgS67+Sa0KjxTc7ZfowIcol+uPb2/C1+12/7HUmc8XDOYFaIjd +gIY5RkIXoM/pHnMHs8feYJcXia5H/7erMPQm7M0N6aXCEAf7Oj9pcrUhdEMfBkWa9xIub3S+QsKG ++hkpH7322fH1AhVNuF/eDr2BeM9m0fcffJHgBTNif9C8LrQva8Um5vm6LGwmnKRkmM7S9fKk08s3 +IQNr2VlPS9SG0j6OmqZ9ZFomPCk8/DQGbR+ISAYUvXn7NKoT4vucMBPPPQsz+OwTsqVorcosDGyC +6IGc76ouopmgbryRbW8L0hx4ghkX/1xh+Jf8ZDTFWupwS1LVk3RHGFu5xnz9cNJuiG3QsMUFm2kx +ytYzbhpVm+dG+jqXl9N792d66f9pOfhmH8pPmy+klMj+c1rpMd/4Y1l83vO8m0Kdt7oKGW1+19Y7 +doryxQFD3J43RpeDWXGbqSN+qqW49dipneu555MqJp0RddfnpnyG/+o92q4XNC/1vF48OJ9j8348 +70HYkT4gXDiAGa2zO1y7aOnKiLq5bIenhxZoTJV2VtwNsA1uaHFhz7IYtVdy3Nz0bJ4vovexfD06 +LaAU7R+vXkcTU2dJnCwkrdBqeuKUFxZKYtbP1mypYuNJK9nJXlIC54sLUz4NsQ0btmTdZlr6YOuZ +1hhVS7cc5UsB3QZNUfnGaA/n9XU+x2TbmCHmOVljQnYGlHtJ9sWW2ZB8EtY1Gm+O+I24LW5sM2LP +tJm113Ms3VRtxhvp63BejvBysBc3BvawW04+qcffhgkNqAKgjdNbtOAVsLmrm/zxnb2hqeMloobY +ng1bimozLUW19UxRjaqtqJtyU0C3a1PUxDdFJXvt5Ve8gjryW1EhXXBIe/Camvj5Of1a01JVeJG4 +yKZUTl01xFmjjS1W2EyLXbaeY+oma7N+0e461a4nePuBt5/8ZtHM5nyjm8EEQ5N6WXxxZENvstKW +7pa/wZzL9Pz33z3//Ijf+AzSV9wmU+r+6d9+H57//L+6y+/+ucAeXr6q+K2PTrlm1vuvS/0k+A0H +8nt+k6///Jeo7r6Vlf7K3fw9P3pXf+7g3thYxQ4I99ktfugsJnbD7R9cu9h8+voFwFBqu7wlwM/j +IDDMt18FtNlfqbh8wmvPfGH6nttW8R/72oO+fhhxLvDlU2gnKbefS/y6B6Pn/YZ/W1B/Y+3fgrV/ +VBPwf9ELf20KZW5kc3RyZWFtCmVuZG9iago3IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9QYXJlbnQg +MyAwIFIKL01lZGlhQm94IFswIDAgMTAwMC4wMDAwMCAxMDAwLjAwMDAwXQovQmxlZWRCb3ggWzAu +MDAwMDAgMC4wMDAwMCAxMDAwLjAwMDAwIDEwMDAuMDAwMDBdCi9Dcm9wQm94IFswIDAgMTAwMC4w +MDAwMCAxMDAwLjAwMDAwXQovVHJpbUJveCBbMC4wMDAwMCAwLjAwMDAwIDEwMDAuMDAwMDAgMTAw +MC4wMDAwMF0KL0FydEJveCBbMC4wMDAwMCAwLjAwMDAwIDEwMDAuMDAwMDAgMTAwMC4wMDAwMF0K +L1JvdGF0ZSAwCi9Db250ZW50cyA2IDAgUgovVGh1bWIgNCAwIFIKPj4KZW5kb2JqCjggMCBvYmoK +PDwgL1Byb2NTZXQgWy9QREYgL1RleHQgL0ltYWdlQiAvSW1hZ2VDIC9JbWFnZUldCi9YT2JqZWN0 +IDw8Ci9SRTAgNSAwIFIKPj4KPj4KCmVuZG9iagozIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovS2lk +cyBbNyAwIFIgXQovQ291bnQgMQovUmVzb3VyY2VzIDggMCBSCj4+CmVuZG9iagp4cmVmCjAgOQow +MDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDEzNCAwMDAwMCBu +IAowMDAwMDEzNjUyIDAwMDAwIG4gCjAwMDAwMDAzNDMgMDAwMDAgbiAKMDAwMDAwMzEyMCAwMDAw +MCBuIAowMDAwMDA2NjAzIDAwMDAwIG4gCjAwMDAwMTMyNTAgMDAwMDAgbiAKMDAwMDAxMzU1OCAw +MDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDkKL1Jvb3QgMSAwIFIKL0luZm8gMiAwIFIKL0lEIFs8 +RDMzMDEzRDExMUQ3MDFFOTlCMjMzNDNGNzBFMDZBNUE+PEQzMzAxM0QxMTFENzAxRTk5QjIzMzQz +RjcwRTA2QTVBPl0KPj4Kc3RhcnR4cmVmCjEzNzI3CiUlRU9GCg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/cmd/scribus/e1f8033066a1e79d574f64111d5b92af.msg b/share/extensions/tests/data/cmd/scribus/e1f8033066a1e79d574f64111d5b92af.msg new file mode 100644 index 0000000..7e13c2e --- /dev/null +++ b/share/extensions/tests/data/cmd/scribus/e1f8033066a1e79d574f64111d5b92af.msg @@ -0,0 +1,13 @@ +Content-Type: multipart/mixed; boundary="--CALLDATA--//--CALLDATA--" +MIME-Version: 1.0 +Program: scribus +Arguments: --version -g + +----CALLDATA--//--CALLDATA-- +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: base64 + +U2NyaWJ1cyBWZXJzaW9uIDEuNS41Cg== + +----CALLDATA--//--CALLDATA---- diff --git a/share/extensions/tests/data/io/CADTextHeight.dxf b/share/extensions/tests/data/io/CADTextHeight.dxf new file mode 100644 index 0000000..a22afe4 --- /dev/null +++ b/share/extensions/tests/data/io/CADTextHeight.dxf @@ -0,0 +1,6566 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1012 + 9 +$DWGCODEPAGE + 3 +ansi_1252 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +81.3540207870886 + 20 +87.11210924039794 + 30 +0.0 + 9 +$EXTMAX + 10 +193.2058260736644 + 20 +192.5216389505478 + 30 +0.0 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$DRAGMODE + 70 + 2 + 9 +$LTSCALE + 40 +1.0 + 9 +$OSMODE + 70 + 37 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +TEXT + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DELOBJ + 70 + 1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937007874016 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMFIT + 70 + 3 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMUNIT + 70 + 2 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +10.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2459161.676118333 + 9 +$TDUPDATE + 40 +2459161.67611985 + 9 +$TDINDWG + 40 +0.0000000116 + 9 +$TDUSRTIMER + 40 +0.0000000116 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$COORDS + 70 + 1 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$ATTDIA + 70 + 0 + 9 +$ATTREQ + 70 + 1 + 9 +$HANDLING + 70 + 1 + 9 +$HANDSEED + 5 +E5 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.000000000000000E+20 + 20 +1.000000000000000E+20 + 30 +1.000000000000000E+20 + 9 +$PEXTMAX + 10 +-1.000000000000000E+20 + 20 +-1.000000000000000E+20 + 30 +-1.000000000000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$PICKSTYLE + 70 + 1 + 9 +$CMLSTYLE + 2 +STANDARD + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$SAVEIMAGES + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SUN + 2 +AcDbSun + 3 +SCENEOE + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +ObjectDBX Classes + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +ObjectDBX Classes + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +ObjectDBX Classes + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +29 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +141.3839179859085 + 22 +132.4655035067433 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +143.6893817658992 + 41 +2.128440366972477 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 7 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +6E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +2.032 + 49 +1.016 + 74 + 0 + 49 +-1.016 + 74 + 0 + 0 +LTYPE + 5 +6F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +13.208 + 49 +8.128 + 74 + 0 + 49 +-1.524 + 74 + 0 + 49 +2.032 + 74 + 0 + 49 +-1.524 + 74 + 0 + 0 +LTYPE + 5 +70 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HIDDEN2 + 70 + 0 + 3 +Hidden (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +4.762499999999999 + 49 +3.175 + 74 + 0 + 49 +-1.5875 + 74 + 0 + 0 +LTYPE + 5 +71 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _ + 72 + 65 + 73 + 2 + 40 +9.652 + 49 +8.128 + 74 + 0 + 49 +-1.524 + 74 + 0 + 0 +LTYPE + 5 +72 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 + 0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ + 72 + 65 + 73 + 6 + 40 +14.732 + 49 +8.128 + 74 + 0 + 49 +-1.524 + 74 + 0 + 49 +1.016 + 74 + 0 + 49 +-1.524 + 74 + 0 + 49 +1.016 + 74 + 0 + 49 +-1.524 + 74 + 0 + 0 +LTYPE + 5 +73 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +11.176 + 49 +8.128 + 74 + 0 + 49 +-1.524 + 74 + 0 + 49 +0.0 + 74 + 0 + 49 +-1.524 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 15 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +74 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +OUTLINE + 70 + 0 + 62 + 3 + 6 +CONTINUOUS + 0 +LAYER + 5 +75 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +AXIS + 70 + 0 + 62 + 7 + 6 +DASHDOT + 0 +LAYER + 5 +76 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DIMENSION + 70 + 0 + 62 + 1 + 6 +CONTINUOUS + 0 +LAYER + 5 +77 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +HATCH + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +78 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +AUXILARY + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +79 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +INVISIBLE + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +7A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +TEXT + 70 + 0 + 62 + 1 + 6 +CONTINUOUS + 0 +LAYER + 5 +7B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +T1 + 70 + 0 + 62 + 5 + 6 +CONTINUOUS + 0 +LAYER + 5 +7C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +T2 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +7D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +T5 + 70 + 0 + 62 + 2 + 6 +CONTINUOUS + 0 +LAYER + 5 +7E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +T8 + 70 + 0 + 62 + 1 + 6 +CONTINUOUS + 0 +LAYER + 5 +7F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DASH + 70 + 0 + 62 + 7 + 6 +DOT + 0 +LAYER + 5 +80 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DASHT1 + 70 + 0 + 62 + 5 + 6 +DOT + 0 +LAYER + 5 +81 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +HATCHT3 + 70 + 0 + 62 + 4 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 33 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +82 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE01 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +83 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE02 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +84 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE03 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +85 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE04 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +86 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE05 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +87 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE06 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +88 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE07 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +89 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE08 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +8A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE09 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +STYLE + 5 +8B +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE10 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Sans Serif.ttf + 4 + +1001 +ACAD +1000 +Sans Serif +1071 + 0 + 0 +STYLE + 5 +8C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE11 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Sans Serif.ttf + 4 + +1001 +ACAD +1000 +Sans Serif +1071 + 16777216 + 0 +STYLE + 5 +8D +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE12 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +DejaVu Sans.ttf + 4 + +1001 +ACAD +1000 +DejaVu Sans +1071 + 0 + 0 +STYLE + 5 +8E +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE13 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +DejaVu Sans.ttf + 4 + +1001 +ACAD +1000 +DejaVu Sans +1071 + 16777216 + 0 +STYLE + 5 +8F +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE14 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +DejaVu Sans Mono.ttf + 4 + +1001 +ACAD +1000 +DejaVu Sans Mono +1071 + 0 + 0 +STYLE + 5 +90 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE15 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +DejaVu Sans Mono.ttf + 4 + +1001 +ACAD +1000 +DejaVu Sans Mono +1071 + 16777216 + 0 +STYLE + 5 +91 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE16 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Arial.ttf + 4 + +1001 +ACAD +1000 +Arial +1071 + 0 + 0 +STYLE + 5 +92 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE17 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Arial.ttf + 4 + +1001 +ACAD +1000 +Arial +1071 + 16777216 + 0 +STYLE + 5 +93 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE18 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Liberation Sans.ttf + 4 + +1001 +ACAD +1000 +Liberation Sans +1071 + 0 + 0 +STYLE + 5 +94 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE19 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Liberation Sans.ttf + 4 + +1001 +ACAD +1000 +Liberation Sans +1071 + 16777216 + 0 +STYLE + 5 +95 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE20 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Liberation Mono.ttf + 4 + +1001 +ACAD +1000 +Liberation Mono +1071 + 0 + 0 +STYLE + 5 +96 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE21 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Liberation Mono.ttf + 4 + +1001 +ACAD +1000 +Liberation Mono +1071 + 16777216 + 0 +STYLE + 5 +97 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE22 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Monospace.ttf + 4 + +1001 +ACAD +1000 +Monospace +1071 + 0 + 0 +STYLE + 5 +98 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE23 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Monospace.ttf + 4 + +1001 +ACAD +1000 +Monospace +1071 + 16777216 + 0 +STYLE + 5 +99 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE24 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +URW Gothic L.ttf + 4 + +1001 +ACAD +1000 +URW Gothic L +1071 + 0 + 0 +STYLE + 5 +9A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE25 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +URW Gothic L.ttf + 4 + +1001 +ACAD +1000 +URW Gothic L +1071 + 16777216 + 0 +STYLE + 5 +9B +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE26 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Waree.ttf + 4 + +1001 +ACAD +1000 +Waree +1071 + 0 + 0 +STYLE + 5 +9C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE27 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Waree.ttf + 4 + +1001 +ACAD +1000 +Waree +1071 + 16777216 + 0 +STYLE + 5 +9D +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE28 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Nimbus Mono L.ttf + 4 + +1001 +ACAD +1000 +Nimbus Mono L +1071 + 0 + 0 +STYLE + 5 +9E +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE29 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Nimbus Sans L.ttf + 4 + +1001 +ACAD +1000 +Nimbus Sans L +1071 + 0 + 0 +STYLE + 5 +9F +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE30 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Nimbus Sans L.ttf + 4 + +1001 +ACAD +1000 +Nimbus Sans L +1071 + 16777216 + 0 +STYLE + 5 +A0 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE31 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Serif.ttf + 4 + +1001 +ACAD +1000 +Serif +1071 + 0 + 0 +STYLE + 5 +A1 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +VCDSTYLE32 + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Serif.ttf + 4 + +1001 +ACAD +1000 +Serif +1071 + 16777216 + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +E4 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_MLEADERVER + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +A2 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.6 + 20 +122.184 + 30 +0.0 + 11 +135.095 + 21 +124.9965 + 31 +0.0 + 0 +LINE + 5 +A3 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.105 + 20 +124.9965 + 30 +0.0 + 11 +134.6 + 21 +122.184 + 31 +0.0 + 0 +LINE + 5 +A4 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.6 + 20 +120.0 + 30 +0.0 + 11 +134.105 + 21 +117.1875 + 31 +0.0 + 0 +LINE + 5 +A5 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +135.095 + 20 +117.1875 + 30 +0.0 + 11 +134.6 + 21 +120.0 + 31 +0.0 + 0 +LINE + 5 +A6 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +90.0 + 20 +112.6000000000002 + 30 +0.0 + 11 +92.8125 + 21 +112.1050000000002 + 31 +0.0 + 0 +LINE + 5 +A7 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +92.8125 + 20 +113.0950000000002 + 30 +0.0 + 11 +90.0 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +A8 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +117.998 + 20 +112.6000000000002 + 30 +0.0 + 11 +115.1855 + 21 +113.0950000000002 + 31 +0.0 + 0 +LINE + 5 +A9 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +115.1855 + 20 +112.1050000000002 + 30 +0.0 + 11 +117.998 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +AA +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +141.4 + 20 +112.6000000000002 + 30 +0.0 + 11 +144.2125 + 21 +112.1050000000002 + 31 +0.0 + 0 +LINE + 5 +AB +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +144.2125 + 20 +113.0950000000002 + 30 +0.0 + 11 +141.4 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +AC +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +140.0 + 20 +112.6000000000002 + 30 +0.0 + 11 +137.1875 + 21 +113.0950000000002 + 31 +0.0 + 0 +LINE + 5 +AD +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +137.1875 + 20 +112.1050000000002 + 30 +0.0 + 11 +140.0 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +AE +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +84.6 + 20 +120.0 + 30 +0.0 + 11 +85.095 + 21 +122.8125 + 31 +0.0 + 0 +LINE + 5 +AF +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +84.10499999999999 + 20 +122.8125 + 30 +0.0 + 11 +84.6 + 21 +120.0 + 31 +0.0 + 0 +LINE + 5 +B0 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +84.6 + 20 +163.687 + 30 +0.0 + 11 +84.10499999999999 + 21 +160.8745 + 31 +0.0 + 0 +LINE + 5 +B1 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +85.095 + 20 +160.8745 + 30 +0.0 + 11 +84.6 + 21 +163.687 + 31 +0.0 + 0 +LINE + 5 +B2 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +84.6 + 20 +120.0 + 30 +0.0 + 11 +84.6 + 21 +163.687 + 31 +0.0 + 0 +LINE + 5 +B3 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +135.78125 + 20 +112.6000000000002 + 30 +0.0 + 11 +140.0 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +B4 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +141.4 + 20 +112.6000000000002 + 30 +0.0 + 11 +149.887961368316 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +B5 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +90.0 + 20 +112.6000000000002 + 30 +0.0 + 11 +117.998 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +B6 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.6 + 20 +115.78125 + 30 +0.0 + 11 +134.6 + 21 +120.0 + 31 +0.0 + 0 +LINE + 5 +B7 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.6 + 20 +122.184 + 30 +0.0 + 11 +134.6 + 21 +134.6526253819066 + 31 +0.0 + 0 +TEXT + 5 +B8 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbText + 10 +133.6 + 20 +125.6758475341707 + 30 +0.0 + 40 +2.25 + 1 +2.184 + 50 +90.0 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +LINE + 5 +B9 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +134.6 + 20 +120.0 + 30 +0.0 + 11 +134.6 + 21 +122.184 + 31 +0.0 + 0 +LINE + 5 +BA +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +139.0 + 20 +122.184 + 30 +0.0 + 11 +133.6 + 21 +122.184 + 31 +0.0 + 0 +LINE + 5 +BB +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +139.0 + 20 +120.0 + 30 +0.0 + 11 +133.6 + 21 +120.0 + 31 +0.0 + 0 +TEXT + 5 +BC +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbText + 10 +100.1052306607185 + 20 +113.6000000000002 + 30 +0.0 + 40 +2.25 + 1 +27.998 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +LINE + 5 +BD +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +117.998 + 20 +119.0 + 30 +0.0 + 11 +117.998 + 21 +111.6000000000002 + 31 +0.0 + 0 +LINE + 5 +BE +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +90.0 + 20 +119.0 + 30 +0.0 + 11 +90.0 + 21 +111.6000000000002 + 31 +0.0 + 0 +TEXT + 5 +BF +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbText + 10 +144.4437565674345 + 20 +113.6000000000002 + 30 +0.0 + 40 +2.25 + 1 +1.4 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +LINE + 5 +C0 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +140.0 + 20 +112.6000000000002 + 30 +0.0 + 11 +141.4 + 21 +112.6000000000002 + 31 +0.0 + 0 +LINE + 5 +C1 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +141.4 + 20 +119.0 + 30 +0.0 + 11 +141.4 + 21 +111.6000000000002 + 31 +0.0 + 0 +LINE + 5 +C2 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +140.0 + 20 +119.0 + 30 +0.0 + 11 +140.0 + 21 +111.6000000000002 + 31 +0.0 + 0 +TEXT + 5 +C3 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbText + 10 +83.6 + 20 +137.8176260494453 + 30 +0.0 + 40 +2.25 + 1 +43.687 + 50 +90.0 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +LINE + 5 +C4 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +89.0 + 20 +163.687 + 30 +0.0 + 11 +83.6 + 21 +163.687 + 31 +0.0 + 0 +LINE + 5 +C5 +330 +1F +100 +AcDbEntity + 8 +DIMENSION +100 +AcDbLine + 10 +89.0 + 20 +120.0 + 30 +0.0 + 11 +83.6 + 21 +120.0 + 31 +0.0 + 0 +TEXT + 5 +C6 +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +133.5999999999997 + 20 +185.4919999999992 + 30 +0.0 + 40 +3.0 + 1 +Text height for L: 2.25 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +C7 +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +133.5999999999997 + 20 +189.5269999999992 + 30 +0.0 + 40 +3.0 + 1 +CAD + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +C8 +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +83.59999999999991 + 20 +185.4919999999992 + 30 +0.0 + 40 +3.0 + 1 +Text height for L: 45.0 + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +C9 +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +83.59999999999991 + 20 +189.5269999999992 + 30 +0.0 + 40 +3.0 + 1 +CAD + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CA +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +83.59999999999991 + 20 +172.6919999999989 + 30 +0.0 + 40 +3.0 + 1 +CAD text height 3 mm corresponds to 12 pt = 16 px in svg + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CB +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +83.59999999999991 + 20 +176.7269999999989 + 30 +0.0 + 40 +3.0 + 1 +Text written in this file: + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CC +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +83.59999999999991 + 20 +88.00000000000016 + 30 +0.0 + 40 +3.0 + 1 +text scale factor = (240 x 25.4)/(45.0 x 96) = 1.411... + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CD +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +90.0 + 20 +100.8000000000002 + 30 +0.0 + 40 +3.0 + 1 +180 pt = 240 px + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CE +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +133.5999999999997 + 20 +100.8000000000002 + 30 +0.0 + 40 +3.0 + 1 +9 pt = 12 px + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +CF +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +139.7407033025464 + 20 +119.9974126092812 + 30 +0.0 + 40 +2.25 + 1 +L + 7 +VCDSTYLE18 +100 +AcDbText + 0 +TEXT + 5 +D0 +330 +1F +100 +AcDbEntity + 8 +TEXT +100 +AcDbText + 10 +84.79086674317226 + 20 +119.9534009496834 + 30 +0.0 + 40 +45.0 + 1 +L + 7 +VCDSTYLE18 +100 +AcDbText + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MATERIAL +350 +43 + 3 +ACAD_MLEADERSTYLE +350 +6B + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACAD_SCALELIST +350 +47 + 3 +ACAD_VISUALSTYLE +350 +2A + 3 +ACDBVARIABLEDICTIONARY +350 +D1 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +1A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +43 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +BYBLOCK +350 +45 + 3 +BYLAYER +350 +44 + 3 +GLOBAL +350 +46 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +6B +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +6C +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +17 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +19 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +47 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +A0 +350 +48 + 3 +A1 +350 +49 + 3 +A2 +350 +4A + 3 +A3 +350 +4B + 3 +A4 +350 +4C + 3 +A5 +350 +4D + 3 +A6 +350 +4E + 3 +A7 +350 +4F + 3 +A8 +350 +50 + 3 +A9 +350 +51 + 3 +B0 +350 +52 + 3 +B1 +350 +53 + 3 +B2 +350 +54 + 3 +B3 +350 +55 + 3 +B4 +350 +56 + 3 +B5 +350 +57 + 3 +B6 +350 +58 + 3 +B7 +350 +59 + 3 +B8 +350 +5A + 3 +B9 +350 +5B + 3 +C0 +350 +5C + 3 +C1 +350 +5D + 3 +C2 +350 +5E + 3 +C3 +350 +5F + 3 +C4 +350 +60 + 3 +C5 +350 +61 + 3 +C6 +350 +62 + 3 +C7 +350 +63 + 3 +C8 +350 +64 + 3 +C9 +350 +65 + 3 +D0 +350 +66 + 3 +D1 +350 +67 + 3 +D2 +350 +68 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +2A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +2DWIREFRAME +350 +2F + 3 +BASIC +350 +32 + 3 +BRIGHTEN +350 +36 + 3 +COLORCHANGE +350 +3A + 3 +CONCEPTUAL +350 +34 + 3 +DIM +350 +35 + 3 +EDGECOLOROFF +350 +3D + 3 +FACEPATTERN +350 +39 + 3 +FLAT +350 +2B + 3 +FLATWITHEDGES +350 +2C + 3 +GOURAUD +350 +2D + 3 +GOURAUDWITHEDGES +350 +2E + 3 +HIDDEN +350 +31 + 3 +JITTEROFF +350 +3B + 3 +LINEPATTERN +350 +38 + 3 +OVERHANGOFF +350 +3C + 3 +REALISTIC +350 +33 + 3 +SHADED +350 +42 + 3 +SHADED_WITH_EDGES +350 +41 + 3 +SHADES_OF_GRAY +350 +3E + 3 +SKETCHY +350 +3F + 3 +THICKEN +350 +37 + 3 +WIREFRAME +350 +30 + 3 +X-RAY +350 +40 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +D1 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +CANNOSCALE +350 +DC + 3 +CENTEREXE +350 +D8 + 3 +CENTERLTYPEFILE +350 +D9 + 3 +CMLEADERSTYLE +350 +D3 + 3 +CTABLESTYLE +350 +D2 + 3 +DIMASSOC +350 +DA + 3 +HIDETEXT +350 +DB + 3 +MSLTSCALE +350 +DD + 3 +PSOLHEIGHT +350 +D5 + 3 +PSOLWIDTH +350 +D4 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +MATERIAL + 5 +45 +102 +{ACAD_REACTORS +330 +43 +102 +} +102 +{ACAD_XDICTIONARY +360 +E0 +102 +} +330 +43 +100 +AcDbMaterial + 1 +BYBLOCK + 0 +MATERIAL + 5 +44 +102 +{ACAD_REACTORS +330 +43 +102 +} +102 +{ACAD_XDICTIONARY +360 +DE +102 +} +330 +43 +100 +AcDbMaterial + 1 +BYLAYER + 0 +MATERIAL + 5 +46 +102 +{ACAD_REACTORS +330 +43 +102 +} +102 +{ACAD_XDICTIONARY +360 +E2 +102 +} +330 +43 +100 +AcDbMaterial + 1 +GLOBAL + 0 +ACAD_PROXY_OBJECT + 5 +6C +102 +{ACAD_REACTORS +330 +6B +102 +} +330 +6B +100 +AcDbZombieObject + 90 + 499 + 91 + 505 + 93 + 610 +310 +40901902A4063FBFFFFFE0000000000000020400000000000020404214DD185B99185C990000000000000104090141901A00000000000004100000000000000041025764000000000000039000 +340 +14 +340 +0 +340 +11 +340 +0 + 94 + 0 +1001 +ACAD_MLEADERVER +1070 + 2 + 0 +MLINESTYLE + 5 +18 +102 +{ACAD_REACTORS +330 +17 +102 +} +330 +17 +100 +AcDbMlineStyle + 2 +Standard + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 2 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 0 +ACAD_PROXY_OBJECT + 5 +48 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 41 +310 +903313A31580 + 0 +ACAD_PROXY_OBJECT + 5 +49 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903313A324000000000000004000 + 0 +ACAD_PROXY_OBJECT + 5 +4A +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903313A344000000000000104000 + 0 +ACAD_PROXY_OBJECT + 5 +4B +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903313A354000000000000144000 + 0 +ACAD_PROXY_OBJECT + 5 +4C +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903313A384000000000000204000 + 0 +ACAD_PROXY_OBJECT + 5 +4D +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A31304000000000000244000 + 0 +ACAD_PROXY_OBJECT + 5 +4E +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A31364000000000000304000 + 0 +ACAD_PROXY_OBJECT + 5 +4F +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A32304000000000000344000 + 0 +ACAD_PROXY_OBJECT + 5 +50 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A333040000000000003E4000 + 0 +ACAD_PROXY_OBJECT + 5 +51 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A34304000000000000444000 + 0 +ACAD_PROXY_OBJECT + 5 +52 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +904313A35304000000000000494000 + 0 +ACAD_PROXY_OBJECT + 5 +53 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 121 +310 +905313A3130304000000000000594000 + 0 +ACAD_PROXY_OBJECT + 5 +54 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903323A310000000000000010100 + 0 +ACAD_PROXY_OBJECT + 5 +55 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903343A310000000000000410100 + 0 +ACAD_PROXY_OBJECT + 5 +56 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 105 +310 +903383A310000000000000810100 + 0 +ACAD_PROXY_OBJECT + 5 +57 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 113 +310 +90431303A310000000000000910100 + 0 +ACAD_PROXY_OBJECT + 5 +58 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 121 +310 +9053130303A310000000000001650100 + 0 +ACAD_PROXY_OBJECT + 5 +59 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 257 +310 +90E312F31323822203D2031272D3022000000000000200FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5A +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D312F363422203D2031272D3022000000000000240FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5B +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D312F333222203D2031272D3022000000000000280FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5C +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D312F313622203D2031272D30220000000000002C0FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5D +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D332F333222203D2031272D30220000000000002E0FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5E +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 241 +310 +90C312F3822203D2031272D3022000000000000300FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +5F +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D332F313622203D2031272D3022000000000000320FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +60 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 241 +310 +90C312F3422203D2031272D3022000000000000340FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +61 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 241 +310 +90C332F3822203D2031272D3022000000000000360FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +62 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 241 +310 +90C312F3222203D2031272D3022000000000000380FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +63 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 241 +310 +90C332F3422203D2031272D30220000000000003A0FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +64 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 161 +310 +90A3122203D2031272D30224000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +65 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 257 +310 +90E312D312F3222203D2031272D30220000000000003E0FC000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +66 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 225 +310 +90A3322203D2031272D302200000000000002100000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +67 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 225 +310 +90A3622203D2031272D302200000000000006100000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +68 +102 +{ACAD_REACTORS +330 +47 +102 +} +330 +47 +100 +AcDbZombieObject + 90 + 499 + 91 + 503 + 93 + 249 +310 +90D31272D3022203D2031272D30220000000000000A100000000000000284000 + 0 +ACAD_PROXY_OBJECT + 5 +2F +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 436 +310 +42CC9915DA5C99599C985B595049028333333333333E33F0000000000000F90107901411070040501600405405064090741402480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +32 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 388 +310 +4150985CDA58D07406404333333333333E33F0000000000000F90107A41107004050150841D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +36 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 428 +310 +42109C9A59DA1D195B90C409028333333333333E33F0000000000000F9010790141107004050150841D405064090741402480A029950 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3A +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 452 +310 +42D0DBDB1BDC90DA185B99D95104090240C333333333333E33F0000000000000F90108901411070040501508421405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +34 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 500 +310 +4290DBDB98D95C1D1D585B10940D028333333333333E33F0000000000000F90107902409070040501000000000018199010841D405064090740C02480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +35 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 412 +310 +40D11A5B50B409028333333333333E33F0000000000000F9010790141107004050150841D405064090741402480A02677FFFFFD0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3D +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 452 +310 +43115919D950DBDB1BDC93D999916409028333333333333E33F0000000000000F9010790141107004050150841D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +39 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 444 +310 +42D19858D95C185D1D195C9B90F409028333333333333E33F0000000000000F9010790141107004050150841D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +2B +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 380 +310 +41119B185D240901404333333333333E33F0000000000000F9010740A907004050150841D405064090741402480A1B50 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +2C +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 468 +310 +43519B185D15DA5D1A115919D95CD0140901404333333333333E33F0000000000000F90107409019070040501600405405064090741402480A1B50 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +2D +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 404 +310 +41D1DBDD5C985D5910240902404333333333333E33F0000000000000F9010740A9070040501641D405064090741402480A1B50 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +2E +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 492 +310 +4411DBDD5C985D5915DA5D1A115919D95CD0340902404333333333333E33F0000000000000F90107409019070040501600405405064090741402480A1B50 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +31 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 476 +310 +41921A5919195B90640502408333333333333E33F0000000000000F901079024090700405020000000000001110200405405064090740C02480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3B +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 428 +310 +42529A5D1D195C93D999914409028333333333333E33F0000000000000F9010790141107004050150A41D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +38 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 444 +310 +42D31A5B995C185D1D195C9B90E409028333333333333E33F0000000000000F9010790141107004050750841D405064090741402483A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3C +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 444 +310 +42D3DD995C9A185B99D3D999915409028333333333333E33F0000000000000F9010790141107004050150941D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +33 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 428 +310 +425499585B1A5CDD1A58D08409038333333333333E33F0000000000000F9010740A907004050150800405405064090740C02480A1B40 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +42 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 420 +310 +4194DA1859195911B40902404333333333333E33F0000000000000F9010740A41107004050150800405405064090840C02480A0B40 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +41 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 516 +310 +4454DA18591959081DDA5D1A08195919D95CD1A40902404333333333333E33F0000000000000F901074090142907004050250800405405064090740C02480A0B40 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3E +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 532 +310 +4394DA1859195CC81BD98811DC985E5174090240C333333333333E33F0000000000000F901079024090741D01000000000000111010841D405064090740C02480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +3F +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 476 +310 +41D4DAD95D18DA1E51840502408333333333333E33F0000000000000F901079024090741D01000000000000111010B41D405064090741802480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +37 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 412 +310 +41D51A1A58DAD95B90D409028333333333333E33F0000000000000F9010790141107004050150C41D405064090741402480A0350 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +30 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 420 +310 +4255DA5C99599C985B595059028333333333333E33F0000000000000F90107901411070040501600405405064090740C02480A0340 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +ACAD_PROXY_OBJECT + 5 +40 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbZombieObject + 90 + 499 + 91 + 501 + 93 + 404 +310 +41560B54985E51940902404000000000000E03F0000000000000F9010740501907004050150841D405064090740C02480A1B40 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +DICTIONARYVAR + 5 +DC +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +1:1 + 0 +DICTIONARYVAR + 5 +D8 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +3.500000 + 0 +DICTIONARYVAR + 5 +D9 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +acadiso.lin + 0 +DICTIONARYVAR + 5 +D3 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +Standard + 0 +DICTIONARYVAR + 5 +D2 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +Standard + 0 +DICTIONARYVAR + 5 +DA +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +2 + 0 +DICTIONARYVAR + 5 +DB +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +1 + 0 +DICTIONARYVAR + 5 +DD +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +1 + 0 +DICTIONARYVAR + 5 +D5 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +80.000000 + 0 +DICTIONARYVAR + 5 +D4 +102 +{ACAD_REACTORS +330 +D1 +102 +} +330 +D1 +100 +DictionaryVariables +280 + 0 + 1 +5.000000 + 0 +DICTIONARY + 5 +E0 +330 +45 +100 +AcDbDictionary + 3 +ACAD_XREC_ROUNDTRIP +360 +E1 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 1 + 0 +DICTIONARY + 5 +DE +330 +44 +100 +AcDbDictionary + 3 +ACAD_XREC_ROUNDTRIP +360 +DF +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 1 + 0 +DICTIONARY + 5 +E2 +330 +46 +100 +AcDbDictionary + 3 +ACAD_XREC_ROUNDTRIP +360 +E3 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 1 + 0 +XRECORD + 5 +E1 +102 +{ACAD_REACTORS +330 +E0 +102 +} +330 +E0 +100 +AcDbXrecord +102 +MATERIAL +148 +0.0 +149 +0.0 +149 +0.0 + 93 + 0 + 94 + 127 +282 + 0 + 72 + 1 + 77 + 1 +171 + 1 +175 + 1 +179 + 1 +273 + 0 + 0 +XRECORD + 5 +DF +102 +{ACAD_REACTORS +330 +DE +102 +} +330 +DE +100 +AcDbXrecord +102 +MATERIAL +148 +0.0 +149 +0.0 +149 +0.0 + 93 + 0 + 94 + 127 +282 + 0 + 72 + 1 + 77 + 1 +171 + 1 +175 + 1 +179 + 1 +273 + 0 + 0 +XRECORD + 5 +E3 +102 +{ACAD_REACTORS +330 +E2 +102 +} +330 +E2 +100 +AcDbXrecord +102 +MATERIAL +148 +0.0 +149 +0.0 +149 +0.0 + 93 + 0 + 94 + 127 +282 + 0 + 72 + 1 + 77 + 1 +171 + 1 +175 + 1 +179 + 1 +273 + 0 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/PAGE_001.DHW b/share/extensions/tests/data/io/PAGE_001.DHW new file mode 100644 index 0000000..e291794 Binary files /dev/null and b/share/extensions/tests/data/io/PAGE_001.DHW differ diff --git a/share/extensions/tests/data/io/PGLT_161.DHW b/share/extensions/tests/data/io/PGLT_161.DHW new file mode 100644 index 0000000..63b1481 Binary files /dev/null and b/share/extensions/tests/data/io/PGLT_161.DHW differ diff --git a/share/extensions/tests/data/io/PGLT_162.DHW b/share/extensions/tests/data/io/PGLT_162.DHW new file mode 100644 index 0000000..6119ee8 Binary files /dev/null and b/share/extensions/tests/data/io/PGLT_162.DHW differ diff --git a/share/extensions/tests/data/io/PGLT_163.DHW b/share/extensions/tests/data/io/PGLT_163.DHW new file mode 100644 index 0000000..a7d52a6 Binary files /dev/null and b/share/extensions/tests/data/io/PGLT_163.DHW differ diff --git a/share/extensions/tests/data/io/color.dxf b/share/extensions/tests/data/io/color.dxf new file mode 100644 index 0000000..d4b14b7 --- /dev/null +++ b/share/extensions/tests/data/io/color.dxf @@ -0,0 +1,3062 @@ +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$EXTMIN + 10 +-0.0768263335360333 + 20 +0.5 + 30 +0 + 9 +$EXTMAX + 10 +9.923173999999999 + 20 +16.99811350395265 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +420 + 20 +297 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1 + 9 +$ATTMODE + 70 + 0 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +15.68 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +cyan_layer + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +2.5 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 +STANDARD + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7854 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1 + 9 +$FILLETRAD + 40 +0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 34 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 2 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +0 + 20 +0 + 30 +0 + 9 +$PEXTMAX + 10 +0 + 20 +0 + 30 +0 + 9 +$GRIDMODE + 70 + 1 + 9 +$SNAPSTYLE + 70 + 0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +210 + 20 +297 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +1 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +50 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +5 + 9 +$PSOLHEIGHT + 40 +80 + 9 +$LOFTANG1 + 40 +1.570796326794897 + 9 +$LOFTANG2 + 40 +1.570796326794897 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +1 + 9 +$LONGITUDE + 40 +1 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 1 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +15.37932070393189 + 22 +11.42261951210867 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +24.44676093519341 + 41 +1.911368015414258 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.619999999999999 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +blue_layer + 70 + 0 + 62 + 5 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +cyan_layer + 70 + 0 + 62 + 4 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +magenta_layer + 70 + 0 + 62 + 6 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +4D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +4E +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +4F +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +2.5 + 41 +2.5 + 42 +0.625 + 43 +0.38 + 44 +1.25 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +2.5 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +0.625 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 8 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +179 + 0 +271 + 2 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 44 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +STANDARD +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +50 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +foo + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +51 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +foo + 70 + 0 + 10 +0 + 20 +0 + 3 +foo + 1 + + 0 +LINE + 5 +53 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 0 +370 + -1 +100 +AcDbLine + 10 +0.5 + 20 +-0.25 + 11 +10.5 + 21 +-0.25 + 0 +LINE + 5 +54 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0.5 + 20 +1.75 + 11 +10.5 + 21 +1.75 + 0 +LINE + 5 +55 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 56 +420 +8421376 +370 + -1 +100 +AcDbLine + 10 +0.5 + 20 +5.75 + 11 +10.5 + 21 +5.75 + 0 +LINE + 5 +56 +100 +AcDbEntity + 8 +magenta_layer + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0.5 + 20 +3.75 + 11 +10.5 + 21 +3.75 + 0 +ENDBLK + 5 +52 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +57 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 254 +370 + -1 +100 +AcDbLine + 10 +6.75 + 20 +0.5 + 11 +6.75 + 21 +10.5 + 0 +LINE + 5 +58 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 96 +370 + -1 +100 +AcDbLine + 10 +8.75 + 20 +0.5 + 11 +8.75 + 21 +10.5 + 0 +LINE + 5 +59 +100 +AcDbEntity + 8 +magenta_layer + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0.75 + 20 +0.5 + 11 +0.75 + 21 +10.5 + 0 +LINE + 5 +5A +100 +AcDbEntity + 8 +blue_layer + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +2.75 + 20 +0.5 + 11 +2.75 + 21 +10.5 + 0 +LINE + 5 +5B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +4.75 + 20 +0.5 + 11 +4.75 + 21 +10.5 + 0 +INSERT + 5 +5C +100 +AcDbEntity + 8 +cyan_layer + 6 +ByLayer + 62 + 2 +370 + -1 +100 +AcDbBlockReference + 2 +foo + 10 +-0.5768259999999999 + 20 +11.2481 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +1 + 45 +1 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/dxf_multiple_inserts.dxf b/share/extensions/tests/data/io/dxf_multiple_inserts.dxf new file mode 100644 index 0000000..8240385 --- /dev/null +++ b/share/extensions/tests/data/io/dxf_multiple_inserts.dxf @@ -0,0 +1,3098 @@ +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$EXTMIN + 10 +48.37047115149272 + 20 +118.7794842891392 + 30 +0 + 9 +$EXTMAX + 10 +114.7057254922649 + 20 +207.6498263615441 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +420 + 20 +297 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1 + 9 +$ATTMODE + 70 + 0 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +15.68 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 +STANDARD + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7854 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1 + 9 +$FILLETRAD + 40 +0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 34 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 2 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +0 + 20 +0 + 30 +0 + 9 +$PEXTMAX + 10 +0 + 20 +0 + 30 +0 + 9 +$GRIDMODE + 70 + 1 + 9 +$SNAPSTYLE + 70 + 0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +210 + 20 +297 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +1 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +50 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +5 + 9 +$PSOLHEIGHT + 40 +80 + 9 +$LOFTANG1 + 40 +1.570796326794897 + 9 +$LOFTANG2 + 40 +1.570796326794897 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +1 + 9 +$LONGITUDE + 40 +1 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 1 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +200.9475425719901 + 22 +135.62771490379 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +246.5526586166971 + 41 +1.911368015414258 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.619999999999999 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +4B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +4C +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +1 + 41 +2.5 + 42 +0.625 + 43 +0.38 + 44 +1.25 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +2.5 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +0.625 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 8 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +179 + 0 +271 + 2 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 44 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +STANDARD +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +4D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +test + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +4E +330 +4D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +test + 70 + 0 + 10 +0 + 20 +0 + 3 +test + 1 + + 0 +ELLIPSE + 5 +50 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +14.95162708883029 + 20 +34.30079155672832 + 30 +0 + 11 +8.795074758135467 + 21 +-13.1926121372032 + 31 +0 + 40 +0.4043037700313199 + 41 +0 + 42 +6.283185307179586 + 0 +ELLIPSE + 5 +51 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +63.54441512752874 + 20 +18.24978012313109 + 30 +0 + 11 +-5.496921723834667 + 21 +-12.53298153034304 + 31 +0 + 40 +0.4019826958521777 + 41 +0 + 42 +6.283185307179586 + 0 +LINE + 5 +52 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +13.63236587510997 + 20 +17.59014951627093 + 11 +49.03254177660523 + 21 +21.32805628847851 + 0 +LINE + 5 +53 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +49.03254177660523 + 20 +21.32805628847851 + 11 +45.95426561125781 + 21 +3.518029903254186 + 0 +LINE + 5 +54 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +45.95426561125781 + 20 +3.518029903254186 + 11 +14.73175021987691 + 21 +5.93667546174144 + 0 +DIMENSION + 5 +55 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +48.30331697523831 + 20 +-3.40164204050974 + 30 +0 + 11 +31.4651888747151 + 21 +-1.52664204050974 + 31 +0 + 70 + 32 + 71 + 5 + 72 + 0 + 3 +Standard + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +14.62706077419188 + 23 +2.721313632407792 + 33 +0 + 14 +48.30331697523831 + 24 +1.70082102025487 + 34 +0 +100 +AcDbRotatedDimension + 0 +ENDBLK + 5 +4F +330 +4D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +INSERT + 5 +56 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +test + 10 +42.88318046372747 + 20 +53.17514377502206 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +1 + 45 +1 + 0 +INSERT + 5 +57 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +test + 10 +131.0066874914664 + 20 +73.17786127878223 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +318.539 + 70 + 1 + 71 + 1 + 44 +1 + 45 +1 + 0 +INSERT + 5 +58 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +test + 10 +269.7993503659729 + 20 +132.718232703211 + 30 +0 + 41 +1.5 + 42 +1.5 + 43 +0 + 50 +231.728 + 70 + 1 + 71 + 1 + 44 +1.5 + 45 +1.5 + 0 +INSERT + 5 +59 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +test + 10 +98.62797555753446 + 20 +207.8936019958894 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +84.28500000000003 + 70 + 1 + 71 + 1 + 44 +1 + 45 +1 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/dxf_polylines.dxf b/share/extensions/tests/data/io/dxf_polylines.dxf new file mode 100644 index 0000000..6db2903 --- /dev/null +++ b/share/extensions/tests/data/io/dxf_polylines.dxf @@ -0,0 +1,2713 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$DWGCODEPAGE + 3 +dos932 + 9 +$LIMMIN + 10 + 0.00 + 20 +-540.50 + 9 +$LIMMAX + 10 +251.00 + 20 +26.00 + 9 +$LTSCALE + 40 +1.0 + 9 +$TEXTSTYLE + 7 +KANJI + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +LTYPE + 5 +23 +100 +AcDbSymbolTable + 70 + 6 + 0 +LTYPE + 5 +200 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 + 0.0 + 0 +LTYPE + 5 +201 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 + 0.0 + 0 +LTYPE + 5 +202 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 + 0.0 + 0 +LTYPE + 2 +DOT + 70 + 0 + 3 +¥¥¥¥¥¥¥¥¥¥ + 72 + 65 + 73 + 2 + 40 + 8.0000 + 49 + 6.0000 + 49 +-2.0000 + 0 +LTYPE + 2 +DASH + 70 + 0 + 3 +------- + 72 + 65 + 73 + 2 + 40 +12.6000 + 49 + 8.4000 + 49 +-4.2000 + 0 +LTYPE + 2 +DASHDOT + 70 + 0 + 3 +--.--.--.- + 72 + 65 + 73 + 4 + 40 +50.5000 + 49 +30.0000 + 49 +-9.0000 + 49 + 2.5000 + 49 +-9.0000 + 0 +LTYPE + 2 +DIVIDE + 70 + 0 + 3 +--¥¥--¥¥--¥¥-- + 72 + 65 + 73 + 6 + 40 +58.0000 + 49 +30.0000 + 49 +-9.0000 + 49 + 2.5000 + 49 +-5.0000 + 49 + 2.5000 + 49 +-9.0000 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 70 + 2 + 0 +STYLE + 2 +STANDARD + 70 + 0 + 40 + 0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +300.0 + 3 +MS UI Gothic + 4 + + 0 +STYLE + 2 +KANJI + 70 + 0 + 40 + 0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +203 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +JINOME +70 + 64 +10 +0.0 +20 +0.0 +30 +0.0 + 3 +JINOME + 1 + + 0 +LINE + 5 +204 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.5 +20 +4.0 +30 +0.0 +11 +0.0 +21 +5.0 +31 +0.0 + 0 +LINE + 5 +205 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.0 +20 +5.0 +30 +0.0 +11 +0.0 +21 +-5.0 +31 +0.0 + 0 +LINE + 5 +206 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.0 +20 +-5.0 +30 +0.0 +11 +-0.5 +21 +-4.0 +31 +0.0 + 0 +ENDBLK + 5 +207 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +208 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BUTTON +70 + 64 +10 +0.0 +20 +0.0 +30 +0.0 + 3 +BUTTON + 1 + + 0 +CIRCLE + 5 +209 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.0 +20 +0.0 +30 +0.0 +40 +1.0 + 0 +LINE + 5 +20a +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +-1.0 +20 +0.0 +30 +0.0 +11 +1.0 +21 +0.0 +31 +0.0 + 0 +LINE + 5 +20b +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.0 +20 +1.0 +30 +0.0 +11 +0.0 +21 +-1.0 +31 +0.0 + 0 +ENDBLK + 5 +20c +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +20d +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +BTNHOLE +70 + 64 +10 +0.0 +20 +0.0 +30 +0.0 + 3 +BTNHOLE + 1 + + 0 +LINE + 5 +20e +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +-1.0 +20 +0.0 +30 +0.0 +11 +1.0 +21 +0.0 +31 +0.0 + 0 +LINE + 5 +20f +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +-1.0 +20 +0.1 +30 +0.0 +11 +-1.0 +21 +-0.1 +31 +0.0 + 0 +LINE + 5 +210 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +1.0 +20 +0.1 +30 +0.0 +11 +1.0 +21 +-0.1 +31 +0.0 + 0 +ENDBLK + 5 +211 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +212 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +AIJIRUSHI +70 + 64 +10 +0.0 +20 +0.0 +30 +0.0 + 3 +AIJIRUSHI + 1 + + 0 +LINE + 5 +213 +100 +AcDbEntity + 8 +0 +100 +AcDbLine +10 +0.0 +20 +0.0 +30 +0.0 +11 +2.0 +21 +0.0 +31 +0.0 + 0 +CIRCLE + 5 +214 +100 +AcDbEntity + 8 +0 +100 +AcDbCircle +10 +2.0 +20 +0.0 +30 +0.0 +40 +0.4 + 0 +ENDBLK + 5 +215 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 2 +WADACHI +70 + 64 +10 +0.0 +20 +0.0 +30 +0.0 + 3 +WADACHI + 1 + + 0 +ARC + 8 +0 +10 +0.0 +20 +0.0 +30 +0.0 +40 + 1.0 +50 + 90.0 +51 + 270.0 + 0 +ARC + 8 +0 +10 +0.0 +20 +0.0 +30 +0.0 +40 + 1.25 +50 + 90.0 +51 + 270.0 + 0 +ENDBLK + 8 +0 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +216 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +DASH +10 + 0.0000 +20 + 0.0000 +30 +0.0 +11 + 0.0001 +21 +-540.0000 +31 +0.0 + 0 +LINE + 5 +217 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +75.0000 +20 +26.0000 +30 +0.0 +11 +201.9999 +21 +-7.5000 +31 +0.0 + 0 +LINE + 5 +218 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 + 0.0001 +20 +-540.0000 +30 +0.0 +11 +112.0000 +21 +-539.9999 +31 +0.0 + 0 +LINE + 5 +219 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +122.0000 +20 +-539.9998 +30 +0.0 +11 +243.0001 +21 +-540.5000 +31 +0.0 + 0 +LINE + 5 +21a +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +232.0000 +20 +-390.0000 +30 +0.0 +11 +243.0001 +21 +-540.5000 +31 +0.0 + 0 +LINE + 5 +21b +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +251.0000 +20 +-206.9999 +30 +0.0 +11 +232.0000 +21 +-390.0000 +31 +0.0 + 0 +LINE + 5 +21c +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +104.7800 +20 +-388.9999 +30 +0.0 +11 +112.0000 +21 +-539.9999 +31 +0.0 + 0 +LINE + 5 +21d +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 6 +CONTINUOUS +10 +130.2200 +20 +-388.9998 +30 +0.0 +11 +122.0000 +21 +-539.9998 +31 +0.0 + 0 +POLYLINE + 5 +21e + 8 +0 + 6 +CONTINUOUS +66 + 1 +10 +0.0 +20 +0.0 +30 +0.0 +70 + 128 +75 + 6 + 0 +VERTEX + 5 +21f + 8 +0 +10 + 0.0000 +20 + 0.0000 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +220 + 8 +0 +10 +10.1026 +20 + 0.0000 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +221 + 8 +0 +10 +12.5942 +20 + 0.0026 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +222 + 8 +0 +10 +15.0737 +20 + 0.0208 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +223 + 8 +0 +10 +20.0256 +20 + 0.1666 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +224 + 8 +0 +10 +25.0032 +20 + 0.5416 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +225 + 8 +0 +10 +30.0000 +20 + 1.1666 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +226 + 8 +0 +10 +34.9999 +20 + 2.0416 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +227 + 8 +0 +10 +39.9999 +20 + 3.1665 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +228 + 8 +0 +10 +44.8977 +20 + 4.5024 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +229 + 8 +0 +10 +49.1827 +20 + 5.8538 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22a + 8 +0 +10 +52.4432 +20 + 7.0493 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22b + 8 +0 +10 +55.0722 +20 + 8.1701 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22c + 8 +0 +10 +57.5651 +20 + 9.3409 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22d + 8 +0 +10 +60.0214 +20 +10.6085 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22e + 8 +0 +10 +62.4518 +20 +12.0202 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +22f + 8 +0 +10 +64.9074 +20 +13.7036 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +230 + 8 +0 +10 +67.3873 +20 +15.7349 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +231 + 8 +0 +10 +69.6416 +20 +17.9040 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +232 + 8 +0 +10 +70.5961 +20 +18.9595 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +233 + 8 +0 +10 +71.4343 +20 +19.9880 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +234 + 8 +0 +10 +72.1740 +20 +20.9985 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +235 + 8 +0 +10 +75.0000 +20 +26.0000 +30 +0.0 +70 + 8 + 0 +SEQEND + 5 +236 +100 +AcDbEntity + 8 +0 + 0 +POLYLINE + 5 +237 + 8 +0 + 6 +CONTINUOUS +66 + 1 +10 +0.0 +20 +0.0 +30 +0.0 +70 + 128 +75 + 6 + 0 +VERTEX + 5 +238 + 8 +0 +10 +251.0000 +20 +-206.9999 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +239 + 8 +0 +10 +245.7260 +20 +-205.2677 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23a + 8 +0 +10 +244.3457 +20 +-204.7271 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23b + 8 +0 +10 +242.9443 +20 +-204.1463 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23c + 8 +0 +10 +241.5358 +20 +-203.5456 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23d + 8 +0 +10 +238.7515 +20 +-202.3596 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23e + 8 +0 +10 +236.0693 +20 +-201.1884 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +23f + 8 +0 +10 +233.5286 +20 +-199.9172 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +240 + 8 +0 +10 +231.0879 +20 +-198.5045 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +241 + 8 +0 +10 +228.6328 +20 +-196.9890 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +242 + 8 +0 +10 +226.1910 +20 +-195.4257 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +243 + 8 +0 +10 +223.9274 +20 +-193.8790 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +244 + 8 +0 +10 +221.8282 +20 +-192.3214 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +245 + 8 +0 +10 +219.7000 +20 +-190.6362 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +246 + 8 +0 +10 +217.4669 +20 +-188.7820 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +247 + 8 +0 +10 +215.1785 +20 +-186.7947 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +248 + 8 +0 +10 +212.8902 +20 +-184.6673 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +249 + 8 +0 +10 +210.6573 +20 +-182.3505 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24a + 8 +0 +10 +208.5420 +20 +-179.8787 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24b + 8 +0 +10 +206.6105 +20 +-177.3705 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24c + 8 +0 +10 +204.8695 +20 +-174.9016 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24d + 8 +0 +10 +203.2682 +20 +-172.5044 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24e + 8 +0 +10 +201.7923 +20 +-170.2701 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +24f + 8 +0 +10 +200.4645 +20 +-168.3404 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +250 + 8 +0 +10 +199.2577 +20 +-166.6172 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +251 + 8 +0 +10 +198.0967 +20 +-164.7712 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +252 + 8 +0 +10 +196.9818 +20 +-162.7249 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +253 + 8 +0 +10 +195.9881 +20 +-160.6576 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +254 + 8 +0 +10 +195.1101 +20 +-158.6311 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +255 + 8 +0 +10 +194.2625 +20 +-156.5793 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +256 + 8 +0 +10 +193.4292 +20 +-154.4558 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +257 + 8 +0 +10 +192.6662 +20 +-152.2391 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +258 + 8 +0 +10 +192.0039 +20 +-149.8984 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +259 + 8 +0 +10 +191.4419 +20 +-147.3926 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25a + 8 +0 +10 +190.9453 +20 +-144.6746 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25b + 8 +0 +10 +190.4471 +20 +-141.6900 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25c + 8 +0 +10 +189.9109 +20 +-138.3425 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25d + 8 +0 +10 +189.3359 +20 +-134.5095 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25e + 8 +0 +10 +188.7831 +20 +-130.4147 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +25f + 8 +0 +10 +188.3707 +20 +-126.6168 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +260 + 8 +0 +10 +188.1353 +20 +-123.3689 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +261 + 8 +0 +10 +188.0284 +20 +-120.5971 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +262 + 8 +0 +10 +187.9779 +20 +-118.0468 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +263 + 8 +0 +10 +187.8967 +20 +-115.3110 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +264 + 8 +0 +10 +187.8217 +20 +-112.3030 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +265 + 8 +0 +10 +187.9077 +20 +-109.2398 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +266 + 8 +0 +10 +188.1539 +20 +-105.8076 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +267 + 8 +0 +10 +188.4040 +20 +-101.1906 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +268 + 8 +0 +10 +188.6228 +20 +-95.5372 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +269 + 8 +0 +10 +188.8997 +20 +-89.9559 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26a + 8 +0 +10 +189.2562 +20 +-84.9538 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26b + 8 +0 +10 +189.6428 +20 +-80.3887 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26c + 8 +0 +10 +190.0670 +20 +-75.9890 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26d + 8 +0 +10 +190.5949 +20 +-71.3873 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26e + 8 +0 +10 +191.2745 +20 +-66.3658 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +26f + 8 +0 +10 +192.1309 +20 +-60.8611 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +270 + 8 +0 +10 +193.1467 +20 +-54.8421 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +271 + 8 +0 +10 +194.2622 +20 +-48.3178 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +272 + 8 +0 +10 +195.4052 +20 +-41.6366 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +273 + 8 +0 +10 +196.4954 +20 +-35.4629 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +274 + 8 +0 +10 +197.5153 +20 +-29.9478 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +275 + 8 +0 +10 +198.5099 +20 +-24.7246 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +276 + 8 +0 +10 +199.0069 +20 +-22.1556 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +277 + 8 +0 +10 +199.5043 +20 +-19.6209 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +278 + 8 +0 +10 +201.9999 +20 +-7.4999 +30 +0.0 +70 + 8 + 0 +SEQEND + 5 +279 +100 +AcDbEntity + 8 +0 + 0 +POLYLINE + 5 +27a + 8 +0 + 6 +CONTINUOUS +66 + 1 +10 +0.0 +20 +0.0 +30 +0.0 +70 + 128 +75 + 6 + 0 +VERTEX + 5 +27b + 8 +0 +10 +117.9999 +20 +-210.0000 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +27c + 8 +0 +10 +116.1315 +20 +-230.8508 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +27d + 8 +0 +10 +115.6055 +20 +-236.7203 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +27e + 8 +0 +10 +115.0095 +20 +-243.3714 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +27f + 8 +0 +10 +114.3018 +20 +-251.2699 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +280 + 8 +0 +10 +112.4014 +20 +-272.4779 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +281 + 8 +0 +10 +109.9882 +20 +-299.4094 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +282 + 8 +0 +10 +107.5453 +20 +-326.6955 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +283 + 8 +0 +10 +105.5515 +20 +-349.5276 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +284 + 8 +0 +10 +104.4441 +20 +-364.0422 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +285 + 8 +0 +10 +104.1984 +20 +-370.8021 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +286 + 8 +0 +10 +104.3370 +20 +-374.6637 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +287 + 8 +0 +10 +104.4412 +20 +-376.5048 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +288 + 8 +0 +10 +104.5456 +20 +-378.3788 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +289 + 8 +0 +10 +104.7800 +20 +-388.9999 +30 +0.0 +70 + 8 + 0 +SEQEND + 5 +28a +100 +AcDbEntity + 8 +0 + 0 +POLYLINE + 5 +28b + 8 +0 + 6 +CONTINUOUS +66 + 1 +10 +0.0 +20 +0.0 +30 +0.0 +70 + 128 +75 + 6 + 0 +VERTEX + 5 +28c + 8 +0 +10 +117.9999 +20 +-210.0000 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +28d + 8 +0 +10 +121.5367 +20 +-251.6312 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +28e + 8 +0 +10 +122.2383 +20 +-259.8901 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +28f + 8 +0 +10 +122.9044 +20 +-267.7296 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +290 + 8 +0 +10 +124.4109 +20 +-285.4618 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +291 + 8 +0 +10 +126.4101 +20 +-309.1170 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +292 + 8 +0 +10 +128.4211 +20 +-333.6472 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +293 + 8 +0 +10 +129.8808 +20 +-352.9847 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +294 + 8 +0 +10 +130.7328 +20 +-366.3191 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +295 + 8 +0 +10 +130.9543 +20 +-370.9370 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +296 + 8 +0 +10 +131.0593 +20 +-374.5082 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +297 + 8 +0 +10 +131.0657 +20 +-377.3610 +30 +0.0 +70 + 8 + 0 +VERTEX + 5 +298 + 8 +0 +10 +130.2199 +20 +-388.9998 +30 +0.0 +70 + 8 + 0 +SEQEND + 5 +299 +100 +AcDbEntity + 8 +0 + 0 +INSERT + 5 +29a +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 2 +JINOME +10 +46.9 +20 +-265.7 +30 +0.0 +41 +30.00 +42 +30.00 +43 +30.00 +50 +-0.0 + 0 +INSERT + 5 +29b +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 2 +AIJIRUSHI +10 +194.9 +20 +-154.7 +30 +0.0 +41 +10.00 +42 +10.00 +43 +10.00 +50 +559.2 + 0 +TEXT + 5 +29c +100 +AcDbEntity + 8 +0 +100 +AcDbText +10 +50.1951 +20 +-185.6933 +30 +0.0 +40 +10.00 +1 +Œãg  1–‡ +50 +270 + 7 +STANDARD + 72 +0 + 0 +TEXT + 5 +29d +100 +AcDbEntity + 8 +0 +100 +AcDbText +10 + 8.5485 +20 +-275.6601 +30 +0.0 +40 +5.00 +1 +‚íÙ‚¿ +50 +0 + 7 +STANDARD + 72 +0 + 0 +ENDSEC + 0 +EOF + 0 diff --git a/share/extensions/tests/data/io/dxf_with_arc.dxf b/share/extensions/tests/data/io/dxf_with_arc.dxf new file mode 100644 index 0000000..e1bb65e --- /dev/null +++ b/share/extensions/tests/data/io/dxf_with_arc.dxf @@ -0,0 +1,25184 @@ +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1250 + 9 +$INSBASE + 10 +1470.184244857629 + 20 +288.299390501204 + 30 +0 + 9 +$EXTMIN + 10 +-2.398081733190338e-13 + 20 +-247.0000000000017 + 30 +0 + 9 +$EXTMAX + 10 +299.996168582378 + 20 +16.08812260536429 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +2000 + 20 +2000 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$LTSCALE + 40 +0.4 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +4 + 9 +$TRACEWID + 40 +0.05 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1 + 9 +$DIMASZ + 40 +4 + 9 +$DIMEXO + 40 +0 + 9 +$DIMDLI + 40 +10 + 9 +$DIMRND + 40 +0.05 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +0 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +4 + 9 +$DIMCEN + 40 +-3 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 2 + 9 +$DIMALTF + 40 +25.4 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 2 + 9 +$DIMCLRE + 70 + 2 + 9 +$DIMCLRT + 70 + 2 + 9 +$DIMTFAC + 40 +0.5 + 9 +$DIMGAP + 40 +1.5 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 1 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 1 + 9 +$DIMTDEC + 70 + 1 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 2 + 9 +$DIMTXSTY + 7 +standard + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 0 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 2 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7853981633974483 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 1 + 9 +$DIMLTYPE + 6 +BYBLOCK + 9 +$DIMLTEX1 + 6 +BYBLOCK + 9 +$DIMLTEX2 + 6 +BYBLOCK + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 3 + 9 +$SKETCHINC + 40 +0.1 + 9 +$FILLETRAD + 40 +2 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 1 + 9 +$MENU + 1 +acad + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0.7853981633974483 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 16 + 9 +$PINSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1e+20 + 20 +1e+20 + 30 +1e+20 + 9 +$PEXTMAX + 10 +-1e+20 + 20 +-1e+20 + 30 +-1e+20 + 9 +$GRIDMODE + 70 + 1 + 9 +$SNAPSTYLE + 70 + 0 + 9 +$GRIDUNIT + 10 +0 + 20 +0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +12 + 20 +9 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 0 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +STANDARD + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +1 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 0 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 +mochrme_wien_tisk.ctb + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +6 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +0.25 + 9 +$PSOLHEIGHT + 40 +4 + 9 +$LOFTANG1 + 40 +1.570796326794896 + 9 +$LOFTANG2 + 40 +1.570796326794896 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 0 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +227.1516351014727 + 22 +37.9833459024703 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +365.2388729143943 + 41 +1.618852459016394 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 2 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.619999999999999 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + -3 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +4B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +4C +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +1 + 41 +4 + 42 +0 + 43 +0.38 + 44 +0 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +4 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +1.5 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 8 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 2 +177 + 2 +178 + 2 +179 + 0 +271 + 1 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 0 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +standard +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +4D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOTSMALL + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +50 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_NONE + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +53 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C01EA46E0 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +56 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C18903741 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +59 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C3A410068 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +5C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C75D90C8F + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +5F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C1A413407 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +62 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C5FC81BCA + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +65 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C2B0148A3 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +68 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C6BDD0B26 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +6B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C034740AE + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +6E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C59F22E77 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +71 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +GENAXEH + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +74 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C2456717E + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +77 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +(22-14-16X) pálená + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +7A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_POZOR !PÃLENÉ ROZMÄšRY + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +7D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C2EFF5608 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +80 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +A$C054C61AF + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +4E +330 +4D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOTSMALL + 70 + 0 + 10 +0 + 20 +0 + 3 +_DOTSMALL + 1 + + 0 +LWPOLYLINE + 5 +83 +100 +AcDbEntity + 8 +0 + 6 +ByBlock + 62 + 0 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 1 + 43 +0 + 10 +-0.0625 + 20 +2.080942803238667e-17 + 42 +0.9999999999999999 + 10 +0.0625 + 20 +1.471011291944575e-17 + 42 +0.9999999999999999 + 0 +ENDBLK + 5 +4F +330 +4D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +51 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_NONE + 70 + 0 + 10 +0 + 20 +0 + 3 +_NONE + 1 + + 0 +CIRCLE + 5 +84 +100 +AcDbEntity + 8 +0 + 6 +ByBlock + 62 + 0 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +0 + 40 +0.25 + 0 +ENDBLK + 5 +52 +330 +50 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +54 +330 +53 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C01EA46E0 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C01EA46E0 + 1 + + 0 +ENDBLK + 5 +55 +330 +53 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +57 +330 +56 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C18903741 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C18903741 + 1 + + 0 +ENDBLK + 5 +58 +330 +56 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5A +330 +59 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C3A410068 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C3A410068 + 1 + + 0 +ENDBLK + 5 +5B +330 +59 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +5D +330 +5C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C75D90C8F + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C75D90C8F + 1 + + 0 +ENDBLK + 5 +5E +330 +5C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +60 +330 +5F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C1A413407 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C1A413407 + 1 + + 0 +ENDBLK + 5 +61 +330 +5F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +63 +330 +62 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C5FC81BCA + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C5FC81BCA + 1 + + 0 +ENDBLK + 5 +64 +330 +62 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +66 +330 +65 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C2B0148A3 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C2B0148A3 + 1 + + 0 +ENDBLK + 5 +67 +330 +65 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +69 +330 +68 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C6BDD0B26 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C6BDD0B26 + 1 + + 0 +ENDBLK + 5 +6A +330 +68 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6C +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C034740AE + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C034740AE + 1 + + 0 +ENDBLK + 5 +6D +330 +6B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6F +330 +6E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C59F22E77 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C59F22E77 + 1 + + 0 +LINE + 5 +85 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7 + 20 +-5.457e-12 + 11 +7.5 + 21 +-5.457e-12 + 0 +LINE + 5 +86 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +2.700000000000727 + 20 +-3.638e-12 + 11 +7 + 21 +-5.457e-12 + 0 +LINE + 5 +87 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-7.5 + 20 +-9.094900000000001e-12 + 11 +-2.700000000000727 + 21 +-7.275999999999999e-12 + 0 +LINE + 5 +88 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-2.700000000000727 + 20 +0 + 11 +-3 + 21 +0.2999999999992724 + 0 +SPLINE + 5 +89 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 2 + 72 + 6 + 73 + 3 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 10 +-7.5 + 20 +0.2999999999919964 + 30 +0 + 10 +-7.5 + 20 +0.1538900988016394 + 30 +0 + 10 +-7.5 + 20 +-9.094900000000001e-12 + 30 +0 + 0 +LINE + 5 +8A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-3 + 20 +0.2999999999938154 + 11 +-7.5 + 21 +0.2999999999919964 + 0 +LINE + 5 +8B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +0.2999999999992724 + 11 +2.700000000000727 + 21 +0 + 0 +LINE + 5 +8C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +-5.457e-12 + 11 +7.5 + 21 +0.2999999999956344 + 0 +LINE + 5 +8D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +0.2999999999956344 + 11 +7 + 21 +0.2999999999956344 + 0 +LINE + 5 +8E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7 + 20 +0.2999999999956344 + 11 +3 + 21 +0.2999999999956344 + 0 +LINE + 5 +8F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +2.700000000000727 + 20 +0 + 11 +-2.700000000000727 + 21 +0 + 0 +LINE + 5 +90 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-3 + 20 +5 + 11 +-3 + 21 +0.2999999999992724 + 0 +LINE + 5 +91 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-3 + 20 +4.999999999996362 + 11 +-3 + 21 +23.54529946161711 + 0 +LINE + 5 +92 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +5 + 11 +-3 + 21 +5 + 0 +LINE + 5 +93 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +23.54529946161711 + 11 +3 + 21 +20.23760430703078 + 0 +LINE + 5 +94 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +1 + 20 +24.99999999999636 + 11 +2.740192378863866 + 21 +23.99529946161783 + 0 +LINE + 5 +95 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-2.740192378863866 + 20 +23.99529946161783 + 11 +-1 + 21 +24.99999999999636 + 0 +LINE + 5 +96 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +24.99999999999636 + 11 +1 + 21 +24.99999999999636 + 0 +LINE + 5 +97 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +0.2999999999992724 + 11 +3 + 21 +5 + 0 +LINE + 5 +98 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +0.2999999999956344 + 11 +7.5 + 21 +5.999999999994543 + 0 +SPLINE + 5 +99 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0.1847470343155097 + 40 +0.1847470343155097 + 40 +0.3694940686310193 + 40 +0.3694940686310193 + 40 +0.5566106137322026 + 40 +0.5566106137322026 + 40 +0.7437271588333858 + 40 +0.7437271588333858 + 40 +0.7437271588333858 + 40 +0.7437271588333858 + 10 +3 + 20 +20.23760430703078 + 30 +0 + 10 +3 + 20 +19.87173020045338 + 30 +0 + 10 +3.09828101261155 + 20 +19.47729911545866 + 30 +0 + 10 +3.504714861621323 + 20 +18.69305136600997 + 30 +0 + 10 +3.812556686472817 + 20 +18.30138646565865 + 30 +0 + 10 +4.518688201755139 + 20 +17.57104105542021 + 30 +0 + 10 +4.974748167081997 + 20 +17.17606056594013 + 30 +0 + 10 +5.971767955164978 + 20 +16.37971921015742 + 30 +0 + 10 +6.510712351391703 + 20 +15.97530951650333 + 30 +0 + 10 +7 + 20 +15.58849366635513 + 30 +0 + 0 +ELLIPSE + 5 +9A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +9 + 20 +28.23760430702896 + 30 +0 + 11 +-6e-16 + 21 +-13.41640786499874 + 31 +0 + 40 +0.4472135954999579 + 41 +5.943348397725577 + 42 +6.030505052037507 + 0 +LINE + 5 +9B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +20.23760430703078 + 11 +3 + 21 +4.999999999996362 + 0 +LINE + 5 +9C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +11.5 + 20 +5.999999999994543 + 11 +7.5 + 21 +5.999999999994543 + 0 +LINE + 5 +9D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-15.5 + 20 +5.999999999990905 + 11 +-11.5 + 21 +5.999999999990905 + 0 +LINE + 5 +9E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-11.5 + 20 +4.999999999990905 + 11 +-14.5 + 21 +4.999999999990905 + 0 +LINE + 5 +9F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-9 + 20 +5.999999999990905 + 11 +-11.5 + 21 +5.999999999990905 + 0 +LINE + 5 +A0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-11.5 + 20 +4.999999999990905 + 11 +-9 + 21 +4.999999999990905 + 0 +LINE + 5 +A1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-7.5 + 20 +5.999999999992724 + 11 +-9 + 21 +5.999999999990905 + 0 +LINE + 5 +A2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-9 + 20 +4.999999999990905 + 11 +-7.5 + 21 +4.999999999990905 + 0 +LINE + 5 +A3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +4.999999999994543 + 11 +11.5 + 21 +4.999999999994543 + 0 +LINE + 5 +A4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +11.5 + 20 +5.999999999994543 + 11 +15.5 + 21 +5.999999999994543 + 0 +LINE + 5 +A5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +14.5 + 20 +4.999999999994543 + 11 +11.5 + 21 +4.999999999994543 + 0 +LINE + 5 +A6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-14.5 + 20 +4.999999999990905 + 11 +-15.5 + 21 +5.999999999990905 + 0 +LINE + 5 +A7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +14.5 + 20 +4.999999999994543 + 11 +15.5 + 21 +5.999999999994543 + 0 +LINE + 5 +A8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15.5 + 20 +5.999999999994543 + 11 +15.5 + 21 +14.89637028917605 + 0 +LINE + 5 +A9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-15.5 + 20 +14.89637028917241 + 11 +-15.5 + 21 +5.999999999990905 + 0 +LINE + 5 +AA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +15.24722325026232 + 11 +11.5 + 21 +12.93782217350417 + 0 +ELLIPSE + 5 +AB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +11.5 + 20 +20.93782217350236 + 30 +0 + 11 +-1.397343347875937 + 21 +8.302737232552735 + 31 +0 + 40 +0.4514162296451872 + 41 +2.784730464117339 + 42 +3.83783392486262 + 0 +LINE + 5 +AC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +13.71414284285492 + 20 +17.65948620715608 + 11 +14 + 21 +17.49444650052828 + 0 +SPLINE + 5 +AD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 12 + 73 + 8 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +1.063792763713057 + 40 +1.063792763713057 + 40 +1.063792763713057 + 40 +1.063792763713057 + 40 +1.150403181630477 + 40 +1.150403181630477 + 40 +1.312639480122136 + 40 +1.312639480122136 + 40 +1.487078870423753 + 40 +1.487078870423753 + 40 +1.487078870423753 + 40 +1.487078870423753 + 10 +14.63166159904358 + 20 +16.82975648467436 + 30 +0 + 10 +14.75057278376334 + 20 +16.66895366867902 + 30 +0 + 10 +14.82986156604965 + 20 +16.52246570427996 + 30 +0 + 10 +14.98751997457657 + 20 +16.1758819404331 + 30 +0 + 10 +15.04901312309448 + 20 +15.94070571681186 + 30 +0 + 10 +15.08629861224108 + 20 +15.45192801530902 + 30 +0 + 10 +15.05486009893502 + 20 +15.20386988233804 + 30 +0 + 10 +14.97585295221506 + 20 +14.97202439895955 + 30 +0 + 0 +ARC + 5 +AE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +12.5 + 20 +14.89637028917605 + 40 +3 +100 +AcDbArc + 50 +0 + 51 +59.99999999998969 + 0 +SPLINE + 5 +AF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.1169532015498188 + 40 +-0.1169532015498188 + 40 +-0.1169532015498188 + 40 +-0.1169532015498188 + 40 +-0.1133705391174536 + 40 +-0.1133705391174536 + 40 +-0.0737269023574818 + 40 +-0.0737269023574818 + 40 +-0.0303974490876721 + 40 +-0.0303974490876721 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 10 +14.63166160372202 + 20 +16.82975649277796 + 30 +0 + 10 +14.62645817427619 + 20 +16.839873464025 + 30 +0 + 10 +14.62102107926694 + 20 +16.85003470812808 + 30 +0 + 10 +14.55258475849405 + 20 +16.97313086061513 + 30 +0 + 10 +14.46296005909244 + 20 +17.08761304304971 + 30 +0 + 10 +14.22512897424894 + 20 +17.32086454397358 + 30 +0 + 10 +14.0905317329998 + 20 +17.42123051567978 + 30 +0 + 10 +13.88764599723072 + 20 +17.55671552796048 + 30 +0 + 10 +13.80189271991912 + 20 +17.6088237920103 + 30 +0 + 10 +13.71414284285492 + 20 +17.65948620715608 + 30 +0 + 0 +LINE + 5 +B0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +13.71414284285492 + 20 +17.65948620715608 + 11 +7.629903810568066 + 21 +21.1722232502616 + 0 +LINE + 5 +B1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +7.5 + 20 +20.94722325026123 + 11 +14.63166160372202 + 21 +16.82975649277796 + 0 +LINE + 5 +B2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +2.740192378863866 + 20 +23.99529946161783 + 11 +3 + 21 +23.54529946161711 + 0 +SPLINE + 5 +B3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.8804149087032905 + 40 +-0.8804149087032905 + 40 +-0.8804149087032905 + 40 +-0.8804149087032905 + 40 +-0.7416745081346062 + 40 +-0.7416745081346062 + 40 +-0.4616775534525233 + 40 +-0.4616775534525233 + 40 +-0.196217096330425 + 40 +-0.196217096330425 + 40 +0.0149701145503651 + 40 +0.0149701145503651 + 40 +0.0149701145503651 + 40 +0.0149701145503651 + 10 +3 + 20 +23.54529946162802 + 30 +0 + 10 +3 + 20 +23.56008093915625 + 30 +0 + 10 +3.03633363695917 + 20 +23.55237666535686 + 30 +0 + 10 +3.270643453059165 + 20 +23.45127567401505 + 30 +0 + 10 +3.602637004776624 + 20 +23.27405147965692 + 30 +0 + 10 +4.567697708054765 + 20 +22.72157601993967 + 30 +0 + 10 +5.179099107928777 + 20 +22.35995808480038 + 30 +0 + 10 +6.37523476755814 + 20 +21.6381975443237 + 30 +0 + 10 +6.9375 + 20 +21.29448277668053 + 30 +0 + 10 +7.5 + 20 +20.94722325026123 + 30 +0 + 0 +SPLINE + 5 +B4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.0149701145503651 + 40 +-0.0149701145503651 + 40 +-0.0149701145503651 + 40 +-0.0149701145503651 + 40 +0.196217096330425 + 40 +0.196217096330425 + 40 +0.4616775534525233 + 40 +0.4616775534525233 + 40 +0.7416745081346062 + 40 +0.7416745081346062 + 40 +0.8804149087032905 + 40 +0.8804149087032905 + 40 +0.8804149087032905 + 40 +0.8804149087032905 + 10 +7.629903810568066 + 20 +21.1722232502616 + 30 +0 + 10 +7.018689881602767 + 20 +21.52510777668067 + 30 +0 + 10 +6.407731051665905 + 20 +21.87784502160866 + 30 +0 + 10 +5.108007005277613 + 20 +22.62824104966421 + 30 +0 + 10 +4.443656690971693 + 20 +23.01180388246394 + 30 +0 + 10 +3.39501927917081 + 20 +23.61723497445018 + 30 +0 + 10 +3.034274242498213 + 20 +23.82551121848337 + 30 +0 + 10 +2.779672601085621 + 20 +23.97250554468883 + 30 +0 + 10 +2.740192378845677 + 20 +23.99529946162693 + 30 +0 + 10 +2.740192378845677 + 20 +23.99529946162693 + 30 +0 + 0 +LINE + 5 +B5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-3 + 20 +23.54529946161711 + 11 +-2.740192378863866 + 21 +23.99529946161783 + 0 +SPLINE + 5 +B6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 16 + 73 + 12 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.6038559167777109 + 40 +-0.6038559167777109 + 40 +-0.6038559167777109 + 40 +-0.6038559167777109 + 40 +-0.582517922730505 + 40 +-0.582517922730505 + 40 +-0.5587533240396756 + 40 +-0.5587533240396756 + 40 +-0.4985161489849369 + 40 +-0.4985161489849369 + 40 +-0.4481554820137946 + 40 +-0.4481554820137946 + 40 +-0.4453791002559526 + 40 +-0.4453791002559526 + 40 +-0.4453791002559526 + 40 +-0.4453791002559526 + 10 +-13.71414284285492 + 20 +17.65948620715426 + 30 +0 + 10 +-13.75856478896094 + 20 +17.63383918461113 + 30 +0 + 10 +-13.80264095200255 + 20 +17.60772585361519 + 30 +0 + 10 +-13.8948877665207 + 20 +17.55096781434986 + 30 +0 + 10 +-13.94265334912052 + 20 +17.5203307349293 + 30 +0 + 10 +-14.10855721811822 + 20 +17.40801437286427 + 30 +0 + 10 +-14.24740558818666 + 20 +17.30312508613678 + 30 +0 + 10 +-14.48045869458292 + 20 +17.06620659339387 + 30 +0 + 10 +-14.56387479677869 + 20 +16.95597401495979 + 30 +0 + 10 +-14.62546783103607 + 20 +16.84165746852523 + 30 +0 + 10 +-14.62860507966252 + 20 +16.83569926724703 + 30 +0 + 10 +-14.63166161137633 + 20 +16.82975648581851 + 30 +0 + 0 +LINE + 5 +B7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-14.63166161137633 + 20 +16.82975648581851 + 11 +-7.5 + 21 +20.9472232502576 + 0 +LINE + 5 +B8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-7.629903810568066 + 20 +21.17222325025796 + 11 +-13.71414284285492 + 21 +17.65948620715426 + 0 +SPLINE + 5 +B9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.8804149087003743 + 40 +-0.8804149087003743 + 40 +-0.8804149087003743 + 40 +-0.8804149087003743 + 40 +-0.7416745038784879 + 40 +-0.7416745038784879 + 40 +-0.4616775439775058 + 40 +-0.4616775439775058 + 40 +-0.1962170964610889 + 40 +-0.1962170964610889 + 40 +0.0149701145603456 + 40 +0.0149701145603456 + 40 +0.0149701145603456 + 40 +0.0149701145603456 + 10 +-7.500000000003637 + 20 +20.94722325026669 + 30 +0 + 10 +-7.130463050365506 + 20 +21.17535698560278 + 30 +0 + 10 +-6.762305369946261 + 20 +21.40118588313453 + 30 +0 + 10 +-5.673549429156992 + 20 +22.06395726310075 + 30 +0 + 10 +-4.980246565803099 + 20 +22.47868822974306 + 30 +0 + 10 +-3.897620961633947 + 20 +23.10844500927487 + 30 +0 + 10 +-3.501848890653491 + 20 +23.32831894863375 + 30 +0 + 10 +-3.08499562410725 + 20 +23.53781799951321 + 30 +0 + 10 +-3 + 20 +23.56779946161259 + 30 +0 + 10 +-3 + 20 +23.54529946161347 + 30 +0 + 0 +SPLINE + 5 +BA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 14 + 73 + 10 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +-0.0149701145603456 + 40 +-0.0149701145603456 + 40 +-0.0149701145603456 + 40 +-0.0149701145603456 + 40 +0.1962170964610889 + 40 +0.1962170964610889 + 40 +0.4616775439775058 + 40 +0.4616775439775058 + 40 +0.7416745038784879 + 40 +0.7416745038784879 + 40 +0.8804149087003743 + 40 +0.8804149087003743 + 40 +0.8804149087003743 + 40 +0.8804149087003743 + 10 +-2.740192378863866 + 20 +23.99529946161238 + 30 +0 + 10 +-2.740192378863866 + 20 +23.99529946161238 + 30 +0 + 10 +-2.832548839942319 + 20 +23.94197743394943 + 30 +0 + 10 +-3.285502658334735 + 20 +23.68046442496961 + 30 +0 + 10 +-3.715549596065102 + 20 +23.43217670970625 + 30 +0 + 10 +-4.891933327835431 + 20 +22.75299124549747 + 30 +0 + 10 +-5.645277980413084 + 20 +22.31804750754054 + 30 +0 + 10 +-6.828322951529116 + 20 +21.63501617500151 + 30 +0 + 10 +-7.228364022324967 + 20 +21.40405235509025 + 30 +0 + 10 +-7.629903810568066 + 20 +21.17222325025796 + 30 +0 + 0 +ELLIPSE + 5 +BB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +-9 + 20 +16.23760430702714 + 30 +0 + 11 +6 + 21 +0 + 31 +0 + 40 +0.2360679775000923 + 41 +4.965069235526769 + 42 +6.283185307179584 + 0 +ELLIPSE + 5 +BC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +-9 + 20 +2.381197846476425 + 30 +0 + 11 +2.096015021813906 + 21 +12.45410584882909 + 31 +0 + 40 +0.4514162296451875 + 41 +0.1041819343303771 + 42 +0.3568621894724564 + 0 +LINE + 5 +BD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-7.5 + 20 +0.2999999999919964 + 11 +-7.5 + 21 +5.999999999992724 + 0 +SPLINE + 5 +BE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbSpline +210 +0 +220 +0 +230 +0 + 70 + 8 + 71 + 3 + 72 + 12 + 73 + 8 + 74 + 0 + 42 +1e-07 + 43 +1e-07 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0.0863389482915113 + 40 +0.0863389482915113 + 40 +0.1728907842033072 + 40 +0.1728907842033072 + 40 +0.2086223870646714 + 40 +0.2086223870646714 + 40 +0.2086223870646714 + 40 +0.2086223870646714 + 10 +-14.97585295221506 + 20 +14.97202439895591 + 30 +0 + 10 +-15.05662819059216 + 20 +15.20905832517201 + 30 +0 + 10 +-15.08766266904058 + 20 +15.46298220956669 + 30 +0 + 10 +-15.04352887602363 + 20 +15.9816472004095 + 30 +0 + 10 +-14.96867725382617 + 20 +16.24004617991522 + 30 +0 + 10 +-14.79320860889856 + 20 +16.58708940850556 + 30 +0 + 10 +-14.72497321695846 + 20 +16.70357179399616 + 30 +0 + 10 +-14.63166160559558 + 20 +16.82975647581043 + 30 +0 + 0 +LINE + 5 +BF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-14 + 20 +17.49444650052464 + 11 +-13.71414284285492 + 21 +17.65948620715426 + 0 +ARC + 5 +C0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-12.5 + 20 +14.89637028917241 + 40 +3 +100 +AcDbArc + 50 +120.0000000000103 + 51 +180 + 0 +ELLIPSE + 5 +C1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbEllipse + 10 +-11.5 + 20 +20.93782217349872 + 30 +0 + 11 +1.397343347875938 + 21 +8.302737232552728 + 31 +0 + 40 +0.4514162296451875 + 41 +2.445351382316967 + 42 +3.498454843062249 + 0 +LINE + 5 +C2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-11.5 + 20 +12.93782217350053 + 11 +-9 + 21 +14.3811978464746 + 0 +ENDBLK + 5 +70 +330 +6E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +72 +330 +71 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +GENAXEH + 70 + 0 + 10 +0 + 20 +0 + 3 +GENAXEH + 1 + + 0 +LINE + 5 +C3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +0 + 11 +1 + 21 +0 + 0 +ENDBLK + 5 +73 +330 +71 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +75 +330 +74 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C2456717E + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C2456717E + 1 + + 0 +LINE + 5 +C4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-159 + 20 +136.9999999999982 + 11 +0 + 21 +136.9999999999982 + 0 +LINE + 5 +C5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-159 + 20 +-137 + 11 +0 + 21 +-137 + 0 +LINE + 5 +C6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-156 + 20 +136.9999999999982 + 11 +-156 + 21 +-137 + 0 +LINE + 5 +C7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-159 + 20 +139.9999999999982 + 11 +-159 + 21 +-140 + 0 +CIRCLE + 5 +C8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-115.0499999999992 + 20 +-123.5000017100228 + 40 +4 + 0 +LINE + 5 +C9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-199 + 20 +-54.99550574930982 + 11 +-199 + 21 +-64.99550574930981 + 0 +LINE + 5 +CA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-204 + 20 +-59.99550574930982 + 11 +-194 + 21 +-59.99550574930982 + 0 +LINE + 5 +CB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-204 + 20 +59.99550574930982 + 11 +-194 + 21 +59.99550574930982 + 0 +LINE + 5 +CC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-199 + 20 +54.99550574930982 + 11 +-199 + 21 +64.99550574930981 + 0 +CIRCLE + 5 +CD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-143.4165589395707 + 20 +124.5000015088426 + 40 +4 + 0 +CIRCLE + 5 +CE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-82.29999999999927 + 20 +124.5000015088426 + 40 +4 + 0 +DIMENSION + 5 +CF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +199 + 20 +147.1785187405912 + 30 +0 + 11 +97.5 + 21 +150.6785187405912 + 31 +0 + 70 + 32 + 71 + 5 + 3 +BOK + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +0 + 23 +139.9999999999982 + 33 +0 + 14 +199 + 24 +59.99950574930881 + 34 +0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +D0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +184 + 20 +120 + 11 +184 + 21 +-120 + 0 +LINE + 5 +D1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +214 + 20 +-120 + 11 +214 + 21 +120 + 0 +DIMENSION + 5 +D2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +226.3829540258957 + 20 +120 + 30 +0 + 11 +222.8829540258921 + 21 +1.819e-12 + 31 +0 + 70 + 32 + 71 + 5 + 3 +STANDARD + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +214 + 23 +-120 + 33 +0 + 14 +214 + 24 +120 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +DIMENSION + 5 +D3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +209.5134058222611 + 20 +59.99950574930881 + 30 +0 + 11 +206.0134058222575 + 21 +1.819e-12 + 31 +0 + 70 + 32 + 71 + 5 + 3 +STANDARD + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +199 + 23 +-59.99950574931062 + 33 +0 + 14 +199 + 24 +59.99950574930881 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +LWPOLYLINE + 5 +D4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +129.4099999999998 + 20 +112 + 10 +123.4099999999998 + 20 +112 + 10 +123.4099999999998 + 20 +-112 + 10 +129.4099999999998 + 20 +-112 + 0 +LWPOLYLINE + 5 +D5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +3 + 20 +-65.35424567125301 + 10 +3 + 20 +-24.64574829338017 + 0 +DIMENSION + 5 +D6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +169.3235960792226 + 20 +-100 + 30 +0 + 11 +165.823596079219 + 21 +1.819e-12 + 31 +0 + 70 + 32 + 71 + 5 + 3 +STANDARD + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +173.5166852264519 + 23 +100 + 33 +0 + 14 +173.5166852264519 + 24 +-100 + 34 +0 + 50 +90 +100 +AcDbRotatedDimension + 0 +LINE + 5 +D7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +135.6562978838046 + 20 +-112 + 11 +175.3431457505066 + 21 +-112 + 0 +LWPOLYLINE + 5 +D8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +-92.64575473110744 + 10 +65.96000000000276 + 20 +-112 + 10 +71.96000000000276 + 20 +-112 + 10 +71.96000000000276 + 20 +-92.64575473110744 + 0 +LWPOLYLINE + 5 +D9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +-112 + 10 +0 + 20 +-112 + 10 +3 + 20 +-112 + 10 +3 + 20 +-104.6457547311074 + 0 +LINE + 5 +DA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-156 + 20 +-111.9999999999963 + 11 +-123.4099999999926 + 21 +-111.9999999999963 + 0 +LINE + 5 +DB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-118.4647548051325 + 20 +-111.9999999999963 + 11 +-65.95999999999913 + 21 +-111.9999999999982 + 0 +LINE + 5 +DC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-58.99011700600749 + 20 +-111.9999999999982 + 11 +3.000000000003637 + 21 +-111.9999999999982 + 0 +LINE + 5 +DD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +9.024047086841165 + 20 +-111.9999999999982 + 11 +71.10000000000218 + 21 +-111.9999999999982 + 0 +CIRCLE + 5 +DE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-49.54999999999927 + 20 +-123.500001710021 + 40 +4 + 0 +CIRCLE + 5 +DF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +15.95000000000073 + 20 +-123.500001710021 + 40 +4 + 0 +LINE + 5 +E0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +77.19589894258388 + 20 +-112 + 11 +127.8500000000022 + 21 +-112 + 0 +CIRCLE + 5 +E1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +81.45000000000071 + 20 +-123.500001710021 + 40 +4 + 0 +CIRCLE + 5 +E2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +143.2028837674916 + 20 +-123.500001710021 + 40 +4 + 0 +LWPOLYLINE + 5 +E3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +-98.00000342004388 + 10 +49.9800000000032 + 20 +-98.00000342004388 + 10 +49.9800000000032 + 20 +-106.0000034200438 + 10 +65.96000000000276 + 20 +-106.0000034200438 + 0 +LWPOLYLINE + 5 +E4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.68000000000393 + 20 +-63.99999698231477 + 10 +49.9800000000032 + 20 +-63.99999698231477 + 10 +49.9800000000032 + 20 +-71.99999698231477 + 10 +65.68000000000393 + 20 +-71.99999698231477 + 0 +CIRCLE + 5 +E5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +-67.99999698231477 + 40 +4 + 0 +LWPOLYLINE + 5 +E6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +3 + 20 +-99.3542521089803 + 10 +3 + 20 +-70.64574829338017 + 0 +CIRCLE + 5 +E7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +-102.0000034200438 + 40 +4 + 0 +LINE + 5 +E8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-156 + 20 +-100.0000000000018 + 11 +-141.6562075504262 + 21 +-100.0000000000018 + 0 +LINE + 5 +E9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-134.1437924495767 + 20 +-100.0000000000018 + 11 +-133.9000000000014 + 21 +-100.0000000000018 + 0 +LINE + 5 +EA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-88.4759003594263 + 20 +-100.0000000000018 + 11 +-87.94000000000233 + 21 +-100.0000000000018 + 0 +LINE + 5 +EB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-49.97999999999956 + 20 +-100 + 11 +-49.44409964057195 + 21 +-100 + 0 +LINE + 5 +EC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-42.51590035942718 + 20 +-100 + 11 +-3.464099640572385 + 21 +-100 + 0 +LINE + 5 +ED +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3.464099640572385 + 20 +-100 + 11 +42.51590035943081 + 21 +-100 + 0 +CIRCLE + 5 +EE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +-67.99999698231477 + 40 +4 + 0 +LWPOLYLINE + 5 +EF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +112 + 10 +65.96000000000276 + 20 +94.64575432874879 + 0 +LWPOLYLINE + 5 +F0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +-87.35425210897847 + 10 +71.96000000000276 + 20 +-47.14594496440986 + 0 +LWPOLYLINE + 5 +F1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +72.2400000000016 + 20 +-63.99999698231477 + 10 +87.94000000000233 + 20 +-63.99999698231477 + 10 +87.94000000000233 + 20 +-71.99999698231477 + 10 +72.2400000000016 + 20 +-71.99999698231477 + 0 +CIRCLE + 5 +F2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.9200000000019 + 20 +-90.00000342004387 + 40 +4 + 0 +LINE + 5 +F3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +87.94000000000233 + 20 +-100.9998097666976 + 11 +88.06706666003809 + 21 +-100.9998097666976 + 0 +CIRCLE + 5 +F4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +-102.0000034200438 + 40 +4 + 0 +LINE + 5 +F5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +87.94000000000233 + 20 +-100.9998097666976 + 11 +87.99313393794363 + 21 +-100.9998097666976 + 0 +CIRCLE + 5 +F6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96000000000276 + 20 +-90.00000342004387 + 40 +4 + 0 +LWPOLYLINE + 5 +F7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +-98.00000342004388 + 10 +87.94000000000233 + 20 +-98.00000342004388 + 10 +87.94000000000233 + 20 +-106.0000034200438 + 10 +71.96000000000276 + 20 +-106.0000034200438 + 0 +LWPOLYLINE + 5 +F8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +123.4099999999998 + 20 +-86.00000342004387 + 10 +118.9200000000019 + 20 +-86.00000342004387 + 10 +118.9200000000019 + 20 +-94.00000342004387 + 10 +123.4099999999998 + 20 +-94.00000342004387 + 0 +CIRCLE + 5 +F9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.9200000000019 + 20 +-44.50019365334447 + 40 +4 + 0 +CIRCLE + 5 +FA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96000000000276 + 20 +-44.50019365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +FB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +123.4099999999998 + 20 +-40.50019365334446 + 10 +118.9200000000019 + 20 +-40.50019365334446 + 10 +118.9200000000019 + 20 +-48.50019365334446 + 10 +123.4099999999998 + 20 +-48.50019365334446 + 0 +ARC + 5 +FC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +181 + 20 +-105 + 40 +9 +100 +AcDbArc + 50 +90 + 51 +270 + 0 +LINE + 5 +FD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +184 + 20 +-120 + 11 +184 + 21 +-114 + 0 +LINE + 5 +FE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +184 + 20 +-114 + 11 +181 + 21 +-114 + 0 +LINE + 5 +FF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +214 + 20 +-120 + 11 +184 + 21 +-120 + 0 +DIMENSION + 5 +100 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbDimension + 10 +214 + 20 +-130.8769043016091 + 30 +0 + 11 +199 + 21 +-127.3769043016091 + 31 +0 + 70 + 32 + 71 + 5 + 3 +STANDARD + 53 +0 +210 +0 +220 +0 +230 +1 +100 +AcDbAlignedDimension + 13 +184 + 23 +-120 + 33 +0 + 14 +214 + 24 +-120 + 34 +0 +100 +AcDbRotatedDimension + 0 +LINE + 5 +101 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +181 + 20 +-96 + 11 +184 + 21 +-96 + 0 +CIRCLE + 5 +102 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +199 + 20 +-59.99950574931062 + 40 +5.5 + 0 +LINE + 5 +103 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +123.4099999999998 + 20 +112 + 11 +175.3431457505066 + 21 +112 + 0 +LINE + 5 +104 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +133.9000000000014 + 20 +100 + 11 +135.7530592391485 + 21 +100 + 0 +LINE + 5 +105 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +140.0469407608579 + 20 +100 + 11 +173.5166852264519 + 21 +100 + 0 +LWPOLYLINE + 5 +106 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +123.4099999999998 + 20 +50.49980634665553 + 10 +118.9200000000019 + 20 +50.49980634665553 + 10 +118.9200000000019 + 20 +42.49980634665553 + 10 +123.4099999999998 + 20 +42.49980634665553 + 0 +CIRCLE + 5 +107 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.9200000000019 + 20 +46.49980634665553 + 40 +4 + 0 +CIRCLE + 5 +108 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +23.00000000000364 + 20 +46.49980634665553 + 40 +4 + 0 +CIRCLE + 5 +109 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96000000000276 + 20 +46.49980634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +10A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +3 + 20 +26.64575432874881 + 10 +3 + 20 +67.35425170661983 + 0 +LWPOLYLINE + 5 +10B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +50.49980634665553 + 10 +19.00000000000364 + 20 +50.49980634665553 + 10 +19.00000000000364 + 20 +42.49980634665553 + 10 +3 + 20 +42.49980634665553 + 0 +LWPOLYLINE + 5 +10C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +28.00000301768523 + 10 +49.9800000000032 + 20 +28.00000301768523 + 10 +49.9800000000032 + 20 +20.00000301768523 + 10 +65.96000000000276 + 20 +20.00000301768523 + 0 +LWPOLYLINE + 5 +10D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +-17.99999698231477 + 10 +49.9800000000032 + 20 +-17.99999698231477 + 10 +49.9800000000032 + 20 +-25.99999698231477 + 10 +65.96000000000276 + 20 +-25.99999698231477 + 0 +LWPOLYLINE + 5 +10E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +3 + 20 +-19.35424567125119 + 10 +3 + 20 +21.35425170661983 + 0 +CIRCLE + 5 +10F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +23.00000000000364 + 20 +0.9998063466555323 + 40 +4 + 0 +CIRCLE + 5 +110 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +-21.99999698231477 + 40 +4 + 0 +LWPOLYLINE + 5 +111 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +4.999806346655532 + 10 +19.00000000000364 + 20 +4.999806346655532 + 10 +19.00000000000364 + 20 +-3.000193653344467 + 10 +3 + 20 +-3.000193653344467 + 0 +CIRCLE + 5 +112 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +24.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +113 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.9200000000019 + 20 +0.9998063466555323 + 40 +4 + 0 +CIRCLE + 5 +114 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +-21.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +115 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96000000000276 + 20 +0.9998063466555323 + 40 +4 + 0 +LWPOLYLINE + 5 +116 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +-17.99999698231477 + 10 +87.94000000000233 + 20 +-17.99999698231477 + 10 +87.94000000000233 + 20 +-25.99999698231477 + 10 +71.96000000000276 + 20 +-25.99999698231477 + 0 +LWPOLYLINE + 5 +117 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +123.4099999999998 + 20 +4.999806346655532 + 10 +118.9200000000019 + 20 +4.999806346655532 + 10 +118.9200000000019 + 20 +-3.000193653344467 + 10 +123.4099999999998 + 20 +-3.000193653344467 + 0 +CIRCLE + 5 +118 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +24.00000301768523 + 40 +4 + 0 +LWPOLYLINE + 5 +119 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +28.00000301768523 + 10 +87.94000000000233 + 20 +28.00000301768523 + 10 +87.94000000000233 + 20 +20.00000301768523 + 10 +71.96000000000276 + 20 +20.00000301768523 + 0 +LWPOLYLINE + 5 +11A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +108.0000030176852 + 10 +49.9800000000032 + 20 +108.0000030176852 + 10 +49.9800000000032 + 20 +100.0000030176852 + 10 +65.96000000000276 + 20 +100.0000030176852 + 0 +LWPOLYLINE + 5 +11B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +74.00000301768523 + 10 +49.9800000000032 + 20 +74.00000301768523 + 10 +49.9800000000032 + 20 +66.00000301768523 + 10 +65.96000000000276 + 20 +66.00000301768523 + 0 +LINE + 5 +11C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-156 + 20 +112 + 11 +-135.4174291795243 + 21 +112 + 0 +LINE + 5 +11D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-129.4100000000035 + 20 +112 + 11 +-77.15116121854589 + 21 +112 + 0 +LINE + 5 +11E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-71.9600000000064 + 20 +112 + 11 +-8.958275865730684 + 21 +112 + 0 +LINE + 5 +11F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-2.999999999996362 + 20 +112 + 11 +59.17631431428526 + 21 +112 + 0 +CIRCLE + 5 +120 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +23.00000000000364 + 20 +92.00000301768524 + 40 +4 + 0 +LWPOLYLINE + 5 +121 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +3 + 20 +72.64575432874881 + 10 +3 + 20 +101.3542517066198 + 0 +LWPOLYLINE + 5 +122 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +96.00000301768524 + 10 +19.00000000000364 + 20 +96.00000301768524 + 10 +19.00000000000364 + 20 +88.00000301768523 + 10 +3 + 20 +88.00000301768523 + 0 +CIRCLE + 5 +123 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +70.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +124 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-16.79999999999927 + 20 +124.5000015088426 + 40 +4 + 0 +CIRCLE + 5 +125 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +45.9800000000032 + 20 +104.0000030176852 + 40 +4 + 0 +CIRCLE + 5 +126 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +48.70000000000072 + 20 +124.5000015088426 + 40 +4 + 0 +LWPOLYLINE + 5 +127 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +106.6457543287488 + 10 +3 + 20 +112 + 10 +-3 + 20 +112 + 10 +-3 + 20 +106.6457543287488 + 0 +LWPOLYLINE + 5 +128 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-3 + 20 +101.3542517066198 + 10 +-3 + 20 +72.64575432874881 + 0 +LWPOLYLINE + 5 +129 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-3 + 20 +67.35425170661983 + 10 +-3 + 20 +26.64575432874881 + 0 +LWPOLYLINE + 5 +12A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-3 + 20 +21.35425170661983 + 10 +-3 + 20 +-19.35424567125119 + 0 +LWPOLYLINE + 5 +12B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-3 + 20 +-24.64574829338017 + 10 +-3 + 20 +-65.35424567125119 + 0 +LWPOLYLINE + 5 +12C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-3 + 20 +-70.64574829338017 + 10 +-3 + 20 +-99.35425210897847 + 0 +LWPOLYLINE + 5 +12D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +-104.6457547311074 + 10 +-3 + 20 +-112 + 10 +0 + 20 +-112 + 10 +-3 + 20 +-112 + 0 +LINE + 5 +12E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-156 + 20 +100 + 11 +-140.0469407608579 + 21 +100 + 0 +LINE + 5 +12F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-135.7530592391449 + 20 +100 + 11 +-133.9000000000014 + 21 +100 + 0 +LINE + 5 +130 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-123.4100000000035 + 20 +100 + 11 +-71.95999999999913 + 21 +100 + 0 +LINE + 5 +131 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-65.95999999999913 + 20 +100 + 11 +-3 + 21 +100 + 0 +LINE + 5 +132 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +3 + 20 +100 + 11 +49.9800000000032 + 21 +100 + 0 +LWPOLYLINE + 5 +133 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +123.4099999999998 + 20 +96.00000301768524 + 10 +118.9200000000019 + 20 +96.00000301768524 + 10 +118.9200000000019 + 20 +88.00000301768523 + 10 +123.4099999999998 + 20 +88.00000301768523 + 0 +CIRCLE + 5 +134 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.9200000000019 + 20 +92.00000301768524 + 40 +4 + 0 +CIRCLE + 5 +135 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96000000000276 + 20 +92.00000301768524 + 40 +4 + 0 +CIRCLE + 5 +136 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +70.00000301768523 + 40 +4 + 0 +LWPOLYLINE + 5 +137 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +74.00000301768523 + 10 +87.94000000000233 + 20 +74.00000301768523 + 10 +87.94000000000233 + 20 +66.00000301768523 + 10 +71.96000000000276 + 20 +66.00000301768523 + 0 +CIRCLE + 5 +138 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +114.2000000000007 + 20 +124.5000015088426 + 40 +4 + 0 +LINE + 5 +139 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +87.94000000000233 + 20 +100 + 11 +123.4099999999998 + 21 +100 + 0 +LINE + 5 +13A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +65.96000000000276 + 20 +112 + 11 +118.4415006548188 + 21 +112 + 0 +CIRCLE + 5 +13B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +91.94000000000233 + 20 +104.0000030176852 + 40 +4 + 0 +LWPOLYLINE + 5 +13C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +108.0000030176852 + 10 +87.94000000000233 + 20 +108.0000030176852 + 10 +87.94000000000233 + 20 +100.0000030176852 + 10 +71.96000000000276 + 20 +100.0000030176852 + 0 +CIRCLE + 5 +13D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +199 + 20 +59.99950574930881 + 40 +5.5 + 0 +LINE + 5 +13E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +184 + 20 +96 + 11 +181 + 21 +96 + 0 +LINE + 5 +13F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +184 + 20 +114 + 11 +181 + 21 +114 + 0 +ARC + 5 +140 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +181 + 20 +105 + 40 +9 +100 +AcDbArc + 50 +90 + 51 +270 + 0 +LINE + 5 +141 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +214 + 20 +120 + 11 +184 + 21 +120 + 0 +LINE + 5 +142 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +87.94000000000233 + 20 +-100 + 11 +88.47590035942994 + 21 +-100 + 0 +CIRCLE + 5 +143 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +23.00000000000364 + 20 +-44.50019365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +144 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +-40.50019365334446 + 10 +19.00000000000364 + 20 +-40.50019365334446 + 10 +19.00000000000364 + 20 +-48.50019365334446 + 10 +3 + 20 +-48.50019365334446 + 0 +CIRCLE + 5 +145 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +23.00000000000364 + 20 +-90.00000342004387 + 40 +4 + 0 +LWPOLYLINE + 5 +146 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +3 + 20 +-86.00000342004387 + 10 +19.00000000000364 + 20 +-86.00000342004387 + 10 +19.00000000000364 + 20 +-94.00000342004387 + 10 +3 + 20 +-94.00000342004387 + 0 +LINE + 5 +147 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +5.656021735780086 + 20 +-109.0090890118426 + 11 +15.61511074762165 + 21 +-117.8530689860872 + 0 +LINE + 5 +148 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +0.3439782642235514 + 20 +-114.9909109881555 + 11 +10.30306727606512 + 21 +-123.8348909624001 + 0 +LINE + 5 +149 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +5.656021735780086 + 20 +-109.0090890118426 + 11 +0.3439782642235514 + 21 +-114.9909109881555 + 0 +LINE + 5 +14A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15.61511074762165 + 20 +-117.8530689860872 + 11 +10.30306727606512 + 21 +-123.8348909624001 + 0 +LINE + 5 +14B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +49.44409964057559 + 20 +-100 + 11 +49.9800000000032 + 21 +-100 + 0 +LWPOLYLINE + 5 +14C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +89.35425170661983 + 10 +65.96000000000276 + 20 +49.14555765771911 + 0 +LWPOLYLINE + 5 +14D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +94.64575432874879 + 10 +71.96000000000276 + 20 +112 + 0 +LWPOLYLINE + 5 +14E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +43.85405503559195 + 10 +65.96000000000276 + 20 +3.645557657719109 + 0 +LWPOLYLINE + 5 +14F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +49.14555765772092 + 10 +71.96000000000276 + 20 +89.35425170661983 + 0 +LWPOLYLINE + 5 +150 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +-41.85444234227907 + 10 +71.96000000000276 + 20 +-1.645944964409864 + 0 +LWPOLYLINE + 5 +151 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +-47.14594496440986 + 10 +65.96000000000276 + 20 +-87.35425210897847 + 0 +LINE + 5 +152 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +95.40409964057471 + 20 +-100 + 11 +123.4099999999998 + 21 +-100 + 0 +LINE + 5 +153 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +141.3640996405738 + 20 +-100 + 11 +173.5166852264519 + 21 +-100 + 0 +LINE + 5 +154 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +131.9715172855431 + 20 +-108.9277647883209 + 11 +142.6921658413557 + 21 +-117.8662492128023 + 0 +LINE + 5 +155 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +126.8484827144602 + 20 +-115.0722352116772 + 11 +137.5691312702729 + 21 +-124.0107196361587 + 0 +LINE + 5 +156 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +131.9715172855431 + 20 +-108.9277647883209 + 11 +126.8484827144602 + 21 +-115.0722352116772 + 0 +LINE + 5 +157 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +142.6921658413557 + 20 +-117.8662492128023 + 11 +137.5691312702729 + 21 +-124.0107196361587 + 0 +LINE + 5 +158 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +113.3524198494487 + 20 +118.9070051841172 + 11 +120.189711762363 + 21 +109.6272919129114 + 0 +LINE + 5 +159 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +119.7929963247261 + 20 +123.6524213582925 + 11 +126.6302882376367 + 21 +114.3727080870885 + 0 +LINE + 5 +15A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +119.7929963247261 + 20 +123.6524213582925 + 11 +113.3524198494487 + 21 +118.9070051841172 + 0 +LINE + 5 +15B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +126.6302882376403 + 20 +114.3727080870885 + 11 +120.189711762363 + 21 +109.6272919129114 + 0 +LINE + 5 +15C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +75.04516404107198 + 20 +-109.454069356856 + 11 +81.989233397926 + 21 +-117.8689070258115 + 0 +LINE + 5 +15D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +68.87483595893355 + 20 +-114.5459306431421 + 11 +75.81890531578756 + 21 +-122.9607683120957 + 0 +LINE + 5 +15E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +75.04516404107198 + 20 +-109.454069356856 + 11 +68.87483595893355 + 21 +-114.5459306431421 + 0 +LINE + 5 +15F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +81.989233397926 + 20 +-117.8689070258096 + 11 +75.81890531578756 + 21 +-122.9607683120957 + 0 +LINE + 5 +160 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-65.95999999999913 + 20 +-112.0000000000018 + 11 +-71.95999999999913 + 21 +-112.0000000000018 + 0 +LINE + 5 +161 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-120.1745689203417 + 20 +-109.6479826257491 + 11 +-114.1665862945992 + 21 +-117.912553256112 + 0 +LINE + 5 +162 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-126.6454310796544 + 20 +-114.3520173742581 + 11 +-120.6374484539119 + 21 +-122.616588004621 + 0 +LINE + 5 +163 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-63.66440909642552 + 20 +-108.7242920759909 + 11 +-50.53011702043659 + 21 +-117.9287028824365 + 0 +LINE + 5 +164 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-68.25559090357272 + 20 +-115.2757079240127 + 11 +-55.12129882758381 + 21 +-124.4801187304583 + 0 +LINE + 5 +165 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-120.1745689203417 + 20 +-109.6479826257491 + 11 +-126.6454310796544 + 21 +-114.3520173742581 + 0 +LINE + 5 +166 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-114.1665862945992 + 20 +-117.912553256112 + 11 +-120.6374484539119 + 21 +-122.616588004621 + 0 +LINE + 5 +167 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-63.66440909642552 + 20 +-108.7242920759909 + 11 +-68.25559090357272 + 21 +-115.2757079240127 + 0 +LINE + 5 +168 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-50.53011702043659 + 20 +-117.9287028824365 + 11 +-55.12129882758381 + 21 +-124.4801187304583 + 0 +LINE + 5 +169 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-123.4100000000035 + 20 +-112.0000000000036 + 11 +-129.4099999999962 + 21 +-112.0000000000036 + 0 +LINE + 5 +16A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-129.4099999999962 + 20 +-112.0000000000036 + 11 +-129.4100000000035 + 21 +111.9999999999963 + 0 +LINE + 5 +16B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-129.4100000000035 + 20 +111.9999999999963 + 11 +-123.4100000000035 + 21 +111.9999999999963 + 0 +LINE + 5 +16C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-123.4100000000035 + 20 +111.9999999999963 + 11 +-123.4100000000035 + 21 +-112.0000000000036 + 0 +LINE + 5 +16D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-137.7688197378775 + 20 +124.8210029257425 + 11 +-126.7466311076095 + 21 +114.9843703092938 + 0 +LINE + 5 +16E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-143.0955575226726 + 20 +118.8522623071494 + 11 +-132.073368892401 + 21 +109.0156296907007 + 0 +LINE + 5 +16F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-143.0955575226726 + 20 +118.8522623071494 + 11 +-137.7688197378775 + 21 +124.8210029257425 + 0 +LINE + 5 +170 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-132.073368892401 + 20 +109.0156296907007 + 11 +-126.7466311076095 + 21 +114.9843703092938 + 0 +LINE + 5 +171 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-11.1500437666109 + 20 +124.7792765718513 + 11 +-0.3146594148092845 + 21 +114.9646156481976 + 0 +LINE + 5 +172 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-16.5207249369887 + 20 +118.850045275456 + 11 +-5.685340585187077 + 21 +109.0353843518023 + 0 +LINE + 5 +173 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-0.3146594148092845 + 20 +114.9646156481976 + 11 +-5.685340585187077 + 21 +109.0353843518023 + 0 +LINE + 5 +174 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-16.5207249369887 + 20 +118.850045275456 + 11 +-11.1500437666109 + 21 +124.7792765718513 + 0 +LINE + 5 +175 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-76.66827384633143 + 20 +123.9674036022879 + 11 +-68.87783796988879 + 21 +114.5495641235629 + 0 +LINE + 5 +176 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-82.83259790655575 + 20 +118.8682753551711 + 11 +-75.0421620301131 + 21 +109.4504358764461 + 0 +LINE + 5 +177 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-68.87783796988879 + 20 +114.5495641235629 + 11 +-75.0421620301131 + 21 +109.4504358764461 + 0 +LINE + 5 +178 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-82.83259790655575 + 20 +118.8682753551711 + 11 +-76.66827384632779 + 21 +123.9674036022879 + 0 +LWPOLYLINE + 5 +179 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +71.96000000000276 + 20 +3.645557657720928 + 10 +71.96000000000276 + 20 +43.85405503559013 + 0 +LWPOLYLINE + 5 +17A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +65.96000000000276 + 20 +-1.645944964408045 + 10 +65.96000000000276 + 20 +-41.85444234228088 + 0 +LINE + 5 +17B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-159 + 20 +-140 + 11 +0 + 21 +-140 + 0 +LINE + 5 +17C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-159 + 20 +139.9999999999982 + 11 +0 + 21 +139.9999999999982 + 0 +ARC + 5 +17D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +126.4100003772109 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +13.2480371091573 + 51 +60.00000415932957 + 0 +ARC + 5 +17E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +126.4100003772109 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +120.0000041592981 + 51 +239.9999958407019 + 0 +ARC + 5 +17F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96300882907599 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +19.47124355805857 + 51 +60.00000415932957 + 0 +ARC + 5 +180 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.95699117092954 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +119.9999958406704 + 51 +134.3359430318186 + 0 +ARC + 5 +181 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.95699117092954 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +152.6922864937442 + 51 +160.5287564419414 + 0 +ARC + 5 +182 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0.0030088290732238 + 20 +106.0000007544185 + 40 +6 +100 +AcDbArc + 50 +299.9668284538085 + 51 +60.00000415932957 + 0 +ARC + 5 +183 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +126.4100003772109 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +299.9999958406704 + 51 +5.978187031658905 + 0 +ARC + 5 +184 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +126.4100003772109 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +120.0000041592981 + 51 +239.9999958407019 + 0 +ARC + 5 +185 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.96300882907599 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +299.9999958406704 + 51 +359.9999745452056 + 0 +ARC + 5 +186 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +68.95699117092954 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +180.0000254547943 + 51 +240.0000041593296 + 0 +ARC + 5 +187 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0.0030088290732238 + 20 +-106.0000007544185 + 40 +6 +100 +AcDbArc + 50 +299.9999958406704 + 51 +48.63347898135322 + 0 +CIRCLE + 5 +188 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +-102.0000034200438 + 40 +4 + 0 +CIRCLE + 5 +189 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +-67.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +18A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +-21.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +18B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +24.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +18C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +70.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +18D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +0 + 20 +104.0000030176852 + 40 +4 + 0 +ARC + 5 +18E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-0.0030088290732238 + 20 +106.0000007544185 + 40 +6 +100 +AcDbArc + 50 +119.9999958406704 + 51 +240.0331715461915 + 0 +ARC + 5 +18F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-0.0030088290732238 + 20 +-106.0000007544185 + 40 +6 +100 +AcDbArc + 50 +131.3665210186468 + 51 +240.0000041593296 + 0 +LWPOLYLINE + 5 +190 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +-92.64575473110744 + 10 +-65.95999999999913 + 20 +-112 + 10 +-71.95999999999913 + 20 +-112 + 10 +-71.95999999999913 + 20 +-92.64575473110744 + 0 +LWPOLYLINE + 5 +191 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +-98.00000342004388 + 10 +-49.97999999999956 + 20 +-98.00000342004388 + 10 +-49.97999999999956 + 20 +-106.0000034200438 + 10 +-65.95999999999913 + 20 +-106.0000034200438 + 0 +LWPOLYLINE + 5 +192 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.68000000000029 + 20 +-63.99999698231477 + 10 +-49.97999999999956 + 20 +-63.99999698231477 + 10 +-49.97999999999956 + 20 +-71.99999698231477 + 10 +-65.68000000000029 + 20 +-71.99999698231477 + 0 +CIRCLE + 5 +193 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +-67.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +194 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +-102.0000034200438 + 40 +4 + 0 +CIRCLE + 5 +195 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +-67.99999698231477 + 40 +4 + 0 +LWPOLYLINE + 5 +196 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +112 + 10 +-65.95999999999913 + 20 +94.64575432874879 + 0 +LWPOLYLINE + 5 +197 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +-87.35425210897847 + 10 +-71.95999999999913 + 20 +-47.14594496440986 + 0 +LWPOLYLINE + 5 +198 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-72.23999999999796 + 20 +-63.99999698231477 + 10 +-87.93999999999869 + 20 +-63.99999698231477 + 10 +-87.93999999999869 + 20 +-71.99999698231477 + 10 +-72.23999999999796 + 20 +-71.99999698231477 + 0 +CIRCLE + 5 +199 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +-102.0000034200438 + 40 +4 + 0 +LWPOLYLINE + 5 +19A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +-98.00000342004388 + 10 +-87.94000000000233 + 20 +-98.00000342004388 + 10 +-87.94000000000233 + 20 +-106.0000034200438 + 10 +-71.95999999999913 + 20 +-106.0000034200438 + 0 +CIRCLE + 5 +19B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.95999999999913 + 20 +-44.50019365334447 + 40 +4 + 0 +CIRCLE + 5 +19C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.95999999999913 + 20 +46.49980634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +19D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +28.00000301768523 + 10 +-49.97999999999956 + 20 +28.00000301768523 + 10 +-49.97999999999956 + 20 +20.00000301768523 + 10 +-65.95999999999913 + 20 +20.00000301768523 + 0 +LWPOLYLINE + 5 +19E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +-17.99999698231477 + 10 +-49.97999999999956 + 20 +-17.99999698231477 + 10 +-49.97999999999956 + 20 +-25.99999698231477 + 10 +-65.95999999999913 + 20 +-25.99999698231477 + 0 +CIRCLE + 5 +19F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +-21.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +1A0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +24.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +1A1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +-21.99999698231477 + 40 +4 + 0 +CIRCLE + 5 +1A2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.95999999999913 + 20 +0.9998063466555323 + 40 +4 + 0 +LWPOLYLINE + 5 +1A3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +-17.99999698231477 + 10 +-87.94000000000233 + 20 +-17.99999698231477 + 10 +-87.94000000000233 + 20 +-25.99999698231477 + 10 +-71.95999999999913 + 20 +-25.99999698231477 + 0 +CIRCLE + 5 +1A4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +24.00000301768523 + 40 +4 + 0 +LWPOLYLINE + 5 +1A5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +28.00000301768523 + 10 +-87.93999999999869 + 20 +28.00000301768523 + 10 +-87.93999999999869 + 20 +20.00000301768523 + 10 +-71.95999999999913 + 20 +20.00000301768523 + 0 +LWPOLYLINE + 5 +1A6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +108.0000030176852 + 10 +-49.97999999999956 + 20 +108.0000030176852 + 10 +-49.97999999999956 + 20 +100.0000030176852 + 10 +-65.95999999999913 + 20 +100.0000030176852 + 0 +LWPOLYLINE + 5 +1A7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +74.00000301768523 + 10 +-49.97999999999956 + 20 +74.00000301768523 + 10 +-49.97999999999956 + 20 +66.00000301768523 + 10 +-65.95999999999913 + 20 +66.00000301768523 + 0 +CIRCLE + 5 +1A8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +70.00000301768523 + 40 +4 + 0 +CIRCLE + 5 +1A9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-45.97999999999956 + 20 +104.0000030176852 + 40 +4 + 0 +CIRCLE + 5 +1AA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.95999999999913 + 20 +92.00000301768524 + 40 +4 + 0 +CIRCLE + 5 +1AB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +70.00000301768523 + 40 +4 + 0 +LWPOLYLINE + 5 +1AC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +74.00000301768523 + 10 +-87.94000000000233 + 20 +74.00000301768523 + 10 +-87.94000000000233 + 20 +66.00000301768523 + 10 +-71.95999999999913 + 20 +66.00000301768523 + 0 +CIRCLE + 5 +1AD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-91.93999999999869 + 20 +104.0000030176852 + 40 +4 + 0 +LWPOLYLINE + 5 +1AE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +108.0000030176852 + 10 +-87.94000000000233 + 20 +108.0000030176852 + 10 +-87.94000000000233 + 20 +100.0000030176852 + 10 +-71.95999999999913 + 20 +100.0000030176852 + 0 +LWPOLYLINE + 5 +1AF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +89.35425170661983 + 10 +-65.95999999999913 + 20 +49.14555765771911 + 0 +LWPOLYLINE + 5 +1B0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +94.64575432874879 + 10 +-71.95999999999913 + 20 +112 + 0 +LWPOLYLINE + 5 +1B1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +43.85405503559195 + 10 +-65.95999999999913 + 20 +3.645557657719109 + 0 +LWPOLYLINE + 5 +1B2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +49.14555765772092 + 10 +-71.95999999999913 + 20 +89.35425170661983 + 0 +LWPOLYLINE + 5 +1B3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +-41.85444234227907 + 10 +-71.95999999999913 + 20 +-1.645944964409864 + 0 +LWPOLYLINE + 5 +1B4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +-47.14594496440986 + 10 +-65.95999999999913 + 20 +-87.35425210897847 + 0 +LWPOLYLINE + 5 +1B5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-71.95999999999913 + 20 +3.645557657720928 + 10 +-71.95999999999913 + 20 +43.85405503559013 + 0 +LWPOLYLINE + 5 +1B6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0 + 10 +-65.95999999999913 + 20 +-1.645944964408045 + 10 +-65.95999999999913 + 20 +-41.85444234228088 + 0 +ARC + 5 +1B7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.96300882907235 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +119.9999958406704 + 51 +160.5287564419414 + 0 +ARC + 5 +1B8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.9569911709259 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +19.47124355805857 + 51 +60.00000415932957 + 0 +ARC + 5 +1B9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.96300882907235 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +180.0000254547943 + 51 +240.0000041593296 + 0 +CIRCLE + 5 +1BA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-23 + 20 +46.49980634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +1BB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +50.49980634665553 + 10 +-19 + 20 +50.49980634665553 + 10 +-19 + 20 +42.49980634665553 + 10 +-3 + 20 +42.49980634665553 + 0 +CIRCLE + 5 +1BC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-23 + 20 +0.9998063466555323 + 40 +4 + 0 +LWPOLYLINE + 5 +1BD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +4.999806346655532 + 10 +-19 + 20 +4.999806346655532 + 10 +-19 + 20 +-3.000193653344467 + 10 +-3 + 20 +-3.000193653344467 + 0 +CIRCLE + 5 +1BE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-23 + 20 +92.00000301768524 + 40 +4 + 0 +LWPOLYLINE + 5 +1BF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +96.00000301768524 + 10 +-19 + 20 +96.00000301768524 + 10 +-19 + 20 +88.00000301768523 + 10 +-3 + 20 +88.00000301768523 + 0 +CIRCLE + 5 +1C0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-23 + 20 +-44.50019365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +1C1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +-40.50019365334446 + 10 +-19 + 20 +-40.50019365334446 + 10 +-19 + 20 +-48.50019365334446 + 10 +-3 + 20 +-48.50019365334446 + 0 +CIRCLE + 5 +1C2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-23 + 20 +-90.00000342004387 + 40 +4 + 0 +LWPOLYLINE + 5 +1C3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-3 + 20 +-86.00000342004387 + 10 +-19 + 20 +-86.00000342004387 + 10 +-19 + 20 +-94.00000342004387 + 10 +-3 + 20 +-94.00000342004387 + 0 +CIRCLE + 5 +1C4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-114.9199999999982 + 20 +-90.00000342004387 + 40 +4 + 0 +LWPOLYLINE + 5 +1C5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-123.4099999999998 + 20 +-86.00000342004387 + 10 +-118.9199999999982 + 20 +-86.00000342004387 + 10 +-118.9199999999982 + 20 +-94.00000342004387 + 10 +-123.4099999999998 + 20 +-94.00000342004387 + 0 +CIRCLE + 5 +1C6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-114.9199999999982 + 20 +-44.50019365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +1C7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-123.4099999999998 + 20 +-40.50019365334446 + 10 +-118.9199999999982 + 20 +-40.50019365334446 + 10 +-118.9199999999982 + 20 +-48.50019365334446 + 10 +-123.4099999999998 + 20 +-48.50019365334446 + 0 +LWPOLYLINE + 5 +1C8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-123.4099999999998 + 20 +50.49980634665553 + 10 +-118.9199999999982 + 20 +50.49980634665553 + 10 +-118.9199999999982 + 20 +42.49980634665553 + 10 +-123.4099999999998 + 20 +42.49980634665553 + 0 +CIRCLE + 5 +1C9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-114.9199999999982 + 20 +46.49980634665553 + 40 +4 + 0 +CIRCLE + 5 +1CA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-114.9199999999982 + 20 +0.9998063466555323 + 40 +4 + 0 +LWPOLYLINE + 5 +1CB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-123.4099999999998 + 20 +4.999806346655532 + 10 +-118.9199999999982 + 20 +4.999806346655532 + 10 +-118.9199999999982 + 20 +-3.000193653344467 + 10 +-123.4099999999998 + 20 +-3.000193653344467 + 0 +LWPOLYLINE + 5 +1CC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-123.4099999999998 + 20 +96.00000301768524 + 10 +-118.9199999999982 + 20 +96.00000301768524 + 10 +-118.9199999999982 + 20 +88.00000301768523 + 10 +-123.4099999999998 + 20 +88.00000301768523 + 0 +CIRCLE + 5 +1CD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-114.9199999999982 + 20 +92.00000301768524 + 40 +4 + 0 +CIRCLE + 5 +1CE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.95999999999913 + 20 +-90.00000342004387 + 40 +4 + 0 +ARC + 5 +1CF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-126.4069911709302 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +299.9668284538085 + 51 +60.00000415932957 + 0 +ARC + 5 +1D0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-126.4130088290803 + 20 +106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +119.9999958406704 + 51 +166.7519628908427 + 0 +ARC + 5 +1D1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.96300882907235 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +199.4712435580585 + 51 +240.0000041593296 + 0 +ARC + 5 +1D2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.9569911709259 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +299.9999958406704 + 51 +314.3822367755017 + 0 +ARC + 5 +1D3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-68.9569911709259 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +332.7015001009663 + 51 +359.9999745452056 + 0 +ARC + 5 +1D4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-126.4069911709302 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +299.9999958406704 + 51 +60.03317154619149 + 0 +ARC + 5 +1D5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-126.4130088290803 + 20 +-106.0000007544204 + 40 +6 +100 +AcDbArc + 50 +174.0218129683411 + 51 +240.0000041593296 + 0 +LWPOLYLINE + 5 +1D6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +49.68250322376843 + 20 +118.9291229950613 + 10 +63.66581235499324 + 20 +108.7233091312282 + 10 +68.25418764500864 + 20 +115.2766908687736 + 10 +54.27087851378018 + 20 +125.4825047326067 + 0 +INSERT + 5 +1D7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +103.3750030176852 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1D8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +80.62490468217038 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1D9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +57.87480634665553 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +35.12470801114068 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +12.37480634665553 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-10.37529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-33.12519365334447 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-55.87529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1DF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-78.62500342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1E0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-101.3751017555587 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +LWPOLYLINE + 5 +1E1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +76.62490468217038 + 10 +-133.9000000000014 + 20 +76.62490468217038 + 10 +-133.9000000000014 + 20 +84.6249046821704 + 10 +-129.4100000000035 + 20 +84.6249046821704 + 0 +CIRCLE + 5 +1E2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +80.62490468217038 + 40 +4 + 0 +LWPOLYLINE + 5 +1E3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +99.37500301768523 + 10 +-133.9000000000014 + 20 +99.37500301768523 + 10 +-133.9000000000014 + 20 +107.3750030176852 + 10 +-129.4100000000035 + 20 +107.3750030176852 + 0 +CIRCLE + 5 +1E4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +103.3750030176852 + 40 +4 + 0 +LWPOLYLINE + 5 +1E5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +53.87480634665553 + 10 +-133.9000000000014 + 20 +53.87480634665553 + 10 +-133.9000000000014 + 20 +61.87480634665553 + 10 +-129.4100000000035 + 20 +61.87480634665553 + 0 +CIRCLE + 5 +1E6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +57.87480634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +1E7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +31.12470801114068 + 10 +-133.9000000000014 + 20 +31.12470801114068 + 10 +-133.9000000000014 + 20 +39.12470801114068 + 10 +-129.4100000000035 + 20 +39.12470801114068 + 0 +CIRCLE + 5 +1E8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +35.12470801114068 + 40 +4 + 0 +LWPOLYLINE + 5 +1E9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +8.374806346655532 + 10 +-133.9000000000014 + 20 +8.374806346655532 + 10 +-133.9000000000014 + 20 +16.37480634665553 + 10 +-129.4100000000035 + 20 +16.37480634665553 + 0 +CIRCLE + 5 +1EA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +12.37480634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +1EB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +-14.37529198885932 + 10 +-133.9000000000014 + 20 +-14.37529198885932 + 10 +-133.9000000000014 + 20 +-6.375291988859316 + 10 +-129.4100000000035 + 20 +-6.375291988859316 + 0 +CIRCLE + 5 +1EC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +-10.37529198885931 + 40 +4 + 0 +LWPOLYLINE + 5 +1ED +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +-37.12519365334447 + 10 +-133.9000000000014 + 20 +-37.12519365334447 + 10 +-133.9000000000014 + 20 +-29.12519365334447 + 10 +-129.4100000000035 + 20 +-29.12519365334447 + 0 +CIRCLE + 5 +1EE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +-33.12519365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +1EF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +-59.87529198885932 + 10 +-133.9000000000014 + 20 +-59.87529198885932 + 10 +-133.9000000000014 + 20 +-51.87529198885932 + 10 +-129.4100000000035 + 20 +-51.87529198885932 + 0 +CIRCLE + 5 +1F0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +-55.87529198885931 + 40 +4 + 0 +LWPOLYLINE + 5 +1F1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +-105.3751017555587 + 10 +-133.9000000000014 + 20 +-105.3751017555587 + 10 +-133.9000000000014 + 20 +-97.37510175555872 + 10 +-129.4100000000035 + 20 +-97.37510175555872 + 0 +CIRCLE + 5 +1F2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +-101.3751017555587 + 40 +4 + 0 +LWPOLYLINE + 5 +1F3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +-129.4100000000035 + 20 +-82.62500342004385 + 10 +-133.9000000000014 + 20 +-82.62500342004385 + 10 +-133.9000000000014 + 20 +-74.62500342004385 + 10 +-129.4100000000035 + 20 +-74.62500342004385 + 0 +CIRCLE + 5 +1F4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-137.9000000000014 + 20 +-78.62500342004387 + 40 +4 + 0 +INSERT + 5 +1F5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +103.3750030176852 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1F6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +80.62490468217038 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1F7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +57.87480634665553 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1F8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +35.12470801114068 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1F9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +12.37480634665553 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1FA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-10.37529198885931 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1FB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-33.12519365334447 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1FC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-55.87529198885931 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1FD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000051 + 20 +-78.62500342004387 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +1FE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000051 + 20 +-101.3751017555587 + 30 +0 + 41 +-1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +LWPOLYLINE + 5 +1FF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +76.62490468217038 + 10 +133.9000000000051 + 20 +76.62490468217038 + 10 +133.9000000000051 + 20 +84.6249046821704 + 10 +129.4100000000035 + 20 +84.6249046821704 + 0 +CIRCLE + 5 +200 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +80.62490468217038 + 40 +4 + 0 +LWPOLYLINE + 5 +201 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +99.37500301768523 + 10 +133.9000000000051 + 20 +99.37500301768523 + 10 +133.9000000000051 + 20 +107.3750030176852 + 10 +129.4100000000035 + 20 +107.3750030176852 + 0 +CIRCLE + 5 +202 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +103.3750030176852 + 40 +4 + 0 +LWPOLYLINE + 5 +203 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +53.87480634665553 + 10 +133.9000000000051 + 20 +53.87480634665553 + 10 +133.9000000000051 + 20 +61.87480634665553 + 10 +129.4100000000035 + 20 +61.87480634665553 + 0 +CIRCLE + 5 +204 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +57.87480634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +205 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +31.12470801114068 + 10 +133.9000000000051 + 20 +31.12470801114068 + 10 +133.9000000000051 + 20 +39.12470801114068 + 10 +129.4100000000035 + 20 +39.12470801114068 + 0 +CIRCLE + 5 +206 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +35.12470801114068 + 40 +4 + 0 +LWPOLYLINE + 5 +207 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +8.374806346655532 + 10 +133.9000000000051 + 20 +8.374806346655532 + 10 +133.9000000000051 + 20 +16.37480634665553 + 10 +129.4100000000035 + 20 +16.37480634665553 + 0 +CIRCLE + 5 +208 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +12.37480634665553 + 40 +4 + 0 +LWPOLYLINE + 5 +209 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +-14.37529198885932 + 10 +133.9000000000051 + 20 +-14.37529198885932 + 10 +133.9000000000051 + 20 +-6.375291988859316 + 10 +129.4100000000035 + 20 +-6.375291988859316 + 0 +CIRCLE + 5 +20A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +-10.37529198885931 + 40 +4 + 0 +LWPOLYLINE + 5 +20B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +-37.12519365334447 + 10 +133.9000000000051 + 20 +-37.12519365334447 + 10 +133.9000000000051 + 20 +-29.12519365334447 + 10 +129.4100000000035 + 20 +-29.12519365334447 + 0 +CIRCLE + 5 +20C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +-33.12519365334447 + 40 +4 + 0 +LWPOLYLINE + 5 +20D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +-59.87529198885932 + 10 +133.9000000000051 + 20 +-59.87529198885932 + 10 +133.9000000000051 + 20 +-51.87529198885932 + 10 +129.4100000000035 + 20 +-51.87529198885932 + 0 +CIRCLE + 5 +20E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +-55.87529198885931 + 40 +4 + 0 +LWPOLYLINE + 5 +20F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +-105.3751017555587 + 10 +133.9000000000051 + 20 +-105.3751017555587 + 10 +133.9000000000051 + 20 +-97.37510175555872 + 10 +129.4100000000035 + 20 +-97.37510175555872 + 0 +CIRCLE + 5 +210 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +-101.3751017555587 + 40 +4 + 0 +LWPOLYLINE + 5 +211 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 0 + 43 +0 + 10 +129.4100000000035 + 20 +-82.62500342004385 + 10 +133.9000000000051 + 20 +-82.62500342004385 + 10 +133.9000000000051 + 20 +-74.62500342004385 + 10 +129.4100000000035 + 20 +-74.62500342004385 + 0 +CIRCLE + 5 +212 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +137.9000000000014 + 20 +-78.62500342004387 + 40 +4 + 0 +ENDBLK + 5 +76 +330 +74 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +78 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +(22-14-16X) pálená + 70 + 0 + 10 +0 + 20 +0 + 3 +(22-14-16X) pálená + 1 + + 0 +INSERT + 5 +213 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +103.3750030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +214 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +80.62490468216855 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +215 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +57.87480634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +216 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-114.9199999999982 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +217 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-114.9199999999982 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +218 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +35.12470801114068 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +219 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +12.37480634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-10.37529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-33.12519365334629 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-55.87529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-78.62500342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +-67.99999698231657 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +21F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-114.9199999999982 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +220 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-68.96000000000276 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +221 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +-67.99999698231657 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +222 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +-21.99999698231659 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +223 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-114.9199999999982 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +224 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +24.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +225 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-68.96000000000276 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +226 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +-21.99999698231659 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +227 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-23 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +228 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +-67.99999698231657 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +229 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-137.9000000000014 + 20 +-101.3751017555587 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-114.9199999999982 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +-102.0000034200438 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-68.95999999999913 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +-102.0000034200438 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-23 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +22F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +-102.0000034200438 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +230 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-101.3751017555587 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +231 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +114.9199999999982 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +232 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +-102.0000034200438 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +233 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +68.95999999999913 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +234 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +-102.0000034200438 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +235 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +23 + 20 +-90.00000342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +236 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +-67.99999698231657 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +237 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +-67.99999698231657 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +238 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-78.62500342004387 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +239 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-55.87529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-33.12519365334629 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +114.9199999999982 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +68.96000000000276 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +23 + 20 +-44.50019365334628 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +-21.99999698231659 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +23F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +-21.99999698231659 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +240 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +-21.99999698231659 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +241 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-23 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +242 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +23 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +243 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +68.96000000000276 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +244 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +24.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +245 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +24.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +246 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +24.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +247 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +24.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +248 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +12.37480634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +249 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +-10.37529198885931 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +114.9199999999982 + 20 +0.9998063466537132 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +35.12470801114068 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +114.9199999999982 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +57.87480634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +103.3750030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +24F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +137.9000000000014 + 20 +80.62490468216855 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +250 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +114.9199999999982 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +251 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +104.0000030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +252 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +91.94000000000233 + 20 +70.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +253 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +68.96000000000276 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +254 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +68.96000000000276 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +255 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +70.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +256 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +45.9800000000032 + 20 +104.0000030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +257 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +23 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +258 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +23 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +259 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-23 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-23 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +104.0000030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +0 + 20 +70.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +104.0000030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-45.9800000000032 + 20 +70.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +25F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-68.96000000000276 + 20 +46.49980634665371 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +260 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-68.96000000000276 + 20 +92.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +261 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +104.0000030176834 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +262 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C3A410068 + 10 +-91.94000000000233 + 20 +70.00000301768341 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +263 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +-143.4165589395707 + 20 +124.5000015088408 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +264 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +-82.29999999999927 + 20 +124.5000015088408 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +265 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +-16.80000000000291 + 20 +124.5000015088408 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +266 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +48.69999999999709 + 20 +124.5000015088408 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +267 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +114.1999999999971 + 20 +124.5000015088408 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +268 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +143.2028837674952 + 20 +-123.5000017100228 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +269 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +81.4499999999971 + 20 +-123.5000017100228 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +26A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +15.94999999999709 + 20 +-123.5000017100228 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +26B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +-49.55000000000291 + 20 +-123.5000017100228 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +INSERT + 5 +26C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbBlockReference + 2 +A$C75D90C8F + 10 +-115.0499999999992 + 20 +-123.5000017100228 + 30 +0 + 41 +1 + 42 +1 + 43 +0 + 50 +0 + 70 + 1 + 71 + 1 + 44 +0 + 45 +0 + 0 +ENDBLK + 5 +79 +330 +77 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7B +330 +7A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_POZOR !PÃLENÉ ROZMÄšRY + 70 + 0 + 10 +0 + 20 +0 + 3 +_POZOR !PÃLENÉ ROZMÄšRY + 1 + + 0 +ENDBLK + 5 +7C +330 +7A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7E +330 +7D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C2EFF5608 + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C2EFF5608 + 1 + + 0 +ENDBLK + 5 +7F +330 +7D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +81 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +A$C054C61AF + 70 + 0 + 10 +0 + 20 +0 + 3 +A$C054C61AF + 1 + + 0 +LWPOLYLINE + 5 +26D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-116.6031334089257 + 20 +49.47057024059358 + 10 +-116.6031334089257 + 20 +83.32657024059336 + 42 +-0.414213562373095 + 10 +-114.6031334089257 + 20 +85.32657024059336 + 10 +-102.5143334089257 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +-100.5143334089257 + 20 +83.32657024059336 + 10 +-100.5143334089257 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +-102.5143334089257 + 20 +47.47057024059358 + 10 +-114.6031334089257 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +26E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 169 + 70 + 1 + 43 +0 + 10 +-149.8028454088767 + 20 +-84.38103585207135 + 42 +-0.4142135623730929 + 10 +-147.8028454088767 + 20 +-82.38103585207138 + 10 +-146.0040845711564 + 20 +-82.38103585207136 + 42 +-0.1848444519348464 + 10 +-144.6686688393965 + 20 +-82.89218904216614 + 10 +-143.1382611407875 + 20 +-84.26488266190427 + 42 +0.6487279186053531 + 10 +-139.8028454090549 + 20 +-82.77603585207908 + 10 +-139.8028454090549 + 20 +-65.98603585206365 + 42 +0.6487279186055391 + 10 +-143.1382611406684 + 20 +-64.49718904212934 + 10 +-144.6686688393947 + 20 +-65.86988266197659 + 42 +-0.1848444519348816 + 10 +-146.0040845711555 + 20 +-66.38103585206954 + 10 +-147.8028454089499 + 20 +-66.38103585207136 + 42 +-0.4142135623725622 + 10 +-149.8028454089499 + 20 +-64.38103585207136 + 10 +-149.8028454089276 + 20 +-46.45081484393631 + 42 +-0.2679491924308204 + 10 +-148.3028454089276 + 20 +-43.85273863258773 + 42 +0.5773502691897093 + 10 +-148.3028454089276 + 20 +-38.65658620987958 + 42 +-0.2679491924309886 + 10 +-149.8028454089271 + 20 +-36.05850999852737 + 10 +-149.8028454089271 + 20 +-24.92016831157525 + 42 +-0.2679491924310725 + 10 +-148.3028454089276 + 20 +-22.32209210022304 + 42 +0.5773502691897108 + 10 +-148.3028454089276 + 20 +-17.12593967751488 + 42 +-0.2679491924310724 + 10 +-149.8028454089271 + 20 +-14.52786346616267 + 10 +-149.8028454089276 + 20 +-3.389568311573385 + 42 +-0.2679491924309796 + 10 +-148.3028454089276 + 20 +-0.7914921002229891 + 42 +0.5773502691897102 + 10 +-148.3028454089276 + 20 +4.404660322485161 + 42 +-0.267949192430991 + 10 +-149.8028454089271 + 20 +7.002736533837377 + 10 +-149.8028454089271 + 20 +18.14093862369373 + 42 +-0.267949192430993 + 10 +-148.3028454089276 + 20 +20.73901483504597 + 42 +0.5773502691897088 + 10 +-148.3028454089276 + 20 +25.9351672577541 + 42 +-0.2679491924309075 + 10 +-149.8028454089271 + 20 +28.53324346910449 + 10 +-149.8028454088767 + 20 +39.11896414792864 + 42 +-0.414213562373095 + 10 +-147.8028454088767 + 20 +41.11896414792864 + 10 +-146.0040845711564 + 20 +41.11896414792864 + 42 +-0.1848444519348464 + 10 +-144.6686688393965 + 20 +40.60781095783386 + 10 +-143.1382611407875 + 20 +39.23511733809574 + 42 +0.6487279186053454 + 10 +-139.8028454090549 + 20 +40.72396414792092 + 10 +-139.8028454090549 + 20 +57.51396414793635 + 42 +0.648727918605536 + 10 +-143.1382611406684 + 20 +59.00281095787066 + 10 +-144.6686688393947 + 20 +57.6301173380234 + 42 +-0.1848444519348832 + 10 +-146.0040845711555 + 20 +57.11896414793046 + 10 +-147.8028454089499 + 20 +57.11896414792864 + 42 +-0.4142135623725612 + 10 +-149.8028454089499 + 20 +59.11896414792863 + 10 +-149.8028454089271 + 20 +107.8793673846594 + 42 +-0.4142135623730964 + 10 +-146.8028454089271 + 20 +110.8793673846576 + 10 +-132.1810118373951 + 20 +110.8793673846576 + 42 +-0.2679491924311148 + 10 +-129.5829356260419 + 20 +109.3793673846576 + 10 +-123.1189236610698 + 20 +98.18337024059474 + 42 +0.2679491924311174 + 10 +-120.5208474497167 + 20 +96.68337024059474 + 10 +-96.84268336814149 + 20 +96.68337024059475 + 42 +0.2679491924310948 + 10 +-94.24460715678833 + 20 +98.18337024059473 + 10 +-87.78059519181443 + 20 +109.3793673846576 + 42 +-0.2679491924310743 + 10 +-85.18251898046174 + 20 +110.8793673846576 + 10 +-70.19181183739238 + 20 +110.8793673846576 + 42 +-0.2679491924311554 + 10 +-67.59373562603878 + 20 +109.3793673846576 + 10 +-61.12972366106987 + 20 +98.18337024059474 + 42 +0.2679491924311362 + 10 +-58.53164744971627 + 20 +96.68337024059474 + 10 +-34.8534833681415 + 20 +96.68337024059474 + 42 +0.2679491924310957 + 10 +-32.25540715678834 + 20 +98.18337024059474 + 10 +-25.79139519181399 + 20 +109.3793673846576 + 42 +-0.2679491924310536 + 10 +-23.1933189804613 + 20 +110.8793673846576 + 10 +-8.202611837395123 + 20 +110.8793673846576 + 42 +-0.267949192431114 + 10 +-5.604535626041987 + 20 +109.3793673846576 + 10 +0.859476338930099 + 20 +98.18337024059474 + 42 +0.2679491924311164 + 10 +3.457552550283248 + 20 +96.68337024059474 + 10 +27.13571663186304 + 20 +96.68337024059474 + 42 +0.2679491924311554 + 10 +29.73379284321664 + 20 +98.18337024059474 + 10 +36.19780480818417 + 20 +109.3793673846576 + 42 +-0.2679491924311961 + 10 +38.79588101953823 + 20 +110.8793673846576 + 10 +53.78658816260486 + 20 +110.8793673846576 + 42 +-0.2679491924311149 + 10 +56.384664373958 + 20 +109.3793673846576 + 10 +62.84867633893008 + 20 +98.18337024059474 + 42 +0.2679491924311164 + 10 +65.44675255028324 + 20 +96.68337024059474 + 10 +89.12491663185983 + 20 +96.68337024059474 + 42 +0.267949192431116 + 10 +91.72299284321298 + 20 +98.18337024059474 + 10 +98.18700480818234 + 20 +109.3793673846539 + 42 +-0.2679491924310344 + 10 +100.7850810195346 + 20 +110.8793673846539 + 10 +115.7797559261862 + 20 +110.8793673846576 + 42 +-0.267417379145724 + 10 +118.3748494939727 + 20 +109.3845216539739 + 10 +124.8745067899353 + 20 +98.17821597128022 + 42 +0.2674173791456816 + 10 +127.4696003577205 + 20 +96.68337024059474 + 10 +147.2059545910724 + 20 +96.68337024059474 + 42 +-0.414213562373095 + 10 +150.2059545910724 + 20 +93.68337024059474 + 10 +150.2059545910724 + 20 +71.59462959856864 + 42 +-0.2679491924309934 + 10 +148.7059545910724 + 20 +68.99655338721821 + 42 +0.5773502691896997 + 10 +148.7059545910729 + 20 +63.80040096450833 + 42 +-0.2679491924308224 + 10 +150.2059545910724 + 20 +61.2023247531597 + 10 +150.2059545910952 + 20 +44.93337024058928 + 42 +-0.4142135623725602 + 10 +148.2059545910952 + 20 +42.93337024059293 + 10 +146.4071937533008 + 20 +42.93337024059474 + 42 +-0.1848444519349634 + 10 +145.07177802154 + 20 +43.44452343068952 + 10 +143.5413703228137 + 20 +44.81721705053494 + 42 +0.648727918605535 + 10 +140.2059545912007 + 20 +43.32837024060063 + 10 +140.2059545912002 + 20 +26.53837024058521 + 42 +0.6487279186053531 + 10 +143.5413703229328 + 20 +25.04952343076001 + 10 +145.0717780215418 + 20 +26.42221705049815 + 42 +-0.1848444519348308 + 10 +146.4071937533017 + 20 +26.93337024059292 + 10 +148.2059545910219 + 20 +26.93337024059292 + 42 +-0.414213562373095 + 10 +150.2059545910219 + 20 +24.93337024059292 + 10 +150.2059545910747 + 20 +7.002736533850111 + 42 +-0.267949192432042 + 10 +148.7059545910738 + 20 +4.40466032248694 + 42 +0.5773502691897947 + 10 +148.7059545910729 + 20 +-0.7914921002211575 + 42 +-0.2679491924310725 + 10 +150.205954591072 + 20 +-3.389568311573385 + 10 +150.205954591072 + 20 +-14.52786346615903 + 42 +-0.2679491924312185 + 10 +148.7059545910724 + 20 +-17.12593967751495 + 42 +0.5773502691896848 + 10 +148.7059545910738 + 20 +-22.32209210021934 + 42 +-0.2679491924309948 + 10 +150.2059545910733 + 20 +-24.92016831157343 + 10 +150.2059545910724 + 20 +-36.05846346616272 + 42 +-0.2679491924314384 + 10 +148.7059545910697 + 20 +-38.6565396775168 + 42 +0.5773502691905198 + 10 +148.7059545910697 + 20 +-43.85269210022849 + 42 +-0.2679491924314403 + 10 +150.205954591072 + 20 +-46.45076831158258 + 10 +150.2059545910729 + 20 +-57.58915653088843 + 42 +-0.2679491924313894 + 10 +148.705954591072 + 20 +-60.18723274224431 + 42 +0.5773502691898825 + 10 +148.705954591072 + 20 +-65.38338516495241 + 42 +-0.2679491924307045 + 10 +150.2059545910729 + 20 +-67.98146137630101 + 10 +150.2059545910952 + 20 +-78.56662975941072 + 42 +-0.4142135623725622 + 10 +148.2059545910952 + 20 +-80.56662975940708 + 10 +146.4071937533008 + 20 +-80.56662975940526 + 42 +-0.1848444519349629 + 10 +145.07177802154 + 20 +-80.05547656931046 + 10 +143.5413703228137 + 20 +-78.68278294946504 + 42 +0.6487279186055376 + 10 +140.2059545912007 + 20 +-80.17162975939937 + 10 +140.2059545912002 + 20 +-96.96162975941479 + 42 +0.6487279186053531 + 10 +143.5413703229328 + 20 +-98.45047656923998 + 10 +145.0717780215418 + 20 +-97.07778294950187 + 42 +-0.1848444519348313 + 10 +146.4071937533017 + 20 +-96.56662975940708 + 10 +148.2059545910219 + 20 +-96.56662975940709 + 42 +-0.4142135623730929 + 10 +150.2059545910219 + 20 +-98.56662975940706 + 10 +150.2059545910815 + 20 +-147.3270326153379 + 42 +-0.4142135623734113 + 10 +147.205954591082 + 20 +-150.3270326153415 + 10 +132.7269942342764 + 20 +-150.3270326153433 + 42 +-0.2494983946465689 + 10 +130.2388056069399 + 20 +-149.0030151196661 + 10 +122.4603833130336 + 20 +-137.4550533477486 + 42 +0.2494983946465675 + 10 +119.9721946856971 + 20 +-136.1310358520713 + 10 +96.58867449644596 + 20 +-136.1310358520713 + 42 +0.2494983946465435 + 10 +94.10048586910941 + 20 +-137.4550533477486 + 10 +86.32206357520364 + 20 +-149.0030151196661 + 42 +-0.2494983946465649 + 10 +83.83387494786712 + 20 +-150.3270326153433 + 10 +70.73779423427595 + 20 +-150.3270326153433 + 42 +-0.2494983946465399 + 10 +68.24960560693944 + 20 +-149.0030151196661 + 10 +60.47118331303364 + 20 +-137.4550533477486 + 42 +0.2494983946465645 + 10 +57.98299468569712 + 20 +-136.1310358520713 + 10 +34.59947449644551 + 20 +-136.1310358520713 + 42 +0.2494983946465397 + 10 +32.111285869109 + 20 +-137.4550533477486 + 10 +24.33286357520367 + 20 +-149.0030151196661 + 42 +-0.2494983946465661 + 10 +21.84467494786713 + 20 +-150.3270326153433 + 10 +8.748594234275966 + 20 +-150.3270326153433 + 42 +-0.2494983946465399 + 10 +6.260405606939452 + 20 +-149.0030151196661 + 10 +-1.518016686966326 + 20 +-137.4550533477486 + 42 +0.2494983946465655 + 10 +-4.00620531430286 + 20 +-136.1310358520713 + 10 +-27.38972550355447 + 20 +-136.1310358520713 + 42 +0.2494983946465395 + 10 +-29.87791413089098 + 20 +-137.4550533477486 + 10 +-37.65633642479632 + 20 +-149.0030151196661 + 42 +-0.2494983946465663 + 10 +-40.14452505213284 + 20 +-150.3270326153433 + 10 +-53.24060576572401 + 20 +-150.3270326153433 + 42 +-0.2494983946465411 + 10 +-55.72879439306054 + 20 +-149.0030151196661 + 10 +-63.50721668696632 + 20 +-137.4550533477486 + 42 +0.2494983946465645 + 10 +-65.99540531430284 + 20 +-136.1310358520713 + 10 +-89.37892550355446 + 20 +-136.1310358520713 + 42 +0.2494983946465397 + 10 +-91.86711413089097 + 20 +-137.4550533477486 + 10 +-99.64553642479629 + 20 +-149.0030151196661 + 42 +-0.2494983946465663 + 10 +-102.1337250521328 + 20 +-150.3270326153433 + 10 +-115.229805765724 + 20 +-150.3270326153433 + 42 +-0.2494983946465466 + 10 +-117.7179943930605 + 20 +-149.0030151196661 + 10 +-125.4964166869663 + 20 +-137.4550533477486 + 42 +0.2494983946465439 + 10 +-127.9846053143024 + 20 +-136.1310358520713 + 10 +-146.8022140195117 + 20 +-136.1310358520713 + 42 +-0.4149097411852242 + 10 +-149.8022055491851 + 20 +-133.1239069048879 + 10 +-149.8026444036718 + 20 +-111.0424813384798 + 42 +-0.2679491924308265 + 10 +-148.302696039103 + 20 +-108.4443753160831 + 42 +0.5773499140667988 + 10 +-148.3027965414349 + 20 +-103.2482244924031 + 42 +-0.2679542322950039 + 10 +-149.8028454089271 + 20 +-100.6501200680031 + 10 +-149.8028454089271 + 20 +-84.31581893519979 + 0 +CIRCLE + 5 +26F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911372 + 20 +34.93337024059292 + 40 +4 + 0 +CIRCLE + 5 +270 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911344 + 20 +54.33400024059301 + 40 +4 + 0 +CIRCLE + 5 +271 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911344 + 20 +15.53274024059283 + 40 +4 + 0 +CIRCLE + 5 +272 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089919 + 20 +-74.38103585207136 + 40 +4 + 0 +CIRCLE + 5 +273 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089892 + 20 +-54.98040585207127 + 40 +4 + 0 +CIRCLE + 5 +274 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089892 + 20 +-93.78166585207146 + 40 +4 + 0 +CIRCLE + 5 +275 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911367 + 20 +-84.67379585207527 + 40 +4 + 0 +CIRCLE + 5 +276 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911367 + 20 +-70.123795852076 + 40 +4 + 0 +CIRCLE + 5 +277 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +128.6060985911367 + 20 +-99.22379585207455 + 40 +4 + 0 +CIRCLE + 5 +278 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089914 + 20 +45.22613024059682 + 40 +4 + 0 +CIRCLE + 5 +279 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089914 + 20 +30.67613024059756 + 40 +4 + 0 +CIRCLE + 5 +27A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-128.2029894089914 + 20 +59.77613024059611 + 40 +4 + 0 +LWPOLYLINE + 5 +27B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-137.7362454089279 + 20 +72.32613024059172 + 42 +0.414213562373095 + 10 +-135.7362454089279 + 20 +70.32613024059172 + 10 +-124.8777654089272 + 20 +70.32613024059172 + 42 +0.414213562373095 + 10 +-122.8777654089272 + 20 +72.32613024059172 + 10 +-122.8777654089272 + 20 +83.18461024059251 + 42 +0.414213562373095 + 10 +-124.8777654089272 + 20 +85.18461024059252 + 10 +-135.7362454089279 + 20 +85.18461024059252 + 42 +0.4142135623730971 + 10 +-137.7362454089279 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +27C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-116.6031334089257 + 20 +6.409184111131253 + 10 +-116.6031334089257 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +-114.6031334089257 + 20 +42.26518411113102 + 10 +-102.5143334089257 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +-100.5143334089257 + 20 +40.26518411113102 + 10 +-100.5143334089257 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +-102.5143334089257 + 20 +4.409184111131253 + 10 +-114.6031334089257 + 20 +4.409184111131253 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +27D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-116.5450116976767 + 20 +-36.65201588886885 + 10 +-116.5450116976767 + 20 +-2.796015888869078 + 42 +-0.414213562373095 + 10 +-114.5450116976767 + 20 +-0.796015888869078 + 10 +-102.4562116976767 + 20 +-0.796015888869078 + 42 +-0.414213562373095 + 10 +-100.4562116976767 + 20 +-2.796015888869078 + 10 +-100.4562116976767 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +-102.4562116976767 + 20 +-38.65201588886885 + 10 +-114.5450116976767 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +27E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-116.6031334089257 + 20 +-79.71321588886894 + 10 +-116.6031334089257 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +-114.6031334089257 + 20 +-43.85721588886918 + 10 +-102.5143334089257 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +-100.5143334089257 + 20 +-45.85721588886918 + 10 +-100.5143334089257 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +-102.5143334089257 + 20 +-81.71321588886894 + 10 +-114.6031334089257 + 20 +-81.71321588886894 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +27F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-116.6031334089257 + 20 +-122.7742358520718 + 10 +-116.6031334089257 + 20 +-88.91823585207204 + 42 +-0.414213562373095 + 10 +-114.6031334089257 + 20 +-86.91823585207202 + 10 +-102.5143334089257 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +-100.5143334089257 + 20 +-88.91823585207204 + 10 +-100.5143334089257 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +-102.5143334089257 + 20 +-124.7742358520718 + 10 +-114.6031334089257 + 20 +-124.7742358520718 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +280 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.85486140892588 + 20 +-101.9534297594073 + 10 +-94.85486140892588 + 20 +-68.09742975940753 + 42 +-0.4142135623730971 + 10 +-92.8548614089259 + 20 +-66.09742975940753 + 10 +-80.76606140892591 + 20 +-66.09742975940753 + 42 +-0.414213562373095 + 10 +-78.76606140892591 + 20 +-68.09742975940753 + 10 +-78.76606140892591 + 20 +-101.9534297594073 + 42 +-0.414213562373095 + 10 +-80.76606140892591 + 20 +-103.9534297594073 + 10 +-92.8548614089259 + 20 +-103.9534297594073 + 42 +-0.4142135623730971 + 0 +LWPOLYLINE + 5 +281 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.85486140892588 + 20 +-58.41902975940683 + 10 +-94.85486140892588 + 20 +-24.56302975940707 + 42 +-0.4142135623730966 + 10 +-92.8548614089259 + 20 +-22.56302975940707 + 10 +-80.76606140892591 + 20 +-22.56302975940707 + 42 +-0.414213562373095 + 10 +-78.76606140892591 + 20 +-24.56302975940707 + 10 +-78.76606140892591 + 20 +-58.41902975940683 + 42 +-0.4142135623730961 + 10 +-80.76606140892591 + 20 +-60.41902975940684 + 10 +-92.8548614089259 + 20 +-60.41902975940684 + 42 +-0.4142135623730981 + 0 +LWPOLYLINE + 5 +282 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.85486140892588 + 20 +-14.88462975940638 + 10 +-94.85486140892588 + 20 +18.97137024059339 + 42 +-0.4142135623730966 + 10 +-92.8548614089259 + 20 +20.97137024059339 + 10 +-80.76606140892591 + 20 +20.97137024059339 + 42 +-0.414213562373095 + 10 +-78.76606140892591 + 20 +18.97137024059339 + 10 +-78.76606140892591 + 20 +-14.88462975940638 + 42 +-0.414213562373095 + 10 +-80.76606140892591 + 20 +-16.88462975940638 + 10 +-92.8548614089259 + 20 +-16.88462975940638 + 42 +-0.4142135623730971 + 0 +LWPOLYLINE + 5 +283 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.85486140892588 + 20 +28.64977024059226 + 10 +-94.85486140892588 + 20 +62.50577024059203 + 42 +-0.4142135623730971 + 10 +-92.8548614089259 + 20 +64.50577024059203 + 10 +-80.76606140892591 + 20 +64.50577024059203 + 42 +-0.414213562373095 + 10 +-78.76606140892591 + 20 +62.50577024059203 + 10 +-78.76606140892591 + 20 +28.64977024059226 + 42 +-0.414213562373095 + 10 +-80.76606140892591 + 20 +26.64977024059226 + 10 +-92.8548614089259 + 20 +26.64977024059226 + 42 +-0.4142135623730966 + 0 +LWPOLYLINE + 5 +284 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-137.7362454089279 + 20 +7.142551046399603 + 42 +0.414213562373095 + 10 +-135.7362454089279 + 20 +5.142551046399603 + 10 +-124.8777654089272 + 20 +5.142551046399603 + 42 +0.414213562373095 + 10 +-122.8777654089272 + 20 +7.142551046399603 + 10 +-122.8777654089272 + 20 +18.00103104640038 + 42 +0.4142135623730955 + 10 +-124.8777654089272 + 20 +20.00103104640039 + 10 +-135.7362454089279 + 20 +20.00103104640039 + 42 +0.4142135623730955 + 10 +-137.7362454089279 + 20 +18.00103104640038 + 0 +LWPOLYLINE + 5 +285 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-137.7362454089279 + 20 +-14.38795588886932 + 42 +0.4142135623730963 + 10 +-135.7362454089279 + 20 +-16.38795588886933 + 10 +-124.8777654089272 + 20 +-16.38795588886933 + 42 +0.4142135623730963 + 10 +-122.8777654089272 + 20 +-14.38795588886932 + 10 +-122.8777654089272 + 20 +-3.529475888868546 + 42 +0.414213562373095 + 10 +-124.8777654089272 + 20 +-1.529475888868546 + 10 +-135.7362454089279 + 20 +-1.529475888868546 + 42 +0.414213562373095 + 10 +-137.7362454089279 + 20 +-3.529475888868546 + 0 +LWPOLYLINE + 5 +286 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-137.7362454089307 + 20 +-35.9186489536005 + 42 +0.414213562373095 + 10 +-135.7362454089307 + 20 +-37.9186489536005 + 10 +-124.8777654089299 + 20 +-37.9186489536005 + 42 +0.414213562373095 + 10 +-122.8777654089299 + 20 +-35.9186489536005 + 10 +-122.8777654089299 + 20 +-25.06016895359972 + 42 +0.414213562373095 + 10 +-124.8777654089299 + 20 +-23.06016895359972 + 10 +-135.7362454089307 + 20 +-23.06016895359972 + 42 +0.414213562373095 + 10 +-137.7362454089307 + 20 +-25.06016895359972 + 0 +LWPOLYLINE + 5 +287 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-137.7362454089279 + 20 +-122.0408689168034 + 42 +0.414213562373095 + 10 +-135.7362454089279 + 20 +-124.0408689168034 + 10 +-124.8777654089272 + 20 +-124.0408689168034 + 42 +0.414213562373095 + 10 +-122.8777654089272 + 20 +-122.0408689168034 + 10 +-122.8777654089272 + 20 +-111.1823889168026 + 42 +0.414213562373095 + 10 +-124.8777654089272 + 20 +-109.1823889168026 + 10 +-135.7362454089279 + 20 +-109.1823889168026 + 42 +0.414213562373095 + 10 +-137.7362454089279 + 20 +-111.1823889168026 + 0 +LWPOLYLINE + 5 +288 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.23970140892834 + 20 +-122.6322758520746 + 42 +0.414213562373095 + 10 +-92.23970140892834 + 20 +-124.6322758520746 + 10 +-81.38122140892756 + 20 +-124.6322758520746 + 42 +0.414213562373095 + 10 +-79.38122140892756 + 20 +-122.6322758520746 + 10 +-79.38122140892756 + 20 +-111.7737958520738 + 42 +0.414213562373095 + 10 +-81.38122140892756 + 20 +-109.7737958520738 + 10 +-92.23970140892834 + 20 +-109.7737958520738 + 42 +0.414213562373095 + 10 +-94.23970140892834 + 20 +-111.7737958520738 + 0 +LWPOLYLINE + 5 +289 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-94.23970140892834 + 20 +72.32613024059172 + 42 +0.414213562373095 + 10 +-92.23970140892834 + 20 +70.32613024059172 + 10 +-81.38122140892756 + 20 +70.32613024059172 + 42 +0.414213562373095 + 10 +-79.38122140892756 + 20 +72.32613024059172 + 10 +-79.38122140892756 + 20 +83.18461024059251 + 42 +0.4142135623730992 + 10 +-81.38122140892756 + 20 +85.18461024059253 + 10 +-92.23970140892834 + 20 +85.18461024059252 + 42 +0.4142135623730971 + 10 +-94.23970140892834 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +28A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-73.10658940892608 + 20 +49.47057024059358 + 10 +-73.10658940892608 + 20 +83.32657024059336 + 42 +-0.414213562373095 + 10 +-71.10658940892608 + 20 +85.32657024059336 + 10 +-59.01778940892609 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +-57.01778940892609 + 20 +83.32657024059336 + 10 +-57.01778940892609 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +-59.01778940892609 + 20 +47.47057024059358 + 10 +-71.10658940892608 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +28B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-73.10658940892608 + 20 +6.409184111131253 + 10 +-73.10658940892608 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +-71.10658940892608 + 20 +42.26518411113102 + 10 +-59.01778940892609 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +-57.01778940892609 + 20 +40.26518411113102 + 10 +-57.01778940892609 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +-59.01778940892609 + 20 +4.409184111131253 + 10 +-71.10658940892608 + 20 +4.409184111131253 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +28C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-73.0484676976771 + 20 +-36.65201588886885 + 10 +-73.0484676976771 + 20 +-2.796015888869078 + 42 +-0.414213562373095 + 10 +-71.0484676976771 + 20 +-0.796015888869078 + 10 +-58.9596676976771 + 20 +-0.7960158888690778 + 42 +-0.414213562373095 + 10 +-56.95966769767711 + 20 +-2.796015888869078 + 10 +-56.95966769767711 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +-58.9596676976771 + 20 +-38.65201588886885 + 10 +-71.0484676976771 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +28D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-73.10658940892608 + 20 +-79.71321588886894 + 10 +-73.10658940892608 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +-71.10658940892608 + 20 +-43.85721588886918 + 10 +-59.01778940892609 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +-57.01778940892609 + 20 +-45.85721588886918 + 10 +-57.01778940892609 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +-59.01778940892609 + 20 +-81.71321588886894 + 10 +-71.10658940892608 + 20 +-81.71321588886894 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +28E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-73.10658940892608 + 20 +-122.7742358520718 + 10 +-73.10658940892608 + 20 +-88.91823585207204 + 42 +-0.414213562373095 + 10 +-71.10658940892608 + 20 +-86.91823585207202 + 10 +-59.01778940892609 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +-57.01778940892609 + 20 +-88.91823585207204 + 10 +-57.01778940892609 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +-59.01778940892609 + 20 +-124.7742358520718 + 10 +-71.10658940892608 + 20 +-124.7742358520718 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +28F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-29.61004540892736 + 20 +49.47057024059358 + 10 +-29.61004540892736 + 20 +83.32657024059336 + 42 +-0.4142135623730929 + 10 +-27.61004540892737 + 20 +85.32657024059336 + 10 +-15.52124540892737 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +-13.52124540892737 + 20 +83.32657024059336 + 10 +-13.52124540892737 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +-15.52124540892737 + 20 +47.47057024059358 + 10 +-27.61004540892737 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +290 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-29.61004540892736 + 20 +6.409184111131253 + 10 +-29.61004540892736 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +-27.61004540892737 + 20 +42.26518411113102 + 10 +-15.52124540892737 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +-13.52124540892737 + 20 +40.26518411113102 + 10 +-13.52124540892737 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +-15.52124540892737 + 20 +4.409184111131253 + 10 +-27.61004540892737 + 20 +4.409184111131253 + 42 +-0.4142135623730945 + 0 +LWPOLYLINE + 5 +291 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-29.55192369767838 + 20 +-36.65201588886885 + 10 +-29.55192369767838 + 20 +-2.796015888869078 + 42 +-0.414213562373095 + 10 +-27.55192369767838 + 20 +-0.796015888869078 + 10 +-15.46312369767838 + 20 +-0.796015888869078 + 42 +-0.414213562373095 + 10 +-13.46312369767838 + 20 +-2.796015888869078 + 10 +-13.46312369767838 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +-15.46312369767838 + 20 +-38.65201588886885 + 10 +-27.55192369767838 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +292 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-29.61004540892736 + 20 +-79.71321588886894 + 10 +-29.61004540892736 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +-27.61004540892737 + 20 +-43.85721588886918 + 10 +-15.52124540892737 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +-13.52124540892737 + 20 +-45.85721588886918 + 10 +-13.52124540892737 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +-15.52124540892737 + 20 +-81.71321588886894 + 10 +-27.61004540892737 + 20 +-81.71321588886894 + 42 +-0.4142135623730929 + 0 +LWPOLYLINE + 5 +293 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-29.61004540892736 + 20 +-122.7742358520718 + 10 +-29.61004540892736 + 20 +-88.91823585207204 + 42 +-0.4142135623730929 + 10 +-27.61004540892737 + 20 +-86.91823585207202 + 10 +-15.52124540892737 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +-13.52124540892737 + 20 +-88.91823585207204 + 10 +-13.52124540892737 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +-15.52124540892737 + 20 +-124.7742358520718 + 10 +-27.61004540892737 + 20 +-124.7742358520718 + 42 +-0.4142135623730929 + 0 +LWPOLYLINE + 5 +294 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +13.92435459107628 + 20 +49.47057024059358 + 10 +13.92435459107628 + 20 +83.32657024059336 + 42 +-0.414213562373095 + 10 +15.92435459107628 + 20 +85.32657024059336 + 10 +28.01315459107627 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +30.01315459107627 + 20 +83.32657024059336 + 10 +30.01315459107627 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +28.01315459107627 + 20 +47.47057024059358 + 10 +15.92435459107628 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +295 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +13.92435459107628 + 20 +6.409184111131253 + 10 +13.92435459107628 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +15.92435459107628 + 20 +42.26518411113102 + 10 +28.01315459107627 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +30.01315459107627 + 20 +40.26518411113102 + 10 +30.01315459107627 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +28.01315459107627 + 20 +4.409184111131253 + 10 +15.92435459107628 + 20 +4.409184111131253 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +296 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +13.98247630232527 + 20 +-36.65201588886885 + 10 +13.98247630232527 + 20 +-2.796015888869078 + 42 +-0.414213562373095 + 10 +15.98247630232527 + 20 +-0.796015888869078 + 10 +28.07127630232526 + 20 +-0.796015888869078 + 42 +-0.414213562373095 + 10 +30.07127630232526 + 20 +-2.796015888869078 + 10 +30.07127630232526 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +28.07127630232526 + 20 +-38.65201588886885 + 10 +15.98247630232527 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +297 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +13.92435459107628 + 20 +-79.71321588886894 + 10 +13.92435459107628 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +15.92435459107628 + 20 +-43.85721588886918 + 10 +28.01315459107627 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +30.01315459107627 + 20 +-45.85721588886918 + 10 +30.01315459107627 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +28.01315459107627 + 20 +-81.71321588886894 + 10 +15.92435459107628 + 20 +-81.71321588886894 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +298 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +13.92435459107628 + 20 +-122.7742358520718 + 10 +13.92435459107628 + 20 +-88.91823585207204 + 42 +-0.414213562373095 + 10 +15.92435459107628 + 20 +-86.91823585207202 + 10 +28.01315459107627 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +30.01315459107627 + 20 +-88.91823585207204 + 10 +30.01315459107627 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +28.01315459107627 + 20 +-124.7742358520718 + 10 +15.92435459107628 + 20 +-124.7742358520718 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +299 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +57.42089859107545 + 20 +49.47057024059358 + 10 +57.42089859107546 + 20 +83.32657024059336 + 42 +-0.4142135623730961 + 10 +59.42089859107546 + 20 +85.32657024059336 + 10 +71.50969859107545 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +73.50969859107545 + 20 +83.32657024059336 + 10 +73.50969859107545 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +71.50969859107545 + 20 +47.47057024059358 + 10 +59.42089859107546 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +29A +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +57.42089859107545 + 20 +6.409184111131253 + 10 +57.42089859107545 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +59.42089859107546 + 20 +42.26518411113102 + 10 +71.50969859107545 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +73.50969859107545 + 20 +40.26518411113102 + 10 +73.50969859107545 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +71.50969859107545 + 20 +4.409184111131253 + 10 +59.42089859107546 + 20 +4.409184111131253 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +29B +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +57.47902030232444 + 20 +-36.65201588886885 + 10 +57.47902030232444 + 20 +-2.796015888869078 + 42 +-0.4142135623730959 + 10 +59.47902030232445 + 20 +-0.7960158888690785 + 10 +71.56782030232444 + 20 +-0.796015888869078 + 42 +-0.414213562373095 + 10 +73.56782030232444 + 20 +-2.796015888869078 + 10 +73.56782030232444 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +71.56782030232444 + 20 +-38.65201588886885 + 10 +59.47902030232445 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +29C +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +57.42089859107545 + 20 +-79.71321588886894 + 10 +57.42089859107545 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +59.42089859107546 + 20 +-43.85721588886918 + 10 +71.50969859107545 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +73.50969859107545 + 20 +-45.85721588886918 + 10 +73.50969859107545 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +71.50969859107545 + 20 +-81.71321588886894 + 10 +59.42089859107546 + 20 +-81.71321588886894 + 42 +-0.4142135623730961 + 0 +LWPOLYLINE + 5 +29D +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +57.42089859107545 + 20 +-122.7742358520718 + 10 +57.42089859107546 + 20 +-88.91823585207204 + 42 +-0.4142135623730961 + 10 +59.42089859107546 + 20 +-86.91823585207202 + 10 +71.50969859107545 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +73.50969859107545 + 20 +-88.91823585207204 + 10 +73.50969859107545 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +71.50969859107545 + 20 +-124.7742358520718 + 10 +59.42089859107546 + 20 +-124.7742358520718 + 42 +-0.4142135623730961 + 0 +LWPOLYLINE + 5 +29E +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +100.9174425910746 + 20 +49.47057024059358 + 10 +100.9174425910746 + 20 +83.32657024059336 + 42 +-0.414213562373095 + 10 +102.9174425910746 + 20 +85.32657024059336 + 10 +115.0062425910746 + 20 +85.32657024059336 + 42 +-0.414213562373095 + 10 +117.0062425910746 + 20 +83.32657024059336 + 10 +117.0062425910746 + 20 +49.47057024059358 + 42 +-0.414213562373095 + 10 +115.0062425910746 + 20 +47.47057024059358 + 10 +102.9174425910746 + 20 +47.47057024059358 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +29F +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +100.9174425910746 + 20 +6.409184111131253 + 10 +100.9174425910746 + 20 +40.26518411113102 + 42 +-0.414213562373095 + 10 +102.9174425910746 + 20 +42.26518411113102 + 10 +115.0062425910746 + 20 +42.26518411113102 + 42 +-0.414213562373095 + 10 +117.0062425910746 + 20 +40.26518411113102 + 10 +117.0062425910746 + 20 +6.409184111131253 + 42 +-0.414213562373095 + 10 +115.0062425910746 + 20 +4.409184111131253 + 10 +102.9174425910746 + 20 +4.409184111131253 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2A0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +100.9755643023236 + 20 +-36.65201588886885 + 10 +100.9755643023236 + 20 +-2.796015888869078 + 42 +-0.414213562373095 + 10 +102.9755643023236 + 20 +-0.796015888869078 + 10 +115.0643643023236 + 20 +-0.796015888869078 + 42 +-0.414213562373095 + 10 +117.0643643023236 + 20 +-2.796015888869078 + 10 +117.0643643023236 + 20 +-36.65201588886885 + 42 +-0.414213562373095 + 10 +115.0643643023236 + 20 +-38.65201588886885 + 10 +102.9755643023236 + 20 +-38.65201588886885 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2A1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +100.9174425910746 + 20 +-79.71321588886894 + 10 +100.9174425910746 + 20 +-45.85721588886918 + 42 +-0.414213562373095 + 10 +102.9174425910746 + 20 +-43.85721588886918 + 10 +115.0062425910746 + 20 +-43.85721588886918 + 42 +-0.414213562373095 + 10 +117.0062425910746 + 20 +-45.85721588886918 + 10 +117.0062425910746 + 20 +-79.71321588886894 + 42 +-0.414213562373095 + 10 +115.0062425910746 + 20 +-81.71321588886894 + 10 +102.9174425910746 + 20 +-81.71321588886894 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2A2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +100.9174425910746 + 20 +-122.7742358520718 + 10 +100.9174425910746 + 20 +-88.91823585207204 + 42 +-0.414213562373095 + 10 +102.9174425910746 + 20 +-86.91823585207202 + 10 +115.0062425910746 + 20 +-86.91823585207202 + 42 +-0.414213562373095 + 10 +117.0062425910746 + 20 +-88.91823585207204 + 10 +117.0062425910746 + 20 +-122.7742358520718 + 42 +-0.414213562373095 + 10 +115.0062425910746 + 20 +-124.7742358520718 + 10 +102.9174425910746 + 20 +-124.7742358520718 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2A3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-51.35831740892673 + 20 +-101.9534297594073 + 10 +-51.35831740892672 + 20 +-68.09742975940753 + 42 +-0.414213562373095 + 10 +-49.35831740892672 + 20 +-66.09742975940753 + 10 +-37.26951740892673 + 20 +-66.09742975940753 + 42 +-0.414213562373095 + 10 +-35.26951740892673 + 20 +-68.09742975940753 + 10 +-35.26951740892673 + 20 +-101.9534297594073 + 42 +-0.414213562373095 + 10 +-37.26951740892673 + 20 +-103.9534297594073 + 10 +-49.35831740892672 + 20 +-103.9534297594073 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2A4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-51.35831740892673 + 20 +-58.41902975940683 + 10 +-51.35831740892672 + 20 +-24.56302975940707 + 42 +-0.414213562373095 + 10 +-49.35831740892672 + 20 +-22.56302975940707 + 10 +-37.26951740892673 + 20 +-22.56302975940707 + 42 +-0.414213562373095 + 10 +-35.26951740892673 + 20 +-24.56302975940707 + 10 +-35.26951740892673 + 20 +-58.41902975940683 + 42 +-0.4142135623730961 + 10 +-37.26951740892673 + 20 +-60.41902975940684 + 10 +-49.35831740892672 + 20 +-60.41902975940685 + 42 +-0.4142135623730961 + 0 +LWPOLYLINE + 5 +2A5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-51.35831740892673 + 20 +-14.88462975940638 + 10 +-51.35831740892672 + 20 +18.97137024059339 + 42 +-0.414213562373095 + 10 +-49.35831740892672 + 20 +20.97137024059339 + 10 +-37.26951740892673 + 20 +20.97137024059339 + 42 +-0.414213562373095 + 10 +-35.26951740892673 + 20 +18.97137024059339 + 10 +-35.26951740892673 + 20 +-14.88462975940638 + 42 +-0.414213562373095 + 10 +-37.26951740892673 + 20 +-16.88462975940638 + 10 +-49.35831740892672 + 20 +-16.88462975940638 + 42 +-0.4142135623730943 + 0 +LWPOLYLINE + 5 +2A6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-51.35831740892673 + 20 +28.64977024059226 + 10 +-51.35831740892672 + 20 +62.50577024059203 + 42 +-0.414213562373095 + 10 +-49.35831740892672 + 20 +64.50577024059203 + 10 +-37.26951740892673 + 20 +64.50577024059203 + 42 +-0.414213562373095 + 10 +-35.26951740892673 + 20 +62.50577024059203 + 10 +-35.26951740892673 + 20 +28.64977024059226 + 42 +-0.414213562373095 + 10 +-37.26951740892673 + 20 +26.64977024059226 + 10 +-49.35831740892672 + 20 +26.64977024059226 + 42 +-0.414213562373094 + 0 +LWPOLYLINE + 5 +2A7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-50.74315740892915 + 20 +-122.6322758520746 + 42 +0.414213562373094 + 10 +-48.74315740892916 + 20 +-124.6322758520746 + 10 +-37.88467740892838 + 20 +-124.6322758520746 + 42 +0.414213562373095 + 10 +-35.88467740892838 + 20 +-122.6322758520746 + 10 +-35.88467740892838 + 20 +-111.7737958520738 + 42 +0.414213562373095 + 10 +-37.88467740892838 + 20 +-109.7737958520738 + 10 +-48.74315740892916 + 20 +-109.7737958520738 + 42 +0.414213562373094 + 10 +-50.74315740892918 + 20 +-111.7737958520738 + 0 +LWPOLYLINE + 5 +2A8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-50.74315740892915 + 20 +72.32613024059172 + 42 +0.4142135623730971 + 10 +-48.74315740892916 + 20 +70.32613024059168 + 10 +-37.88467740892838 + 20 +70.32613024059172 + 42 +0.414213562373095 + 10 +-35.88467740892838 + 20 +72.32613024059172 + 10 +-35.88467740892838 + 20 +83.18461024059251 + 42 +0.4142135623730961 + 10 +-37.88467740892838 + 20 +85.18461024059252 + 10 +-48.74315740892916 + 20 +85.18461024059252 + 42 +0.414213562373095 + 10 +-50.74315740892917 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +2A9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.842845408925313 + 20 +-101.9534297594073 + 10 +-7.842845408925312 + 20 +-68.09742975940753 + 42 +-0.4142135623730949 + 10 +-5.842845408925313 + 20 +-66.09742975940753 + 10 +6.245954591074678 + 20 +-66.09742975940753 + 42 +-0.4142135623730949 + 10 +8.245954591074678 + 20 +-68.09742975940753 + 10 +8.245954591074678 + 20 +-101.9534297594073 + 42 +-0.414213562373095 + 10 +6.245954591074678 + 20 +-103.9534297594073 + 10 +-5.842845408925312 + 20 +-103.9534297594073 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2AA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.842845408925313 + 20 +-58.41902975940683 + 10 +-7.842845408925312 + 20 +-24.56302975940707 + 42 +-0.4142135623730949 + 10 +-5.842845408925313 + 20 +-22.56302975940707 + 10 +6.245954591074678 + 20 +-22.56302975940707 + 42 +-0.4142135623730949 + 10 +8.245954591074678 + 20 +-24.56302975940707 + 10 +8.24595459107468 + 20 +-58.41902975940683 + 42 +-0.4142135623730963 + 10 +6.245954591074677 + 20 +-60.41902975940684 + 10 +-5.842845408925313 + 20 +-60.41902975940684 + 42 +-0.4142135623730961 + 0 +LWPOLYLINE + 5 +2AB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.842845408925313 + 20 +-14.88462975940638 + 10 +-7.842845408925312 + 20 +18.97137024059339 + 42 +-0.4142135623730949 + 10 +-5.842845408925313 + 20 +20.97137024059339 + 10 +6.245954591074678 + 20 +20.97137024059339 + 42 +-0.4142135623730949 + 10 +8.245954591074678 + 20 +18.97137024059339 + 10 +8.245954591074678 + 20 +-14.88462975940638 + 42 +-0.414213562373095 + 10 +6.245954591074678 + 20 +-16.88462975940638 + 10 +-5.842845408925312 + 20 +-16.88462975940638 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2AC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.842845408925313 + 20 +28.64977024059226 + 10 +-7.842845408925312 + 20 +62.50577024059203 + 42 +-0.4142135623730949 + 10 +-5.842845408925313 + 20 +64.50577024059203 + 10 +6.245954591074678 + 20 +64.50577024059203 + 42 +-0.4142135623730949 + 10 +8.245954591074678 + 20 +62.50577024059203 + 10 +8.245954591074678 + 20 +28.64977024059226 + 42 +-0.414213562373095 + 10 +6.245954591074678 + 20 +26.64977024059226 + 10 +-5.842845408925312 + 20 +26.64977024059226 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2AD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.227685408927753 + 20 +-122.6322758520746 + 42 +0.414213562373095 + 10 +-5.227685408927753 + 20 +-124.6322758520746 + 10 +5.630794591073027 + 20 +-124.6322758520746 + 42 +0.414213562373095 + 10 +7.630794591073027 + 20 +-122.6322758520746 + 10 +7.630794591073025 + 20 +-111.7737958520738 + 42 +0.4142135623730949 + 10 +5.630794591073026 + 20 +-109.7737958520738 + 10 +-5.227685408927754 + 20 +-109.7737958520738 + 42 +0.4142135623730953 + 10 +-7.227685408927757 + 20 +-111.7737958520738 + 0 +LWPOLYLINE + 5 +2AE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +-7.227685408927753 + 20 +72.32613024059172 + 42 +0.414213562373095 + 10 +-5.227685408927753 + 20 +70.32613024059172 + 10 +5.630794591073027 + 20 +70.32613024059172 + 42 +0.414213562373095 + 10 +7.630794591073027 + 20 +72.32613024059172 + 10 +7.630794591073025 + 20 +83.18461024059251 + 42 +0.4142135623730971 + 10 +5.630794591073026 + 20 +85.18461024059252 + 10 +-5.227685408927754 + 20 +85.18461024059252 + 42 +0.4142135623730971 + 10 +-7.227685408927755 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +2AF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +35.6726265910761 + 20 +-101.9534297594073 + 10 +35.6726265910761 + 20 +-68.09742975940753 + 42 +-0.414213562373095 + 10 +37.6726265910761 + 20 +-66.09742975940753 + 10 +49.76142659107608 + 20 +-66.09742975940753 + 42 +-0.414213562373095 + 10 +51.76142659107608 + 20 +-68.09742975940753 + 10 +51.76142659107608 + 20 +-101.9534297594073 + 42 +-0.414213562373095 + 10 +49.76142659107608 + 20 +-103.9534297594073 + 10 +37.6726265910761 + 20 +-103.9534297594073 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2B0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +35.6726265910761 + 20 +-58.41902975940683 + 10 +35.6726265910761 + 20 +-24.56302975940707 + 42 +-0.414213562373095 + 10 +37.6726265910761 + 20 +-22.56302975940707 + 10 +49.76142659107608 + 20 +-22.56302975940707 + 42 +-0.414213562373095 + 10 +51.76142659107608 + 20 +-24.56302975940707 + 10 +51.76142659107609 + 20 +-58.41902975940683 + 42 +-0.4142135623730992 + 10 +49.76142659107608 + 20 +-60.41902975940684 + 10 +37.6726265910761 + 20 +-60.41902975940684 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2B1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +35.6726265910761 + 20 +-14.88462975940638 + 10 +35.6726265910761 + 20 +18.97137024059339 + 42 +-0.414213562373095 + 10 +37.6726265910761 + 20 +20.97137024059339 + 10 +49.76142659107608 + 20 +20.97137024059339 + 42 +-0.414213562373095 + 10 +51.76142659107608 + 20 +18.97137024059339 + 10 +51.76142659107608 + 20 +-14.88462975940638 + 42 +-0.414213562373095 + 10 +49.76142659107608 + 20 +-16.88462975940638 + 10 +37.6726265910761 + 20 +-16.88462975940638 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2B2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +35.6726265910761 + 20 +28.64977024059226 + 10 +35.6726265910761 + 20 +62.50577024059203 + 42 +-0.414213562373095 + 10 +37.6726265910761 + 20 +64.50577024059203 + 10 +49.76142659107608 + 20 +64.50577024059203 + 42 +-0.414213562373095 + 10 +51.76142659107608 + 20 +62.50577024059203 + 10 +51.76142659107608 + 20 +28.64977024059226 + 42 +-0.414213562373095 + 10 +49.76142659107608 + 20 +26.64977024059226 + 10 +37.6726265910761 + 20 +26.64977024059226 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2B3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +36.28778659107366 + 20 +-122.6322758520746 + 42 +0.414213562373095 + 10 +38.28778659107366 + 20 +-124.6322758520746 + 10 +49.14626659107444 + 20 +-124.6322758520746 + 42 +0.4142135623730961 + 10 +51.14626659107445 + 20 +-122.6322758520746 + 10 +51.14626659107442 + 20 +-111.7737958520738 + 42 +0.4142135623730961 + 10 +49.14626659107444 + 20 +-109.7737958520738 + 10 +38.28778659107366 + 20 +-109.7737958520738 + 42 +0.414213562373095 + 10 +36.28778659107366 + 20 +-111.7737958520738 + 0 +LWPOLYLINE + 5 +2B4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +36.28778659107366 + 20 +72.32613024059172 + 42 +0.414213562373095 + 10 +38.28778659107366 + 20 +70.32613024059172 + 10 +49.14626659107444 + 20 +70.32613024059172 + 42 +0.4142135623730961 + 10 +51.14626659107445 + 20 +72.32613024059172 + 10 +51.14626659107443 + 20 +83.18461024059251 + 42 +0.4142135623730971 + 10 +49.14626659107444 + 20 +85.18461024059253 + 10 +38.28778659107366 + 20 +85.18461024059252 + 42 +0.4142135623730992 + 10 +36.28778659107364 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +2B5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.16917059107527 + 20 +-101.9534297594073 + 10 +79.16917059107529 + 20 +-68.09742975940753 + 42 +-0.414213562373095 + 10 +81.16917059107526 + 20 +-66.09742975940753 + 10 +93.25797059107526 + 20 +-66.09742975940753 + 42 +-0.414213562373095 + 10 +95.25797059107526 + 20 +-68.09742975940753 + 10 +95.25797059107526 + 20 +-101.9534297594073 + 42 +-0.414213562373095 + 10 +93.25797059107526 + 20 +-103.9534297594073 + 10 +81.16917059107526 + 20 +-103.9534297594073 + 42 +-0.4142135623730929 + 0 +LWPOLYLINE + 5 +2B6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.16917059107527 + 20 +-58.41902975940683 + 10 +79.16917059107529 + 20 +-24.56302975940707 + 42 +-0.414213562373095 + 10 +81.16917059107526 + 20 +-22.56302975940707 + 10 +93.25797059107526 + 20 +-22.56302975940707 + 42 +-0.414213562373095 + 10 +95.25797059107526 + 20 +-24.56302975940707 + 10 +95.25797059107526 + 20 +-58.41902975940683 + 42 +-0.4142135623730961 + 10 +93.25797059107526 + 20 +-60.41902975940684 + 10 +81.16917059107526 + 20 +-60.41902975940684 + 42 +-0.414213562373095 + 0 +LWPOLYLINE + 5 +2B7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.16917059107527 + 20 +-14.88462975940638 + 10 +79.16917059107529 + 20 +18.97137024059339 + 42 +-0.414213562373095 + 10 +81.16917059107526 + 20 +20.97137024059339 + 10 +93.25797059107526 + 20 +20.97137024059339 + 42 +-0.414213562373095 + 10 +95.25797059107526 + 20 +18.97137024059339 + 10 +95.25797059107526 + 20 +-14.88462975940638 + 42 +-0.414213562373095 + 10 +93.25797059107526 + 20 +-16.88462975940638 + 10 +81.16917059107526 + 20 +-16.88462975940638 + 42 +-0.4142135623730929 + 0 +LWPOLYLINE + 5 +2B8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.16917059107527 + 20 +28.64977024059226 + 10 +79.16917059107529 + 20 +62.50577024059203 + 42 +-0.414213562373095 + 10 +81.16917059107526 + 20 +64.50577024059203 + 10 +93.25797059107526 + 20 +64.50577024059203 + 42 +-0.414213562373095 + 10 +95.25797059107526 + 20 +62.50577024059203 + 10 +95.25797059107526 + 20 +28.64977024059226 + 42 +-0.414213562373095 + 10 +93.25797059107526 + 20 +26.64977024059226 + 10 +81.16917059107526 + 20 +26.64977024059226 + 42 +-0.4142135623730929 + 0 +LWPOLYLINE + 5 +2B9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.78433059107284 + 20 +-122.6322758520746 + 42 +0.414213562373095 + 10 +81.78433059107282 + 20 +-124.6322758520746 + 10 +92.64281059107361 + 20 +-124.6322758520746 + 42 +0.414213562373095 + 10 +94.64281059107361 + 20 +-122.6322758520746 + 10 +94.64281059107361 + 20 +-111.7737958520738 + 42 +0.414213562373095 + 10 +92.64281059107361 + 20 +-109.7737958520738 + 10 +81.78433059107282 + 20 +-109.7737958520738 + 42 +0.414213562373095 + 10 +79.78433059107284 + 20 +-111.7737958520738 + 0 +LWPOLYLINE + 5 +2BA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +79.78433059107284 + 20 +72.32613024059172 + 42 +0.414213562373095 + 10 +81.78433059107282 + 20 +70.32613024059172 + 10 +92.64281059107361 + 20 +70.32613024059174 + 42 +0.4142135623730929 + 10 +94.64281059107361 + 20 +72.32613024059172 + 10 +94.64281059107361 + 20 +83.18461024059251 + 42 +0.414213562373095 + 10 +92.64281059107361 + 20 +85.18461024059253 + 10 +81.78433059107282 + 20 +85.18461024059252 + 42 +0.414213562373095 + 10 +79.78433059107283 + 20 +83.18461024059251 + 0 +LWPOLYLINE + 5 +2BB +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +123.2808745910752 + 20 +71.73463024059311 + 42 +0.414213562373095 + 10 +125.2808745910752 + 20 +69.73463024059311 + 10 +136.139354591076 + 20 +69.73463024059311 + 42 +0.414213562373095 + 10 +138.139354591076 + 20 +71.73463024059311 + 10 +138.139354591076 + 20 +82.59311024059389 + 42 +0.414213562373095 + 10 +136.139354591076 + 20 +84.59311024059389 + 10 +125.2808745910752 + 20 +84.59311024059387 + 42 +0.4142135623730971 + 10 +123.2808745910752 + 20 +82.59311024059389 + 0 +LWPOLYLINE + 5 +2BC +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +123.2808745910752 + 20 +-14.38795588886932 + 42 +0.4142135623730963 + 10 +125.2808745910752 + 20 +-16.38795588886933 + 10 +136.139354591076 + 20 +-16.38795588886933 + 42 +0.4142135623730963 + 10 +138.139354591076 + 20 +-14.38795588886932 + 10 +138.139354591076 + 20 +-3.529475888868546 + 42 +0.414213562373095 + 10 +136.139354591076 + 20 +-1.529475888868546 + 10 +125.2808745910752 + 20 +-1.529475888868546 + 42 +0.414213562373095 + 10 +123.2808745910752 + 20 +-3.529475888868546 + 0 +LWPOLYLINE + 5 +2BD +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +123.2808745910752 + 20 +-35.9186489536005 + 42 +0.414213562373095 + 10 +125.2808745910752 + 20 +-37.9186489536005 + 10 +136.139354591076 + 20 +-37.9186489536005 + 42 +0.414213562373095 + 10 +138.139354591076 + 20 +-35.9186489536005 + 10 +138.139354591076 + 20 +-25.06016895359972 + 42 +0.414213562373095 + 10 +136.139354591076 + 20 +-23.06016895359972 + 10 +125.2808745910752 + 20 +-23.06016895359972 + 42 +0.414213562373095 + 10 +123.2808745910752 + 20 +-25.06016895359972 + 0 +LWPOLYLINE + 5 +2BE +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +123.2808745910752 + 20 +-57.44915588886943 + 42 +0.414213562373095 + 10 +125.2808745910752 + 20 +-59.44915588886943 + 10 +136.139354591076 + 20 +-59.44915588886943 + 42 +0.414213562373095 + 10 +138.139354591076 + 20 +-57.44915588886943 + 10 +138.139354591076 + 20 +-46.59067588886864 + 42 +0.414213562373095 + 10 +136.139354591076 + 20 +-44.59067588886864 + 10 +125.2808745910752 + 20 +-44.59067588886864 + 42 +0.414213562373095 + 10 +123.2808745910752 + 20 +-46.59067588886864 + 0 +LWPOLYLINE + 5 +2BF +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 8 + 70 + 1 + 43 +0 + 10 +123.280874591072 + 20 +-122.6322758520746 + 42 +0.414213562373095 + 10 +125.280874591072 + 20 +-124.6322758520746 + 10 +136.1393545910728 + 20 +-124.6322758520746 + 42 +0.414213562373095 + 10 +138.1393545910728 + 20 +-122.6322758520746 + 10 +138.1393545910728 + 20 +-111.7737958520738 + 42 +0.414213562373095 + 10 +136.1393545910728 + 20 +-109.7737958520738 + 10 +125.280874591072 + 20 +-109.7737958520738 + 42 +0.414213562373095 + 10 +123.280874591072 + 20 +-111.7737958520738 + 0 +CIRCLE + 5 +2C0 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +135.7287637886265 + 20 +-137.5506342337085 + 40 +4 + 0 +CIRCLE + 5 +2C1 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +77.28583459106994 + 20 +-137.5506342337085 + 40 +5 + 0 +CIRCLE + 5 +2C2 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +15.29663459106586 + 20 +-137.5506342337103 + 40 +5 + 0 +CIRCLE + 5 +2C3 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-46.69256540893002 + 20 +-137.5506342337085 + 40 +5 + 0 +CIRCLE + 5 +2C4 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-108.6817654089268 + 20 +-137.5506342337085 + 40 +5 + 0 +CIRCLE + 5 +2C5 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-77.68716540893274 + 20 +97.15656881262113 + 40 +5 + 0 +CIRCLE + 5 +2C6 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-15.69796540893003 + 20 +97.15656881262476 + 40 +5 + 0 +CIRCLE + 5 +2C7 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +46.29123459106994 + 20 +97.15656881262476 + 40 +5 + 0 +CIRCLE + 5 +2C8 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +108.2804345910699 + 20 +97.15656881262476 + 40 +5 + 0 +CIRCLE + 5 +2C9 +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbCircle + 10 +-135.5278767893387 + 20 +97.15656881263023 + 40 +4 + 0 +ENDBLK + 5 +82 +330 +80 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +2CA +100 +AcDbEntity + 8 +0 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 3 + 70 + 0 + 43 +0 + 10 +50.89394130774346 + 20 +-45.65485911429928 + 10 +102.5363229288361 + 20 +-0.7484403133491686 + 10 +186.7358581806176 + 20 +-78.21201274498812 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/nicechart_01.csv b/share/extensions/tests/data/io/nicechart_01.csv new file mode 100644 index 0000000..2cd8d62 --- /dev/null +++ b/share/extensions/tests/data/io/nicechart_01.csv @@ -0,0 +1,13 @@ +Month;1978;1979;1980;1981 +January;2;1,3;0.1;2.3 +February;6.5;2.4;1.2;6.1 +March;7.4;6.7;7.9;4.7 +April;7.7;6.4;8.2;8.9 +May;10.9;11.7;18.7;11.1 +June;12.6;14.2;14.7;14.7 +July;16.5;15.5;17.5;15.1 +August;15.9;15.4;14.6;16.6 +September;14;14.5;13.2;15.3 +October;11.9;13.9;11.5;9.2 +November;6.7;8.5;7;6.6 +December;6.4;2.2;6.3;3.5 diff --git a/share/extensions/tests/data/io/no_block_section.dxf b/share/extensions/tests/data/io/no_block_section.dxf new file mode 100644 index 0000000..624759c --- /dev/null +++ b/share/extensions/tests/data/io/no_block_section.dxf @@ -0,0 +1,10690 @@ + 0 +SECTION + 2 +HEADER + 9 +$EXTMIN + 10 +0 + 20 +0 + 9 +$EXTMAX + 10 +42000 + 20 +29700 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +LTYPE + 70 + 9 + 0 +LTYPE + 2 +CONTINUOUS + 70 + 64 + 3 +ŽÀü + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 2 +DASHED1 + 70 + 64 + 3 +-- -- -- -- -- -- -- -- + 72 + 65 + 73 + 2 + 40 +2.5 + 49 +1.25 + 49 +-1.25 + 0 +LTYPE + 2 +DASHED2 + 70 + 64 + 3 +---- ---- ---- ---- + 72 + 65 + 73 + 2 + 40 +5.0 + 49 +2.5 + 49 +-2.5 + 0 +LTYPE + 2 +DASHED3 + 70 + 64 + 3 +------ ------ ------ ------ + 72 + 65 + 73 + 2 + 40 +5.0 + 49 +3.75 + 49 +-1.25 + 0 +LTYPE + 2 +CENTER1 + 70 + 64 + 3 +----- - ----- - ----- - ----- - + 72 + 65 + 73 + 4 + 40 +10.0 + 49 +6.25 + 49 +-1.25 + 49 +1.25 + 49 +-1.25 + 0 +LTYPE + 2 +CENTER2 + 70 + 64 + 3 +---------- -- ---------- -- + 72 + 65 + 73 + 4 + 40 +20.0 + 49 +12.5 + 49 +-2.5 + 49 +2.5 + 49 +-2.5 + 0 +LTYPE + 2 +PHANTOM1 + 70 + 64 + 3 +--- - - --- - - --- - - --- - - + 72 + 65 + 73 + 6 + 40 +10.0 + 49 +3.25 + 49 +-1.25 + 49 +1.25 + 49 +-1.25 + 49 +1.25 + 49 +-1.25 + 0 +LTYPE + 2 +PHANTOM2 + 70 + 64 + 3 +-------- - - -------- - - + 72 + 65 + 73 + 6 + 40 +20.0 + 49 +10.0 + 49 +-2.5 + 49 +1.25 + 49 +-2.5 + 49 +1.25 + 49 +-2.5 + 0 +LTYPE + 2 +DOT + 70 + 64 + 3 +- - - - - - - - + 72 + 65 + 73 + 2 + 40 +2.5 + 49 +0.625 + 49 +-1.875 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 70 + 1 + 0 +STYLE + 2 +STANDARD + 70 + 64 + 40 +0.0 + 41 +1.0 + 42 +0.0 + 50 +0.0 + 71 + 0 + 3 +TXT + 4 +BIGFONT + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 70 + 5 + 0 +LAYER + 2 +0-0 + 70 + 64 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +0x1 + 70 + 64 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +0-2 + 70 + 64 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +1-0 + 70 + 64 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +ADD_LINE + 70 + 64 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17499.998 + 20 +28499.998 + 11 +25499.998 + 21 +28499.998 + 0 +LINE + 8 +0-0 + 6 +DASHED1 + 62 + 7 + 10 +17499.998 + 20 +27999.997 + 11 +25499.998 + 21 +27999.997 + 0 +LINE + 8 +0-0 + 6 +DASHED2 + 62 + 3 + 10 +17499.998 + 20 +27500 + 11 +25499.998 + 21 +27500 + 0 +LINE + 8 +0-0 + 6 +DASHED3 + 62 + 2 + 10 +17499.998 + 20 +26999.998 + 11 +25499.998 + 21 +26999.998 + 0 +LINE + 8 +0-0 + 6 +CENTER1 + 62 + 6 + 10 +17499.998 + 20 +26499.999 + 11 +25499.998 + 21 +26499.999 + 0 +LINE + 8 +0-0 + 6 +CENTER2 + 62 + 5 + 10 +17499.998 + 20 +26000 + 11 +25499.998 + 21 +26000 + 0 +LINE + 8 +0-0 + 6 +PHANTOM1 + 62 + 4 + 10 +17499.998 + 20 +25499.998 + 11 +25499.998 + 21 +25499.998 + 0 +LINE + 8 +0-0 + 6 +PHANTOM2 + 62 + 4 + 10 +17499.998 + 20 +24999.999 + 11 +25499.998 + 21 +24999.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +499.99996 + 20 +29249.998 + 11 +499.99996 + 21 +29449.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +499.99996 + 20 +29449.999 + 11 +2700.0001 + 21 +29449.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +2700.0001 + 20 +29249.998 + 11 +2700.0001 + 21 +29449.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +499.99996 + 20 +29249.998 + 11 +2700.0001 + 21 +29249.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +499.99996 + 20 +28999.997 + 11 +499.99996 + 21 +29199.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +499.99996 + 20 +28999.997 + 11 +3749.9998 + 21 +28999.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +3749.9998 + 20 +28999.997 + 11 +3749.9998 + 21 +29199.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +3749.9998 + 20 +29199.998 + 11 +500.00008 + 21 +29199.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +499.99996 + 20 +28499.998 + 11 +4899.9998 + 21 +28499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +499.99996 + 20 +28499.998 + 11 +499.99996 + 21 +28899.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +499.99996 + 20 +28899.997 + 11 +4899.9998 + 21 +28899.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +4899.9998 + 20 +28499.998 + 11 +4899.9998 + 21 +28899.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +499.99996 + 20 +27999.997 + 11 +499.99996 + 21 +28399.995 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +499.99996 + 20 +27999.997 + 11 +6999.9992 + 21 +27999.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +6999.9992 + 20 +27999.997 + 11 +6999.9992 + 21 +28399.995 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +6999.9992 + 20 +28399.995 + 11 +499.99977 + 21 +28399.995 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +499.99996 + 20 +26499.997 + 11 +10249.999 + 21 +26499.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +10249.999 + 20 +26499.997 + 11 +10249.999 + 21 +27099.996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +10249.999 + 20 +27099.996 + 11 +499.99977 + 21 +27099.996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +499.99977 + 20 +27099.996 + 11 +499.99996 + 21 +26499.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +499.99977 + 20 +27249.997 + 11 +499.99977 + 21 +27849.996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +499.99977 + 20 +27249.997 + 11 +7099.9996 + 21 +27249.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +7099.9996 + 20 +27249.997 + 11 +7099.9996 + 21 +27849.996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +7099.9996 + 20 +27849.996 + 11 +499.99977 + 21 +27849.996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +499.99996 + 20 +24499.998 + 11 +499.99996 + 21 +25299.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +499.99996 + 20 +24499.998 + 11 +13500 + 21 +24499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +13499.999 + 20 +24499.998 + 11 +13499.999 + 21 +25299.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +13499.999 + 20 +25299.998 + 11 +500.00039 + 21 +25299.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +499.99977 + 20 +25499.998 + 11 +499.99977 + 21 +26299.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +9299.9993 + 20 +25499.998 + 11 +9299.9993 + 21 +26299.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +499.99977 + 20 +25499.998 + 11 +9299.9993 + 21 +25499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +9299.9993 + 20 +26299.999 + 11 +499.99977 + 21 +26299.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +499.99996 + 20 +23249.998 + 11 +499.99996 + 21 +24249.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +499.99996 + 20 +23249.998 + 11 +10499.999 + 21 +23249.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +10499.999 + 20 +23249.998 + 11 +10499.999 + 21 +24249.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +10499.999 + 20 +24249.997 + 11 +499.99977 + 21 +24249.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +499.99996 + 20 +21999.997 + 11 +499.99996 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +499.99996 + 20 +21999.997 + 11 +15999.998 + 21 +21999.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +15999.998 + 20 +21999.997 + 11 +15999.998 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +15999.998 + 20 +22999.998 + 11 +500.00039 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10750 + 20 +20499.998 + 11 +10950.001 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10950.001 + 20 +20499.998 + 11 +10950.001 + 21 +18174.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10750 + 20 +18174.999 + 11 +10950.001 + 21 +18174.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10750 + 20 +20499.998 + 11 +10750 + 21 +18174.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10499.999 + 20 +20499.998 + 11 +10700 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10499.999 + 20 +17124.998 + 11 +10700 + 21 +17124.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10700 + 20 +17124.998 + 11 +10700 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +10000 + 20 +20499.998 + 11 +10000 + 21 +15874.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +10000 + 20 +20499.998 + 11 +10399.999 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +10399.999 + 20 +20499.998 + 11 +10399.999 + 21 +15874.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +10000 + 20 +15874.999 + 11 +10399.999 + 21 +15874.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +9499.9987 + 20 +20499.998 + 11 +9899.9975 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +9499.9987 + 20 +20499.998 + 11 +9499.9987 + 21 +13775 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +9499.9987 + 20 +13775 + 11 +9899.9975 + 21 +13775 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +9899.9975 + 20 +13775 + 11 +9899.9975 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +7999.9988 + 20 +20499.998 + 11 +7999.9988 + 21 +10374.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +7999.9988 + 20 +10374.999 + 11 +8599.9983 + 21 +10374.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +8599.9983 + 20 +10374.999 + 11 +8599.9983 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +8599.9983 + 20 +20499.998 + 11 +7999.9988 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +8749.9987 + 20 +20499.998 + 11 +9349.9982 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +8749.9987 + 20 +20499.998 + 11 +8749.9987 + 21 +13624.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +8749.9987 + 20 +13624.999 + 11 +9349.9982 + 21 +13624.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 3 + 10 +9349.9982 + 20 +13624.999 + 11 +9349.9982 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +6000.0009 + 20 +20499.998 + 11 +6799.9998 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +6000.0009 + 20 +20499.998 + 11 +6000.0009 + 21 +6874.9988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +6000.0009 + 20 +6875.0001 + 11 +6799.9998 + 21 +6875.0001 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +6799.9998 + 20 +6875.0001 + 11 +6799.9998 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +7000.0005 + 20 +20499.998 + 11 +7800.0006 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +7000.0005 + 20 +11249.999 + 11 +7800.0006 + 21 +11249.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +7000.0005 + 20 +20499.998 + 11 +7000.0005 + 21 +11249.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 2 + 10 +7800.0006 + 20 +11249.999 + 11 +7800.0006 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +4750.0018 + 20 +20499.998 + 11 +5750.0026 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +4750.0018 + 20 +20499.998 + 11 +4750.0018 + 21 +9999.9979 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +4750.0018 + 20 +9999.9979 + 11 +5750.0001 + 21 +9999.9979 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +5750.0001 + 20 +9999.9979 + 11 +5750.0001 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +3500.0002 + 20 +20499.998 + 11 +4500.001 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +3500.0002 + 20 +20499.998 + 11 +3500.0002 + 21 +4499.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +3500.0002 + 20 +4499.9998 + 11 +4500.001 + 21 +4499.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 6 + 10 +4500.001 + 20 +4499.9998 + 11 +4500.001 + 21 +20499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +10499.999 + 20 +20499.998 + 11 +10499.999 + 21 +17124.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +16999.998 + 20 +19999.998 + 11 +22999.998 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +16999.998 + 20 +19999.998 + 11 +17289.776 + 21 +20077.644 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +16999.998 + 20 +19999.998 + 11 +17289.776 + 21 +19922.351 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22999.998 + 20 +19999.998 + 11 +22710.221 + 21 +20077.644 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22999.998 + 20 +19999.998 + 11 +22710.221 + 21 +19922.351 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +19999.998 + 11 +19999.998 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +22999.998 + 11 +19922.352 + 21 +22710.221 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +22999.998 + 11 +20077.643 + 21 +22710.221 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +17454.414 + 20 +17454.414 + 11 +23429.467 + 21 +23429.467 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22121.319 + 20 +22121.319 + 11 +22271.32 + 21 +22381.126 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22121.319 + 20 +22121.319 + 11 +22381.126 + 21 +22271.32 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +17878.678 + 20 +17878.678 + 11 +17618.87 + 21 +17728.677 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +17878.678 + 20 +17878.678 + 11 +17728.677 + 21 +17618.87 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +19999.998 + 11 +23288.042 + 21 +16711.952 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22121.317 + 20 +17878.678 + 11 +22381.123 + 21 +17728.677 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +22121.317 + 20 +17878.678 + 11 +22271.317 + 21 +17618.87 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +28605.549 + 20 +19999.998 + 11 +29301.161 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +23605.55 + 11 +24999.997 + 21 +24301.162 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +26118.031 + 20 +19999.998 + 11 +26802.774 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +21118.032 + 11 +24999.997 + 21 +21802.773 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24999.997 + 20 +22999.998 + 11 +24999.997 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27999.997 + 20 +19999.998 + 11 +24999.997 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +18999.998 + 11 +27999.997 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +19499.999 + 11 +24999.997 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +27999.997 + 20 +19499.999 + 11 +27999.997 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +23999.998 + 20 +22999.998 + 11 +23999.998 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24499.998 + 20 +22999.998 + 11 +23999.998 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24499.998 + 20 +19999.998 + 11 +23999.998 + 21 +19999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +14999.999 + 11 +28111.268 + 21 +18111.269 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +14999.999 + 11 +24717.156 + 21 +15282.841 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24717.156 + 20 +15282.841 + 11 +27828.424 + 21 +18394.111 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +28111.268 + 20 +18111.269 + 11 +27828.424 + 21 +18394.111 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +25499.998 + 20 +14499.998 + 11 +28611.267 + 21 +17611.268 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +25249.998 + 20 +14749.999 + 11 +25499.998 + 21 +14499.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +28361.269 + 20 +17861.269 + 11 +28611.269 + 21 +17611.268 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +29301.161 + 20 +19999.998 + 11 +29223.515 + 21 +20289.776 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +29301.161 + 20 +19999.998 + 11 +29378.808 + 21 +20289.776 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +24301.162 + 11 +25289.774 + 21 +24378.809 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +24301.162 + 11 +25289.774 + 21 +24223.516 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +16999.998 + 20 +11999.999 + 11 +22999.998 + 21 +11999.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +9899.9994 + 11 +19999.998 + 21 +15349.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +13499.999 + 11 +19922.352 + 21 +13789.777 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +13499.999 + 11 +20077.643 + 21 +13789.777 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +10499.999 + 11 +19922.352 + 21 +10210.221 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +19999.998 + 20 +10499.999 + 11 +20077.643 + 21 +10210.221 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23499.997 + 20 +10499.999 + 11 +23499.997 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23499.997 + 20 +8499.9992 + 11 +31499.998 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31499.998 + 20 +8499.9992 + 11 +31499.998 + 21 +10499.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31499.998 + 20 +10499.999 + 11 +23499.997 + 21 +10499.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23499.997 + 20 +9499.9993 + 11 +31499.998 + 21 +9499.9993 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23499.997 + 20 +9499.9993 + 11 +23598.762 + 21 +9654.5181 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23598.762 + 20 +9654.5181 + 11 +23697.528 + 21 +9805.3252 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23697.528 + 20 +9805.3252 + 11 +23796.294 + 21 +9948.7989 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23796.294 + 20 +9948.7989 + 11 +23895.059 + 21 +10081.491 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23895.059 + 20 +10081.491 + 11 +23993.825 + 21 +10200.216 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23993.825 + 20 +10200.216 + 11 +24092.59 + 21 +10302.122 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24092.59 + 20 +10302.122 + 11 +24191.356 + 21 +10384.761 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24191.356 + 20 +10384.761 + 11 +24290.122 + 21 +10446.147 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24290.122 + 20 +10446.147 + 11 +24388.885 + 21 +10484.806 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24388.885 + 20 +10484.806 + 11 +24487.65 + 21 +10499.811 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24487.65 + 20 +10499.811 + 11 +24586.416 + 21 +10490.799 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24586.416 + 20 +10490.799 + 11 +24685.182 + 21 +10457.989 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24685.182 + 20 +10457.989 + 11 +24783.947 + 21 +10402.166 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24783.947 + 20 +10402.166 + 11 +24882.713 + 21 +10324.674 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24882.713 + 20 +10324.674 + 11 +24981.478 + 21 +10227.372 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24981.478 + 20 +10227.372 + 11 +25080.244 + 21 +10112.599 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25080.244 + 20 +10112.599 + 11 +25179.01 + 21 +9983.1113 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25179.01 + 20 +9983.1113 + 11 +25277.775 + 21 +9842.0193 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25277.775 + 20 +9842.0193 + 11 +25376.541 + 21 +9692.711 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25376.541 + 20 +9692.711 + 11 +25475.306 + 21 +9538.7744 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25475.306 + 20 +9538.7744 + 11 +25574.072 + 21 +9383.9061 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25574.072 + 20 +9383.9061 + 11 +25672.838 + 21 +9231.8265 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25672.838 + 20 +9231.8265 + 11 +25771.603 + 21 +9086.1884 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25771.603 + 20 +9086.1884 + 11 +25870.366 + 21 +8950.4899 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25870.366 + 20 +8950.4899 + 11 +25969.132 + 21 +8827.9912 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25969.132 + 20 +8827.9912 + 11 +26067.898 + 21 +8721.6341 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26067.898 + 20 +8721.6341 + 11 +26166.663 + 21 +8633.9736 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26166.663 + 20 +8633.9736 + 11 +26265.429 + 21 +8567.1154 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26265.429 + 20 +8567.1154 + 11 +26364.194 + 21 +8522.6653 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26364.194 + 20 +8522.6653 + 11 +26462.96 + 21 +8501.691 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26462.96 + 20 +8501.691 + 11 +26561.726 + 21 +8504.6968 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26561.726 + 20 +8504.6968 + 11 +26660.491 + 21 +8531.6096 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26660.491 + 20 +8531.6096 + 11 +26759.257 + 21 +8581.7836 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26759.257 + 20 +8581.7836 + 11 +26858.022 + 21 +8654.0131 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26858.022 + 20 +8654.0131 + 11 +26956.788 + 21 +8746.5637 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26956.788 + 20 +8746.5637 + 11 +27055.554 + 21 +8857.2126 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27055.554 + 20 +8857.2126 + 11 +27154.319 + 21 +8983.3011 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27154.319 + 20 +8983.3011 + 11 +27253.085 + 21 +9121.8 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27253.085 + 20 +9121.8 + 11 +27351.848 + 21 +9269.3842 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27351.848 + 20 +9269.3842 + 11 +27450.616 + 21 +9422.508 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27450.616 + 20 +9422.508 + 11 +27549.379 + 21 +9577.4932 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27549.379 + 20 +9577.4932 + 11 +27648.145 + 21 +9730.6163 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27648.145 + 20 +9730.6163 + 11 +27746.91 + 21 +9878.2 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27746.91 + 20 +9878.2 + 11 +27845.676 + 21 +10016.699 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27845.676 + 20 +10016.699 + 11 +27944.441 + 21 +10142.788 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27944.441 + 20 +10142.788 + 11 +28043.207 + 21 +10253.435 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28043.207 + 20 +10253.435 + 11 +28141.973 + 21 +10345.986 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28141.973 + 20 +10345.986 + 11 +28240.738 + 21 +10418.215 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28240.738 + 20 +10418.215 + 11 +28339.504 + 21 +10468.389 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28339.504 + 20 +10468.389 + 11 +28438.269 + 21 +10495.301 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28438.269 + 20 +10495.301 + 11 +28537.035 + 21 +10498.307 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28537.035 + 20 +10498.307 + 11 +28635.801 + 21 +10477.332 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28635.801 + 20 +10477.332 + 11 +28734.566 + 21 +10432.882 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28734.566 + 20 +10432.882 + 11 +28833.329 + 21 +10366.024 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28833.329 + 20 +10366.024 + 11 +28932.097 + 21 +10278.363 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28932.097 + 20 +10278.363 + 11 +29030.861 + 21 +10172.006 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29030.861 + 20 +10172.006 + 11 +29129.629 + 21 +10049.506 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29129.629 + 20 +10049.506 + 11 +29228.392 + 21 +9913.8084 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29228.392 + 20 +9913.8084 + 11 +29327.157 + 21 +9768.1709 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29327.157 + 20 +9768.1709 + 11 +29425.923 + 21 +9616.0913 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29425.923 + 20 +9616.0913 + 11 +29524.689 + 21 +9461.2224 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29524.689 + 20 +9461.2224 + 11 +29623.454 + 21 +9307.2864 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29623.454 + 20 +9307.2864 + 11 +29722.22 + 21 +9157.9781 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29722.22 + 20 +9157.9781 + 11 +29820.985 + 21 +9016.8855 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29820.985 + 20 +9016.8855 + 11 +29919.751 + 21 +8887.3977 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29919.751 + 20 +8887.3977 + 11 +30018.517 + 21 +8772.6246 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30018.517 + 20 +8772.6246 + 11 +30117.282 + 21 +8675.3239 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30117.282 + 20 +8675.3239 + 11 +30216.048 + 21 +8597.8313 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30216.048 + 20 +8597.8313 + 11 +30314.813 + 21 +8542.0095 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30314.813 + 20 +8542.0095 + 11 +30413.579 + 21 +8509.199 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30413.579 + 20 +8509.199 + 11 +30512.342 + 21 +8500.1872 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30512.342 + 20 +8500.1872 + 11 +30611.11 + 21 +8515.192 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30611.11 + 20 +8515.192 + 11 +30709.873 + 21 +8553.852 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30709.873 + 20 +8553.852 + 11 +30808.641 + 21 +8615.2387 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30808.641 + 20 +8615.2387 + 11 +30907.405 + 21 +8697.8768 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30907.405 + 20 +8697.8768 + 11 +31006.17 + 21 +8799.783 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31006.17 + 20 +8799.783 + 11 +31104.936 + 21 +8918.509 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31104.936 + 20 +8918.509 + 11 +31203.701 + 21 +9051.201 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31203.701 + 20 +9051.201 + 11 +31302.467 + 21 +9194.6747 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31302.467 + 20 +9194.6747 + 11 +31401.233 + 21 +9345.4824 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31401.233 + 20 +9345.4824 + 11 +31499.998 + 21 +9500.0012 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12499.999 + 20 +4999.9992 + 11 +12593.749 + 21 +4757.8113 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12593.749 + 20 +4757.8113 + 11 +12687.499 + 21 +4531.2495 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12687.499 + 20 +4531.2495 + 11 +12781.249 + 21 +4320.3121 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12781.249 + 20 +4320.3121 + 11 +12874.999 + 21 +4124.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12874.999 + 20 +4124.9998 + 11 +12968.749 + 21 +3945.3124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12968.749 + 20 +3945.3124 + 11 +13062.499 + 21 +3781.2499 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13062.499 + 20 +3781.2499 + 11 +13156.249 + 21 +3632.8123 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13156.249 + 20 +3632.8123 + 11 +13249.999 + 21 +3499.9999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13249.999 + 20 +3499.9999 + 11 +13343.749 + 21 +3382.8124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13343.749 + 20 +3382.8124 + 11 +13437.499 + 21 +3281.2498 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13437.499 + 20 +3281.2498 + 11 +13531.249 + 21 +3195.3124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13531.249 + 20 +3195.3124 + 11 +13624.999 + 21 +3124.9999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13624.999 + 20 +3124.9999 + 11 +13718.749 + 21 +3070.3123 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13718.749 + 20 +3070.3123 + 11 +13812.499 + 21 +3031.2499 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13812.499 + 20 +3031.2499 + 11 +13906.249 + 21 +3007.8124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13906.249 + 20 +3007.8124 + 11 +13999.999 + 21 +2999.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13999.999 + 20 +2999.9998 + 11 +14093.749 + 21 +3007.8124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14093.749 + 20 +3007.8124 + 11 +14187.499 + 21 +3031.2499 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14187.499 + 20 +3031.2499 + 11 +14281.249 + 21 +3070.3123 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14281.249 + 20 +3070.3123 + 11 +14374.999 + 21 +3124.9999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14374.999 + 20 +3124.9999 + 11 +14468.749 + 21 +3195.3124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14468.749 + 20 +3195.3124 + 11 +14562.499 + 21 +3281.2498 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14562.499 + 20 +3281.2498 + 11 +14656.249 + 21 +3382.8124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14656.249 + 20 +3382.8124 + 11 +14749.999 + 21 +3499.9999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14749.999 + 20 +3499.9999 + 11 +14843.749 + 21 +3632.8123 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14843.749 + 20 +3632.8123 + 11 +14937.499 + 21 +3781.2499 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14937.499 + 20 +3781.2499 + 11 +15031.249 + 21 +3945.3124 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15031.249 + 20 +3945.3124 + 11 +15124.999 + 21 +4124.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15124.999 + 20 +4124.9998 + 11 +15218.749 + 21 +4320.3121 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15218.749 + 20 +4320.3121 + 11 +15312.499 + 21 +4531.2495 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15312.499 + 20 +4531.2495 + 11 +15406.249 + 21 +4757.8113 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15406.249 + 20 +4757.8113 + 11 +15499.999 + 21 +4999.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12499.999 + 20 +2999.9998 + 11 +15499.999 + 21 +2999.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16500 + 20 +4999.9992 + 11 +16557.332 + 21 +5210.1891 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16557.332 + 20 +5210.1891 + 11 +16660.472 + 21 +5548.0472 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16660.472 + 20 +5548.0472 + 11 +16775.537 + 21 +5817.7429 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16775.537 + 20 +5817.7429 + 11 +16910.072 + 21 +5976.1329 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16910.072 + 20 +5976.1329 + 11 +16999.999 + 21 +5999.9985 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16999.999 + 20 +5999.9985 + 11 +17207.119 + 21 +5881.0232 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17207.119 + 20 +5881.0232 + 11 +17594.746 + 21 +5311.7706 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17594.746 + 20 +5311.7706 + 11 +17917.171 + 21 +4588.5306 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17917.171 + 20 +4588.5306 + 11 +18053.634 + 21 +4068.1928 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18053.634 + 20 +4068.1928 + 11 +17999.999 + 21 +3999.9997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17999.999 + 20 +3999.9997 + 11 +17929.572 + 21 +4054.5676 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17929.572 + 20 +4054.5676 + 11 +17767.895 + 21 +4260.5034 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17767.895 + 20 +4260.5034 + 11 +17606.905 + 21 +4548.1732 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17606.905 + 20 +4548.1732 + 11 +17506.652 + 21 +4847.9771 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17506.652 + 20 +4847.9771 + 11 +17499.998 + 21 +4999.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17499.998 + 20 +4999.9992 + 11 +17567.72 + 21 +5155.8343 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17567.72 + 20 +5155.8343 + 11 +17853.96 + 21 +5294.7591 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17853.96 + 20 +5294.7591 + 11 +18276.409 + 21 +5283.5835 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18276.409 + 20 +5283.5835 + 11 +18744.001 + 21 +5138.756 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18744.001 + 20 +5138.756 + 11 +18999.997 + 21 +4999.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18999.997 + 20 +4999.9992 + 11 +19170.537 + 21 +4873.5921 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19170.537 + 20 +4873.5921 + 11 +19406.016 + 21 +4625.4165 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19406.016 + 20 +4625.4165 + 11 +19544.379 + 21 +4364.704 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19544.379 + 20 +4364.704 + 11 +19558.879 + 21 +4121.3748 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19558.879 + 20 +4121.3748 + 11 +19499.999 + 21 +3999.9997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19499.999 + 20 +3999.9997 + 11 +19388.963 + 21 +3898.6981 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19388.963 + 20 +3898.6981 + 11 +19116.249 + 21 +3762.798 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19116.249 + 20 +3762.798 + 11 +18816.194 + 21 +3657.3249 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18816.194 + 20 +3657.3249 + 11 +18576.623 + 21 +3560.6143 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18576.623 + 20 +3560.6143 + 11 +18500 + 21 +3499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18500 + 20 +3499.9996 + 11 +18498.006 + 21 +3402.2519 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18498.006 + 20 +3402.2519 + 11 +18739.141 + 21 +3221.5395 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18739.141 + 20 +3221.5395 + 11 +19183.637 + 21 +3067.832 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19183.637 + 20 +3067.832 + 11 +19707.972 + 21 +2990.4598 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19707.972 + 20 +2990.4598 + 11 +20000 + 21 +2999.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20000 + 20 +2999.9998 + 11 +20231.985 + 21 +3050.2944 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20231.985 + 20 +3050.2944 + 11 +20560.194 + 21 +3220.9865 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20560.194 + 20 +3220.9865 + 11 +20799.246 + 21 +3477.5277 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20799.246 + 20 +3477.5277 + 11 +20951.104 + 21 +3796.1371 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20951.104 + 20 +3796.1371 + 11 +20999.999 + 21 +3999.9997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20999.999 + 20 +3999.9997 + 11 +21021.457 + 21 +4237.3554 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21021.457 + 20 +4237.3554 + 11 +20981.629 + 21 +4649.9699 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20981.629 + 20 +4649.9699 + 11 +20853.994 + 21 +5035.4017 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20853.994 + 20 +5035.4017 + 11 +20649.5 + 21 +5357.0657 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20649.5 + 20 +5357.0657 + 11 +20499.997 + 21 +5499.9981 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20499.997 + 20 +5499.9981 + 11 +20282.492 + 21 +5625.2397 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20282.492 + 20 +5625.2397 + 11 +19845.251 + 21 +5714.1053 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19845.251 + 20 +5714.1053 + 11 +19348.922 + 21 +5682.3389 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19348.922 + 20 +5682.3389 + 11 +18816.412 + 21 +5576.6957 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18816.412 + 20 +5576.6957 + 11 +18500 + 21 +5499.9981 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +11499.999 + 20 +8499.9992 + 11 +11606.311 + 21 +8676.4361 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +11606.311 + 20 +8676.4361 + 11 +11801.086 + 21 +8967.8039 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +11801.086 + 20 +8967.8039 + 11 +12027.758 + 21 +9223.5187 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12027.758 + 20 +9223.5187 + 11 +12306.506 + 21 +9421.0165 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12306.506 + 20 +9421.0165 + 11 +12499.999 + 21 +9499.9993 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12499.999 + 20 +9499.9993 + 11 +12746.15 + 21 +9551.7427 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12746.15 + 20 +9551.7427 + 11 +13202.847 + 21 +9548.3862 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13202.847 + 20 +9548.3862 + 11 +13623.891 + 21 +9428.0438 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13623.891 + 20 +9428.0438 + 11 +13920.282 + 21 +9190.9359 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13920.282 + 20 +9190.9359 + 11 +13999.999 + 21 +8999.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13999.999 + 20 +8999.9996 + 11 +13976.802 + 21 +8688.6436 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13976.802 + 20 +8688.6436 + 11 +13667.007 + 21 +8097.1634 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13667.007 + 20 +8097.1634 + 11 +13178.118 + 21 +7604.1433 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13178.118 + 20 +7604.1433 + 11 +12698.995 + 21 +7404.525 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12698.995 + 20 +7404.525 + 11 +12499.999 + 21 +7499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12499.999 + 20 +7499.9996 + 11 +12439.05 + 21 +7610.0163 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12439.05 + 20 +7610.0163 + 11 +12384.546 + 21 +7867.3649 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12384.546 + 20 +7867.3649 + 11 +12388.748 + 21 +8153.0378 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12388.748 + 20 +8153.0378 + 11 +12445.474 + 21 +8400.375 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12445.474 + 20 +8400.375 + 11 +12499.999 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12499.999 + 20 +8499.9992 + 11 +12615.534 + 21 +8567.0145 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12615.534 + 20 +8567.0145 + 11 +12893.139 + 21 +8480.7162 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +12893.139 + 20 +8480.7162 + 11 +13260.902 + 21 +8262.7217 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13260.902 + 20 +8262.7217 + 11 +13708.245 + 21 +8056.9854 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13708.245 + 20 +8056.9854 + 11 +13999.999 + 21 +8000 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +13999.999 + 20 +8000 + 11 +14309.955 + 21 +8015.118 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14309.955 + 20 +8015.118 + 11 +14836.432 + 21 +8163.1872 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14836.432 + 20 +8163.1872 + 11 +15265.8 + 21 +8363.8405 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15265.8 + 20 +8363.8405 + 11 +15496.805 + 21 +8498.6481 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15496.805 + 20 +8498.6481 + 11 +15499.999 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15499.999 + 20 +8499.9992 + 11 +15408.62 + 21 +8435.2417 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15408.62 + 20 +8435.2417 + 11 +15111.14 + 21 +8210.6789 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15111.14 + 20 +8210.6789 + 11 +14767.384 + 21 +7914.199 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14767.384 + 20 +7914.199 + 11 +14529.503 + 21 +7628.3677 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14529.503 + 20 +7628.3677 + 11 +14499.998 + 21 +7499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14499.998 + 20 +7499.9996 + 11 +14544.265 + 21 +7435.8007 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14544.265 + 20 +7435.8007 + 11 +14728.032 + 21 +7377.7112 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14728.032 + 20 +7377.7112 + 11 +15003.454 + 21 +7381.4586 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15003.454 + 20 +7381.4586 + 11 +15318.96 + 21 +7441.5271 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15318.96 + 20 +7441.5271 + 11 +15499.999 + 21 +7499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15499.999 + 20 +7499.9996 + 11 +15793.918 + 21 +7644.2966 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15793.918 + 20 +7644.2966 + 11 +16189.253 + 21 +7982.0965 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16189.253 + 20 +7982.0965 + 11 +16435.775 + 21 +8382.3477 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16435.775 + 20 +8382.3477 + 11 +16524.452 + 21 +8786.6557 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16524.452 + 20 +8786.6557 + 11 +16499.998 + 21 +8999.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16499.998 + 20 +8999.9996 + 11 +16391.654 + 21 +9226.8047 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16391.654 + 20 +9226.8047 + 11 +16031.864 + 21 +9529.1935 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16031.864 + 20 +9529.1935 + 11 +15507.848 + 21 +9747.4144 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +15507.848 + 20 +9747.4144 + 11 +14883.26 + 21 +9914.0899 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +14883.26 + 20 +9914.0899 + 11 +14499.998 + 21 +9999.9985 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23499.997 + 20 +11999.999 + 11 +29499.997 + 21 +11999.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +22028.039 + 11 +32944.213 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +18999.998 + 11 +40499.995 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40499.995 + 20 +18999.998 + 11 +40499.995 + 21 +22028.039 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40499.995 + 20 +22028.039 + 11 +32944.213 + 21 +22028.039 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32999.996 + 20 +22999.998 + 11 +40499.995 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32999.996 + 20 +22499.999 + 11 +32999.996 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +40499.995 + 20 +22499.999 + 11 +40499.995 + 21 +22999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +31999.995 + 20 +21999.997 + 11 +31999.995 + 21 +18999.998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32499.996 + 20 +21999.997 + 11 +31999.995 + 21 +21999.997 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32499.996 + 20 +18999.998 + 11 +31999.995 + 21 +18999.998 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32940.692 + 20 +12994.732 + 11 +32940.692 + 21 +15994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32940.692 + 20 +15994.732 + 11 +40440.691 + 21 +15994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40440.691 + 20 +15994.732 + 11 +40440.691 + 21 +12994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40440.691 + 20 +12994.732 + 11 +32940.692 + 21 +12994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32940.692 + 20 +16999.998 + 11 +40440.691 + 21 +16999.998 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32940.692 + 20 +16499.999 + 11 +32940.692 + 21 +16999.998 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +40440.691 + 20 +16499.999 + 11 +40440.691 + 21 +16999.998 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +31999.995 + 20 +15994.732 + 11 +31999.995 + 21 +12994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32499.996 + 20 +15994.732 + 11 +31999.995 + 21 +15994.732 + 0 +LINE + 8 +1-0 + 6 +CONTINUOUS + 62 + 7 + 10 +32499.996 + 20 +12994.732 + 11 +31999.995 + 21 +12994.732 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +11528.04 + 11 +32944.213 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +8499.9992 + 11 +40499.995 + 21 +8499.9992 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40499.995 + 20 +8499.9992 + 11 +40499.995 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +40499.995 + 20 +11528.04 + 11 +32944.213 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +39612.691 + 20 +8499.9992 + 11 +40499.995 + 21 +9387.3035 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +38198.478 + 20 +8499.9992 + 11 +40499.995 + 21 +10801.517 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +36784.266 + 20 +8499.9992 + 11 +39812.306 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +35370.053 + 20 +8499.9992 + 11 +38398.093 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +33955.838 + 20 +8499.9992 + 11 +36983.88 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +8902.5862 + 11 +35569.665 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32944.213 + 20 +10316.798 + 11 +34155.453 + 21 +11528.04 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21999.997 + 20 +4499.9991 + 11 +22124.796 + 21 +4485.2554 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22124.796 + 20 +4485.2554 + 11 +22230.329 + 21 +4485.2554 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22230.329 + 20 +4485.2554 + 11 +22335.867 + 21 +4617.1767 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22335.867 + 20 +4617.1767 + 11 +22520.556 + 21 +4775.481 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22520.556 + 20 +4775.481 + 11 +22678.863 + 21 +4854.6333 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22678.863 + 20 +4854.6333 + 11 +22758.014 + 21 +4986.5546 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22758.014 + 20 +4986.5546 + 11 +22810.783 + 21 +5144.8591 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22810.783 + 20 +5144.8591 + 11 +22889.934 + 21 +5276.7801 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22889.934 + 20 +5276.7801 + 11 +22995.472 + 21 +5329.5479 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22995.472 + 20 +5329.5479 + 11 +23101.01 + 21 +5408.7002 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23101.01 + 20 +5408.7002 + 11 +23206.543 + 21 +5408.7002 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23206.543 + 20 +5408.7002 + 11 +23391.232 + 21 +5461.4692 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23391.232 + 20 +5461.4692 + 11 +23602.308 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23602.308 + 20 +5487.8537 + 11 +23786.997 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23786.997 + 20 +5487.8537 + 11 +23945.304 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23945.304 + 20 +5487.8537 + 11 +24129.993 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24129.993 + 20 +5487.8537 + 11 +24288.296 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24288.296 + 20 +5487.8537 + 11 +24420.216 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24420.216 + 20 +5487.8537 + 11 +24552.136 + 21 +5487.8537 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24552.136 + 20 +5487.8537 + 11 +24684.061 + 21 +5382.3169 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24684.061 + 20 +5382.3169 + 11 +24815.981 + 21 +5250.3956 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24815.981 + 20 +5250.3956 + 11 +24895.132 + 21 +5092.0914 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24895.132 + 20 +5092.0914 + 11 +24974.283 + 21 +4933.7856 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24974.283 + 20 +4933.7856 + 11 +25027.052 + 21 +4775.481 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25027.052 + 20 +4775.481 + 11 +25079.821 + 21 +4643.56 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25079.821 + 20 +4643.56 + 11 +25106.208 + 21 +4458.8709 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25106.208 + 20 +4458.8709 + 11 +25132.59 + 21 +4326.9509 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25132.59 + 20 +4326.9509 + 11 +25132.59 + 21 +4168.6454 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25132.59 + 20 +4168.6454 + 11 +25053.439 + 21 +3983.9563 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25053.439 + 20 +3983.9563 + 11 +24947.901 + 21 +3931.1879 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24947.901 + 20 +3931.1879 + 11 +24789.594 + 21 +3825.6511 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24789.594 + 20 +3825.6511 + 11 +24604.905 + 21 +3799.2672 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24604.905 + 20 +3799.2672 + 11 +24472.985 + 21 +3772.8827 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24472.985 + 20 +3772.8827 + 11 +24261.914 + 21 +3746.4988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24261.914 + 20 +3746.4988 + 11 +24077.224 + 21 +3746.4988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24077.224 + 20 +3746.4988 + 11 +23655.077 + 21 +3746.4988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23655.077 + 20 +3746.4988 + 11 +23496.77 + 21 +3746.4988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23496.77 + 20 +3746.4988 + 11 +23417.619 + 21 +3904.8034 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23417.619 + 20 +3904.8034 + 11 +23364.85 + 21 +4063.1086 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23364.85 + 20 +4063.1086 + 11 +23338.468 + 21 +4274.1819 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23338.468 + 20 +4274.1819 + 11 +23338.468 + 21 +4511.6399 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23338.468 + 20 +4511.6399 + 11 +23364.85 + 21 +4643.56 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23364.85 + 20 +4643.56 + 11 +23470.388 + 21 +4775.481 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23470.388 + 20 +4775.481 + 11 +23575.921 + 21 +4881.0178 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23575.921 + 20 +4881.0178 + 11 +23734.228 + 21 +4960.1701 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23734.228 + 20 +4960.1701 + 11 +23866.148 + 21 +5039.3224 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23866.148 + 20 +5039.3224 + 11 +24050.837 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24050.837 + 20 +5065.7069 + 11 +24182.758 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24182.758 + 20 +5065.7069 + 11 +24314.683 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24314.683 + 20 +5065.7069 + 11 +24472.985 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24472.985 + 20 +5065.7069 + 11 +24604.905 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24604.905 + 20 +5065.7069 + 11 +24710.443 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24710.443 + 20 +5065.7069 + 11 +24842.363 + 21 +5065.7069 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24842.363 + 20 +5065.7069 + 11 +25000.67 + 21 +4986.5546 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25000.67 + 20 +4986.5546 + 11 +25158.972 + 21 +4801.8655 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25158.972 + 20 +4801.8655 + 11 +25290.897 + 21 +4722.7132 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25290.897 + 20 +4722.7132 + 11 +25396.43 + 21 +4590.7922 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25396.43 + 20 +4590.7922 + 11 +25475.586 + 21 +4458.8709 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25475.586 + 20 +4458.8709 + 11 +25607.506 + 21 +4300.5664 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25607.506 + 20 +4300.5664 + 11 +25739.426 + 21 +4115.877 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25739.426 + 20 +4115.877 + 11 +25792.195 + 21 +3957.5718 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25792.195 + 20 +3957.5718 + 11 +25844.964 + 21 +3746.4988 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25844.964 + 20 +3746.4988 + 11 +25871.346 + 21 +3588.1936 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25871.346 + 20 +3588.1936 + 11 +25871.346 + 21 +3456.273 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25871.346 + 20 +3456.273 + 11 +25792.195 + 21 +3324.3517 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25792.195 + 20 +3324.3517 + 11 +25660.275 + 21 +3218.8155 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25660.275 + 20 +3218.8155 + 11 +25528.35 + 21 +3166.0471 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25528.35 + 20 +3166.0471 + 11 +25396.43 + 21 +3113.2787 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25396.43 + 20 +3113.2787 + 11 +25290.897 + 21 +3113.2787 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25290.897 + 20 +3113.2787 + 11 +25185.359 + 21 +3113.2787 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25185.359 + 20 +3113.2787 + 11 +25132.59 + 21 +3271.5839 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25132.59 + 20 +3271.5839 + 11 +25132.59 + 21 +3403.5046 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25132.59 + 20 +3403.5046 + 11 +25158.972 + 21 +3535.4252 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25158.972 + 20 +3535.4252 + 11 +25211.741 + 21 +3667.3459 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25211.741 + 20 +3667.3459 + 11 +25290.897 + 21 +3799.2672 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25290.897 + 20 +3799.2672 + 11 +25396.43 + 21 +3904.8034 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25396.43 + 20 +3904.8034 + 11 +25554.737 + 21 +3983.9563 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25554.737 + 20 +3983.9563 + 11 +25686.657 + 21 +4063.1086 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25686.657 + 20 +4063.1086 + 11 +25844.964 + 21 +4115.877 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25844.964 + 20 +4115.877 + 11 +25950.497 + 21 +4142.2615 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25950.497 + 20 +4142.2615 + 11 +26056.035 + 21 +4195.0296 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26056.035 + 20 +4195.0296 + 11 +26187.955 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26187.955 + 20 +4221.4141 + 11 +26346.262 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26346.262 + 20 +4221.4141 + 11 +26451.8 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26451.8 + 20 +4221.4141 + 11 +26557.333 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26557.333 + 20 +4221.4141 + 11 +26662.871 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26662.871 + 20 +4221.4141 + 11 +26768.41 + 21 +4221.4141 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26768.41 + 20 +4221.4141 + 11 +26873.943 + 21 +4195.0296 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26873.943 + 20 +4195.0296 + 11 +26979.481 + 21 +4142.2615 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26979.481 + 20 +4142.2615 + 11 +27085.019 + 21 +4063.1086 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27085.019 + 20 +4063.1086 + 11 +27190.557 + 21 +3983.9563 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27190.557 + 20 +3983.9563 + 11 +27216.939 + 21 +3852.0356 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27216.939 + 20 +3852.0356 + 11 +27190.557 + 21 +3720.1143 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27190.557 + 20 +3720.1143 + 11 +27085.019 + 21 +3588.1936 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27085.019 + 20 +3588.1936 + 11 +26979.481 + 21 +3535.4252 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26979.481 + 20 +3535.4252 + 11 +26999.998 + 21 +3499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +35499.996 + 20 +5499.9993 + 11 +36929.575 + 21 +4070.4214 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37141.708 + 20 +4158.2894 + 11 +37141.708 + 21 +4950.7828 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37353.84 + 20 +5038.6509 + 11 +37966.254 + 21 +4426.2355 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37966.254 + 20 +4001.9712 + 11 +37176.416 + 21 +3212.1318 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37264.284 + 20 +2999.9998 + 11 +38199.995 + 21 +2999.9998 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +38499.996 + 20 +3299.9999 + 11 +38499.996 + 21 +3699.9984 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +38712.129 + 20 +4212.1304 + 11 +39287.864 + 21 +4787.8675 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +39199.996 + 20 +4999.9995 + 11 +36299.999 + 21 +4999.9995 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +35999.998 + 20 +4699.9995 + 11 +35999.998 + 21 +3799.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +36299.999 + 20 +3499.9996 + 11 +39499.997 + 21 +3499.9996 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +41999.998 + 20 +0 + 11 +41999.998 + 21 +29837.836 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +41999.998 + 20 +29837.836 + 11 +0 + 21 +29837.836 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +0 + 20 +29837.836 + 11 +0 + 21 +0 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +0 + 20 +0 + 11 +41999.998 + 21 +0 + 0 +CIRCLE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19999.998 + 20 +19999.998 + 40 +2999.9998 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24999.997 + 20 +19999.998 + 40 +2999.9998 + 50 +0 + 51 +90 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +19999.998 + 40 +4301.1642 + 50 +0 + 51 +90 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 7 + 10 +24999.997 + 20 +19999.998 + 40 +1802.7759 + 50 +0 + 51 +90 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +16999.998 + 20 +11999.999 + 11 +17045.575 + 21 +11739.527 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17045.575 + 20 +11739.527 + 11 +17180.92 + 21 +11486.969 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17180.92 + 20 +11486.969 + 11 +17401.922 + 21 +11249.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17401.922 + 20 +11249.999 + 11 +17701.865 + 21 +11035.818 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17701.865 + 20 +11035.818 + 11 +18071.635 + 21 +10850.932 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18071.635 + 20 +10850.932 + 11 +18499.998 + 21 +10700.961 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18499.998 + 20 +10700.961 + 11 +18973.937 + 21 +10590.46 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18973.937 + 20 +10590.46 + 11 +19479.053 + 21 +10522.787 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19479.053 + 20 +10522.787 + 11 +19999.998 + 21 +10499.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19999.998 + 20 +10499.999 + 11 +20520.942 + 21 +10522.787 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20520.942 + 20 +10522.787 + 11 +21026.058 + 21 +10590.46 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21026.058 + 20 +10590.46 + 11 +21499.998 + 21 +10700.961 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21499.998 + 20 +10700.961 + 11 +21928.361 + 21 +10850.932 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21928.361 + 20 +10850.932 + 11 +22298.131 + 21 +11035.818 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22298.131 + 20 +11035.818 + 11 +22598.074 + 21 +11249.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22598.074 + 20 +11249.999 + 11 +22819.076 + 21 +11486.969 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22819.076 + 20 +11486.969 + 11 +22954.421 + 21 +11739.527 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22954.421 + 20 +11739.527 + 11 +22999.998 + 21 +11999.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22999.998 + 20 +11999.999 + 11 +22954.421 + 21 +12260.471 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22954.421 + 20 +12260.471 + 11 +22819.076 + 21 +12513.029 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22819.076 + 20 +12513.029 + 11 +22598.074 + 21 +12749.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22598.074 + 20 +12749.999 + 11 +22298.131 + 21 +12964.18 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +22298.131 + 20 +12964.18 + 11 +21928.361 + 21 +13149.066 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21928.361 + 20 +13149.066 + 11 +21499.998 + 21 +13299.037 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21499.998 + 20 +13299.037 + 11 +21026.058 + 21 +13409.538 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +21026.058 + 20 +13409.538 + 11 +20520.942 + 21 +13477.211 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +20520.942 + 20 +13477.211 + 11 +19999.998 + 21 +13499.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19999.998 + 20 +13499.999 + 11 +19479.053 + 21 +13477.211 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +19479.053 + 20 +13477.211 + 11 +18973.937 + 21 +13409.538 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18973.937 + 20 +13409.538 + 11 +18499.998 + 21 +13299.037 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18499.998 + 20 +13299.037 + 11 +18071.635 + 21 +13149.066 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +18071.635 + 20 +13149.066 + 11 +17701.865 + 21 +12964.18 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17701.865 + 20 +12964.18 + 11 +17401.922 + 21 +12749.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17401.922 + 20 +12749.999 + 11 +17180.92 + 21 +12513.029 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17180.92 + 20 +12513.029 + 11 +17045.575 + 21 +12260.471 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +17045.575 + 20 +12260.471 + 11 +16999.998 + 21 +11999.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29499.997 + 20 +11999.999 + 11 +29454.42 + 21 +12260.471 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29454.42 + 20 +12260.471 + 11 +29319.074 + 21 +12513.029 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29319.074 + 20 +12513.029 + 11 +29098.073 + 21 +12749.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29098.073 + 20 +12749.999 + 11 +28798.13 + 21 +12964.18 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28798.13 + 20 +12964.18 + 11 +28428.359 + 21 +13149.066 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +28428.359 + 20 +13149.066 + 11 +27999.997 + 21 +13299.037 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27999.997 + 20 +13299.037 + 11 +27526.057 + 21 +13409.538 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27526.057 + 20 +13409.538 + 11 +27020.941 + 21 +13477.211 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +27020.941 + 20 +13477.211 + 11 +26499.997 + 21 +13499.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +26499.997 + 20 +13499.999 + 11 +25979.052 + 21 +13477.211 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25979.052 + 20 +13477.211 + 11 +25473.936 + 21 +13409.538 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +25473.936 + 20 +13409.538 + 11 +24999.997 + 21 +13299.037 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24999.997 + 20 +13299.037 + 11 +24571.634 + 21 +13149.066 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24571.634 + 20 +13149.066 + 11 +24201.863 + 21 +12964.18 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +24201.863 + 20 +12964.18 + 11 +23901.921 + 21 +12749.999 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23901.921 + 20 +12749.999 + 11 +23680.919 + 21 +12513.029 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23680.919 + 20 +12513.029 + 11 +23545.574 + 21 +12260.471 + 0 +LINE + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +23545.574 + 20 +12260.471 + 11 +23499.997 + 21 +11999.999 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29083.333 + 20 +5083.332 + 40 +1086.5331 + 50 +184.39868 + 51 +327.52877 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +30916.664 + 20 +3916.6653 + 40 +1086.5333 + 50 +4.3987274 + 51 +147.52876 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31249.997 + 20 +3942.3069 + 40 +752.21563 + 50 +175.60128 + 51 +4.3987121 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +32336.953 + 20 +3858.6945 + 40 +1842.383 + 50 +117.01853 + 51 +175.60128 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +31837.716 + 20 +4837.7183 + 40 +743.41837 + 50 +332.98152 + 51 +117.01847 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +33520.267 + 20 +3979.7316 + 40 +1145.2631 + 50 +152.9815 + 51 +117.01858 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +29536.068 + 20 +4446.5169 + 40 +1054.0996 + 50 +91.960937 + 51 +296.11151 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37017.443 + 20 +4158.2894 + 40 +124.26427 + 50 +224.99989 + 51 +0 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37265.972 + 20 +4950.7828 + 40 +124.26439 + 50 +44.999893 + 51 +180 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37754.121 + 20 +4214.1035 + 40 +300.00062 + 50 +315.00004 + 51 +44.999923 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +37264.284 + 20 +3124.2635 + 40 +124.26365 + 50 +135 + 51 +270 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +38199.995 + 20 +3299.9999 + 40 +300.00097 + 50 +270 + 51 +0 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +39224.26 + 20 +3699.9984 + 40 +724.26344 + 50 +134.99995 + 51 +180 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +39199.996 + 20 +4875.7359 + 40 +124.26365 + 50 +315 + 51 +90 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +36299.999 + 20 +4699.9995 + 40 +300.00097 + 50 +90 + 51 +180 + 0 +ARC + 8 +0-0 + 6 +CONTINUOUS + 62 + 4 + 10 +36299.999 + 20 +3799.9996 + 40 +300.00004 + 50 +180 + 51 +270 + 0 +TEXT + 8 +0-0 + 10 +500.00039 + 20 +29000 + 40 +200 + 41 +1 + 50 +0 + 1 +F2 2.0~2.0 •¶ŽšŠÔ 1.0 + 0 +TEXT + 8 +0-0 + 10 +500.00039 + 20 +28499.998 + 40 +400 + 41 +1 + 50 +0 + 1 +F3 4.0~4.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +500.00039 + 20 +27999.997 + 40 +400 + 41 +1 + 50 +0 + 1 +F4 4.0~4.0 •¶ŽšŠÔ 2.0 + 0 +TEXT + 8 +0-0 + 10 +499.99977 + 20 +27249.997 + 40 +600 + 41 +1 + 50 +0 + 1 +F5 6.0~6.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +499.99996 + 20 +21999.997 + 40 +1000 + 41 +1 + 50 +0 + 1 +F10 10~10 •¶ŽšŠÔ 5.0 + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +28499.998 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.1 ŽÀü + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +27999.997 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.2 “_ü + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +27500 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.3 “_ü(2) + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +26999.998 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.4 “_ü(3) + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +26499.999 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.5 ˆê“_½ü + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +26000 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.6 ˆê“_½ü(2) + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +25499.998 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.1 “ñ“_½ü + 0 +TEXT + 8 +0-0 + 10 +17499.998 + 20 +24999.999 + 40 +400 + 41 +1 + 50 +0 + 1 +Pen.1 “ñ“_½ü(2) + 0 +TEXT + 8 +0-0 + 10 +500.00039 + 20 +29249.998 + 40 +200 + 41 +1 + 50 +0 + 1 +F1 2.0~2.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +499.99996 + 20 +26499.997 + 40 +600 + 41 +1 + 50 +0 + 1 +F6 6.0~6.0 •¶ŽšŠÔ 2.0 + 0 +TEXT + 8 +0-0 + 10 +499.99996 + 20 +24499.998 + 40 +800 + 41 +1 + 50 +0 + 1 +F8 8.0~8.0 •¶ŽšŠÔ 4.0 + 0 +TEXT + 8 +0-0 + 10 +499.99977 + 20 +25499.998 + 40 +800 + 41 +1 + 50 +0 + 1 +F7 8.0~8.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +499.99996 + 20 +23249.998 + 40 +1000 + 41 +1 + 50 +0 + 1 +F9 10~10 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +3500.0002 + 20 +20499.998 + 40 +1000 + 41 +1 + 50 +270 + 1 +F10 10~10 •¶ŽšŠÔ 5.0 + 0 +TEXT + 8 +0-0 + 10 +4750.0018 + 20 +20499.998 + 40 +1000 + 41 +1 + 50 +270 + 1 +F9 10~10 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +7000.0005 + 20 +20499.998 + 40 +800 + 41 +1 + 50 +270 + 1 +F7 8.0~8.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +5999.9997 + 20 +20500.001 + 40 +800 + 41 +1 + 50 +270 + 1 +F3 4.0~4.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +7999.9988 + 20 +20499.998 + 40 +600 + 41 +1 + 50 +270 + 1 +F2 2.0~2.0 •¶ŽšŠÔ 1.0 + 0 +TEXT + 8 +0-0 + 10 +8749.9987 + 20 +20500.001 + 40 +600 + 41 +1 + 50 +270 + 1 +F3 4.0~4.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +10000 + 20 +20499.998 + 40 +400 + 41 +1 + 50 +270 + 1 +F2 2.0~2.0 •¶ŽšŠÔ 1.0 + 0 +TEXT + 8 +0-0 + 10 +9499.9987 + 20 +20499.998 + 40 +400 + 41 +1 + 50 +270 + 1 +F4 4.0~4.0 •¶ŽšŠÔ 2.0 + 0 +TEXT + 8 +0-0 + 10 +10750 + 20 +20499.996 + 40 +200 + 41 +1 + 50 +270 + 1 +F2 2.0~2.0 •¶ŽšŠÔ 1.0 + 0 +TEXT + 8 +0-0 + 10 +10500.002 + 20 +20500.001 + 40 +200 + 41 +1 + 50 +270 + 1 +F2 2.0~2.0 •¶ŽšŠÔ 1.0 + 0 +TEXT + 8 +0-0 + 10 +19299.998 + 20 +20049.998 + 40 +400 + 41 +1 + 50 +0 + 1 +ƒÓ6,000 + 0 +TEXT + 8 +0-0 + 10 +19949.998 + 20 +20899.998 + 40 +400 + 41 +1 + 50 +90 + 1 +R3,000 + 0 +TEXT + 8 +0-0 + 10 +22404.163 + 20 +22474.871 + 40 +400 + 41 +1 + 50 +45 + 1 +ƒÓ6,000 + 0 +TEXT + 8 +0-0 + 10 +22474.869 + 20 +17595.835 + 40 +400 + 41 +1 + 50 +315 + 1 +R3,000 + 0 +TEXT + 8 +0-0 + 10 +27581.761 + 20 +23571.71 + 40 +400 + 41 +1 + 50 +315 + 1 +4,712.4 + 0 +TEXT + 8 +0-0 + 10 +26097.974 + 20 +21522.238 + 40 +400 + 41 +1 + 50 +315 + 1 +90ß + 0 +TEXT + 8 +0-0 + 10 +25999.998 + 20 +19049.998 + 40 +400 + 41 +1 + 50 +0 + 1 +3,000 + 0 +TEXT + 8 +0-0 + 10 +23949.998 + 20 +20999.999 + 40 +400 + 41 +1 + 50 +90 + 1 +3,000 + 0 +TEXT + 8 +0-0 + 10 +24999.997 + 20 +14999.999 + 40 +400 + 41 +1 + 50 +45.000015 + 1 +F3 4.0~4.0 •¶ŽšŠÔ 0.0 + 0 +TEXT + 8 +0-0 + 10 +26666.724 + 20 +15737.435 + 40 +400 + 41 +1 + 50 +45 + 1 +4,400 + 0 +TEXT + 8 +0-0 + 10 +19599.998 + 20 +9299.9993 + 40 +400 + 41 +1 + 50 +0 + 1 +‘ȉ~ + 0 +TEXT + 8 +0-0 + 10 +25899.997 + 20 +11299.999 + 40 +400 + 41 +1 + 50 +0 + 1 +”¼‘ȉ~ + 0 +TEXT + 8 +0-0 + 10 +19499.997 + 20 +12049.999 + 40 +400 + 41 +1 + 50 +0 + 1 +6,000 + 0 +TEXT + 8 +0-0 + 10 +19949.998 + 20 +13949.999 + 40 +400 + 41 +1 + 50 +90 + 1 +ƒÓ3,000 + 0 +TEXT + 8 +0-0 + 10 +26499.997 + 20 +7799.9994 + 40 +400 + 41 +1 + 50 +0 + 1 +ƒTƒCƒ“‹Èü + 0 +TEXT + 8 +0-0 + 10 +13300 + 20 +2299.9997 + 40 +400 + 41 +1 + 50 +0 + 1 +2ŽŸ‹Èü + 0 +TEXT + 8 +0-0 + 10 +17599.999 + 20 +2299.9997 + 40 +400 + 41 +1 + 50 +0 + 1 +ƒXƒvƒ‰ƒCƒ“‹Èü + 0 +TEXT + 8 +0-0 + 10 +12999.999 + 20 +6299.9994 + 40 +400 + 41 +1 + 50 +0 + 1 +ƒxƒWƒF‹Èü + 0 +TEXT + 8 +0-0 + 10 +28499.998 + 20 +27999.997 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒOƒ‹[ƒv0 ƒŒƒCƒ„0‚Ì•¶Žš—ñ + 0 +TEXT + 8 +0x1 + 10 +28499.998 + 20 +26999.998 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒOƒ‹[ƒv0 ƒŒƒCƒ„1 “Ç‚ÝŽæ‚è•s‰ÂƒŒƒCƒ„‚Ì•¶Žš—ñ + 0 +TEXT + 8 +0-2 + 10 +28499.998 + 20 +25999.998 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒOƒ‹[ƒv0 ƒŒƒCƒ„2 ”ñ•\Ž¦ƒŒƒCƒ„‚Ì•¶Žš—ñ + 0 +TEXT + 8 +0-0 + 10 +34799.994 + 20 +19699.999 + 40 +600 + 41 +1 + 50 +0 + 1 +1/100‚ÌŽlŠpŒ` + 0 +TEXT + 8 +0-0 + 10 +36249.996 + 20 +23049.998 + 40 +400 + 41 +1 + 50 +0 + 1 +7,500 + 0 +TEXT + 8 +0-0 + 10 +31949.995 + 20 +19999.998 + 40 +400 + 41 +1 + 50 +90 + 1 +3,000 + 0 +TEXT + 8 +1-0 + 10 +36090.692 + 20 +17049.998 + 40 +400 + 41 +1 + 50 +0 + 1 +15,000 + 0 +TEXT + 8 +1-0 + 10 +31949.995 + 20 +13994.731 + 40 +400 + 41 +1 + 50 +90 + 1 +6,000 + 0 +TEXT + 8 +1-0 + 10 +34799.994 + 20 +13700 + 40 +600 + 41 +1 + 50 +0 + 1 +1/200‚ÌŽlŠpŒ` + 0 +TEXT + 8 +0-0 + 10 +35249.993 + 20 +9700 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒnƒbƒ`ƒ“ƒO + 0 +TEXT + 8 +1-0 + 10 +34199.992 + 20 +14699.999 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒOƒ‹[ƒv1 ƒŒƒCƒ„0 + 0 +TEXT + 8 +0-0 + 10 +23699.997 + 20 +2299.9997 + 40 +400 + 41 +1 + 50 +0 + 1 +Žè‘‚«ü + 0 +TEXT + 8 +0-0 + 10 +30699.998 + 20 +2299.9994 + 40 +400 + 41 +1 + 50 +0 + 1 +˜A‘±‰~ŒÊ + 0 +TEXT + 8 +0-0 + 10 +37099.997 + 20 +2299.9997 + 40 +400 + 41 +1 + 50 +0 + 1 +˜Aü + 0 +TEXT + 8 +0-0 + 10 +34199.992 + 20 +20699.999 + 40 +600 + 41 +1 + 50 +0 + 1 +ƒOƒ‹[ƒv0 ƒŒƒCƒ„0 + 0 +TEXT + 8 +0-0 + 10 +19499.997 + 20 +8299.9991 + 40 +400 + 41 +1 + 50 +0 + 1 +“_~5 + 0 +TEXT + 8 +0-0 + 10 +0 + 20 +0 + 40 +1000 + 41 +1 + 50 +0 + 1 +A3 1/100 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +29301.161 + 20 +19999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +24999.997 + 20 +24301.162 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +26802.774 + 20 +19999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +24999.997 + 20 +21802.773 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +24999.997 + 20 +18999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +27999.997 + 20 +18999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +23999.998 + 20 +22999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +23999.998 + 20 +19999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +25499.998 + 20 +14499.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +28611.267 + 20 +17611.268 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +16999.998 + 20 +11999.999 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +22999.998 + 20 +11999.999 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +18999.998 + 20 +7999.9994 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +19499.999 + 20 +7999.9994 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +19999.999 + 20 +7999.9994 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +20499.998 + 20 +7999.9994 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +20999.999 + 20 +7999.9994 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +32999.996 + 20 +22999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +40499.995 + 20 +22999.998 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +31999.995 + 20 +21999.997 + 0 +POINT + 8 +0-0 + 62 + 7 + 10 +31999.995 + 20 +18999.998 + 0 +POINT + 8 +1-0 + 62 + 7 + 10 +32940.692 + 20 +16999.998 + 0 +POINT + 8 +1-0 + 62 + 7 + 10 +40440.691 + 20 +16999.998 + 0 +POINT + 8 +1-0 + 62 + 7 + 10 +31999.995 + 20 +15994.732 + 0 +POINT + 8 +1-0 + 62 + 7 + 10 +31999.995 + 20 +12994.732 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test.eps b/share/extensions/tests/data/io/test.eps new file mode 100644 index 0000000..a2bbae9 --- /dev/null +++ b/share/extensions/tests/data/io/test.eps @@ -0,0 +1,83 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: cairo 1.15.10 (http://cairographics.org) +%%CreationDate: Fri Apr 26 10:51:47 2019 +%%Pages: 1 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%BoundingBox: 0 0 94 98 +%%EndComments +%%BeginProlog +50 dict begin +/q { gsave } bind def +/Q { grestore } bind def +/cm { 6 array astore concat } bind def +/w { setlinewidth } bind def +/J { setlinecap } bind def +/j { setlinejoin } bind def +/M { setmiterlimit } bind def +/d { setdash } bind def +/m { moveto } bind def +/l { lineto } bind def +/c { curveto } bind def +/h { closepath } bind def +/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto + 0 exch rlineto 0 rlineto closepath } bind def +/S { stroke } bind def +/f { fill } bind def +/f* { eofill } bind def +/n { newpath } bind def +/W { clip } bind def +/W* { eoclip } bind def +/BT { } bind def +/ET { } bind def +/BDC { mark 3 1 roll /BDC pdfmark } bind def +/EMC { mark /EMC pdfmark } bind def +/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def +/Tj { show currentpoint cairo_store_point } bind def +/TJ { + { + dup + type /stringtype eq + { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse + } forall + currentpoint cairo_store_point +} bind def +/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore + cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def +/Tf { pop /cairo_font exch def /cairo_font_matrix where + { pop cairo_selectfont } if } bind def +/Td { matrix translate cairo_font_matrix matrix concatmatrix dup + /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point + /cairo_font where { pop cairo_selectfont } if } bind def +/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def + cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def +/g { setgray } bind def +/rg { setrgbcolor } bind def +/d1 { setcachedevice } bind def +/cairo_data_source { + CairoDataIndex CairoData length lt + { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } + { () } ifelse +} def +/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def +/cairo_image { image cairo_flush_ascii85_file } def +/cairo_imagemask { imagemask cairo_flush_ascii85_file } def +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%PageBoundingBox: 0 0 94 98 +%%EndPageSetup +q 0 0 94 98 rectclip +1 0 0 -1 0 98 cm q +0.652941 0.801961 0.511765 rg +1.641 0 m 91.734 0 l 92.645 0 93.375 0.73 93.375 1.641 c 93.375 95.625 +l 93.375 96.535 92.645 97.266 91.734 97.266 c 1.641 97.266 l 0.73 97.266 + 0 96.535 0 95.625 c 0 1.641 l 0 0.73 0.73 0 1.641 0 c h +1.641 0 m f +Q Q +showpage +%%Trailer +end +%%EOF diff --git a/share/extensions/tests/data/io/test.fig b/share/extensions/tests/data/io/test.fig new file mode 100644 index 0000000..4925068 --- /dev/null +++ b/share/extensions/tests/data/io/test.fig @@ -0,0 +1,15 @@ +#FIG 3.2 Produced by xfig version 3.2.6a +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2700 3285 587 587 2700 3285 3285 3240 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1890 2565 4950 2565 4950 5175 1890 5175 1890 2565 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 + 5220 4320 5220 2610 6705 2610 6705 4320 5220 4320 +4 0 0 50 -1 0 12 0.0000 4 165 1260 2520 1890 Hello Inkscape\001 diff --git a/share/extensions/tests/data/io/test.hpgl b/share/extensions/tests/data/io/test.hpgl new file mode 100644 index 0000000..fc737c8 --- /dev/null +++ b/share/extensions/tests/data/io/test.hpgl @@ -0,0 +1 @@ +IN;SP1;PU0,0;PD0,90;PU1543,280;PD1538,279,1534,275,1533,272,1053,358,1054,352,1056,349,713,2,711,7,711,12,714,17,718,19,719,19,653,502,648,500,645,497,210,716,213,720,218,722,223,720,227,717,227,716,666,928,663,932,659,934,733,1416,737,1414,741,1409,741,1404,738,1399,1076,1047,1078,1052,1079,1056,1560,1135,1559,1129,1556,1125,1551,1123,1546,1124,1545,1124,1315,694,1320,693,1324,694,1548,261,1543,260,1537,262,1534,266,1533,271,1533,272,1494,279;PU4234,3332;PD4234,3326,4237,3322,4242,3320,4244,3320,4246,3275,4247,3275,4252,3222,4262,3155,4278,3075,4279,3075,4302,2985,4303,2986,4318,2938,4318,2939,4336,2890,4357,2841,4380,2792,4381,2792,4407,2742,4408,2743,4437,2694,4438,2694,4471,2646,4508,2599,4509,2599,4549,2553,4550,2554,4595,2510,4595,2511,4644,2469,4645,2470,4698,2431,4699,2432,4757,2396,4757,2397,4820,2365,4821,2366,4889,2337,4889,2338,4962,2314,4962,2315,5041,2295,5041,2296,5126,2282,5126,2283,5216,2274,5312,2271,5312,2272,5405,2275,5405,2276,5487,2285,5523,2292,5557,2300,5557,2301,5588,2310,5617,2320,5617,2321,5644,2332,5644,2333,5668,2346,5690,2360,5690,2361,5710,2375,5710,2376,5728,2391,5727,2392,5744,2408,5743,2409,5758,2426,5758,2427,5771,2445,5770,2446,5792,2484,5791,2485,5807,2526,5806,2527,5818,2571,5817,2571,5825,2616,5824,2616,5829,2664,5828,2664,5831,2712,5830,2712,5831,2811,5832,2910,5833,2910,5835,2958,5836,2958,5840,3005,5841,3005,5849,3051,5850,3050,5862,3094,5863,3094,5879,3135,5880,3135,5902,3173,5903,3173,5916,3191,5917,3190,5932,3208,5932,3207,5949,3224,5950,3223,5968,3239,5968,3238,5989,3253,5989,3252,6012,3266,6012,3265,6037,3278,6037,3277,6064,3288,6093,3298,6125,3307,6125,3306,6159,3314,6159,3313,6196,3320,6196,3319,6277,3328,6277,3327,6370,3330,6466,3327,6466,3326,6557,3317,6556,3316,6641,3302,6641,3301,6719,3282,6719,3281,6792,3257,6860,3229,6860,3228,6923,3196,6923,3195,6981,3159,6980,3159,7034,3120,7033,3119,7082,3078,7127,3034,7126,3033,7167,2988,7166,2987,7203,2940,7236,2891,7235,2891,7265,2842,7291,2792,7314,2742,7313,2742,7334,2693,7333,2693,7351,2644,7366,2597,7365,2597,7389,2507,7388,2507,7404,2427,7413,2359,7418,2307,7417,2307,7419,2262;PU11,3320;PD16,3322,17,3323,1076,2265,1078,2269,1078,2275,1076,2279,2134,3337,2137,3332,2137,3327,2134,3323,3192,2265;PU7247,4616;PD7242,4613,7237,4613,7232,4616,7231,4617,7181,4583,7180,4583,7125,4551,7125,4552,7065,4522,7065,4523,7001,4496,7000,4496,6933,4472,6933,4473,6862,4451,6862,4452,6788,4433,6788,4434,6712,4418,6712,4419,6633,4406,6553,4397,6471,4391,6388,4388,6388,4389,6305,4389,6221,4393,6137,4400,6054,4411,5973,4425,5895,4442,5820,4462,5820,4463,5750,4485,5684,4510,5684,4511,5622,4538,5622,4539,5565,4568,5565,4569,5512,4600,5513,4601,5465,4635,5466,4635,5423,4671,5424,4671,5387,4709,5388,4709,5357,4748,5358,4748,5333,4788,5334,4789,5316,4830,5317,4830,5305,4872,5306,4873,5301,4916,5303,4916,5304,4959,5306,4958,5314,5001,5316,5000,5331,5042,5332,5041,5353,5082,5354,5081,5382,5120,5383,5119,5416,5157,5417,5156,5456,5193,5456,5192,5501,5227,5501,5226,5551,5259,5551,5258,5606,5289,5666,5317,5730,5343,5731,5343,5799,5366,5872,5387,5948,5405,5949,5405,6029,5420,6111,5432,6194,5440,6278,5445,6361,5447,6444,5445,6526,5440,6607,5432,6687,5421,6764,5407,6764,5406,6840,5390,6839,5389,6912,5369,6982,5346,6981,5346,7048,5320,7047,5320,7110,5292,7109,5291,7168,5260,7167,5260,7221,5226,7217,5222,7212,5221,7207,5223,7203,5227,7203,5228,6351,4914,6354,4910,6359,4908,6364,4908,6368,4912,6370,4914,7249,4620,7246,4615,7241,4613,7236,4614,7232,4617,7231,4617,7198,4595;SP0;PU0,0;IN; \ No newline at end of file diff --git a/share/extensions/tests/data/io/test.ps b/share/extensions/tests/data/io/test.ps new file mode 100644 index 0000000..0c85986 --- /dev/null +++ b/share/extensions/tests/data/io/test.ps @@ -0,0 +1,120 @@ +%!PS-Adobe-3.0 +%%Creator: cairo 1.15.10 (http://cairographics.org) +%%CreationDate: Fri Apr 26 10:51:29 2019 +%%Pages: 1 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%DocumentMedia: 33x34mm 93 97 0 () () +%%BoundingBox: 0 0 94 98 +%%EndComments +%%BeginProlog +/languagelevel where +{ pop languagelevel } { 1 } ifelse +2 lt { /Helvetica findfont 12 scalefont setfont 50 500 moveto + (This print job requires a PostScript Language Level 2 printer.) show + showpage quit } if +/q { gsave } bind def +/Q { grestore } bind def +/cm { 6 array astore concat } bind def +/w { setlinewidth } bind def +/J { setlinecap } bind def +/j { setlinejoin } bind def +/M { setmiterlimit } bind def +/d { setdash } bind def +/m { moveto } bind def +/l { lineto } bind def +/c { curveto } bind def +/h { closepath } bind def +/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto + 0 exch rlineto 0 rlineto closepath } bind def +/S { stroke } bind def +/f { fill } bind def +/f* { eofill } bind def +/n { newpath } bind def +/W { clip } bind def +/W* { eoclip } bind def +/BT { } bind def +/ET { } bind def +/BDC { mark 3 1 roll /BDC pdfmark } bind def +/EMC { mark /EMC pdfmark } bind def +/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def +/Tj { show currentpoint cairo_store_point } bind def +/TJ { + { + dup + type /stringtype eq + { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse + } forall + currentpoint cairo_store_point +} bind def +/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore + cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def +/Tf { pop /cairo_font exch def /cairo_font_matrix where + { pop cairo_selectfont } if } bind def +/Td { matrix translate cairo_font_matrix matrix concatmatrix dup + /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point + /cairo_font where { pop cairo_selectfont } if } bind def +/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def + cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def +/g { setgray } bind def +/rg { setrgbcolor } bind def +/d1 { setcachedevice } bind def +/cairo_data_source { + CairoDataIndex CairoData length lt + { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } + { () } ifelse +} def +/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def +/cairo_image { image cairo_flush_ascii85_file } def +/cairo_imagemask { imagemask cairo_flush_ascii85_file } def +/cairo_set_page_size { + % Change paper size, but only if different from previous paper size otherwise + % duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size + % so we use the same when checking if the size changes. + /setpagedevice where { + pop currentpagedevice + /PageSize known { + 2 copy + currentpagedevice /PageSize get aload pop + exch 4 1 roll + sub abs 5 gt + 3 1 roll + sub abs 5 gt + or + } { + true + } ifelse + { + 2 array astore + 2 dict begin + /PageSize exch def + /ImagingBBox null def + currentdict end + setpagedevice + } { + pop pop + } ifelse + } { + pop + } ifelse +} def +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%PageMedia: 33x34mm +%%PageBoundingBox: 0 0 94 98 +94 98 cairo_set_page_size +%%EndPageSetup +q 0 0 94 98 rectclip +1 0 0 -1 0 98 cm q +0.9 0.5 0.5 rg +1.641 0 m 91.734 0 l 92.645 0 93.375 0.73 93.375 1.641 c 93.375 95.625 +l 93.375 96.535 92.645 97.266 91.734 97.266 c 1.641 97.266 l 0.73 97.266 + 0 96.535 0 95.625 c 0 1.641 l 0 0.73 0.73 0 1.641 0 c h +1.641 0 m f +Q Q +showpage +%%Trailer +%%EOF diff --git a/share/extensions/tests/data/io/test2_r12.dxf b/share/extensions/tests/data/io/test2_r12.dxf new file mode 100644 index 0000000..601549d --- /dev/null +++ b/share/extensions/tests/data/io/test2_r12.dxf @@ -0,0 +1,33472 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +-1.7738298380863851 + 20 +-1.1031808211555469 + 30 +-0.0000000000112498 + 9 +$EXTMAX + 10 +42052.112172750269 + 20 +29762.896876123232 + 30 +0.0000000000002956 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 1 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$DRAGMODE + 70 + 2 + 9 +$LTSCALE + 40 +100.0 + 9 +$OSMODE + 70 + 3071 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +500.0 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +KANJI + 9 +$CLAYER + 8 +1 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937007874016 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$BLIPMODE + 70 + 0 + 9 +$CHAMFERA + 40 +10.0 + 9 +$CHAMFERB + 40 +10.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2451983.4934869329 + 9 +$TDUPDATE + 40 +2451983.6952679278 + 9 +$TDINDWG + 40 +0.1338517361 + 9 +$TDUSRTIMER + 40 +0.1338516204 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 3 + 9 +$PDSIZE + 40 +300.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$COORDS + 70 + 1 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$ATTDIA + 70 + 0 + 9 +$ATTREQ + 70 + 1 + 9 +$HANDLING + 70 +-16383 + 9 +$HANDSEED + 5 +2360 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 48 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.0000000000000000E+020 + 20 +1.0000000000000000E+020 + 30 +1.0000000000000000E+020 + 9 +$PEXTMAX + 10 +-1.0000000000000000E+020 + 20 +-1.0000000000000000E+020 + 30 +-1.0000000000000000E+020 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 70 + 8 + 0 +VPORT + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +21025.169171456091 + 22 +14880.89684765104 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +30109.423655284168 + 41 +1.8391472868217049 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 70 + 5 + 0 +LTYPE + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 2 +HIDDEN + 70 + 0 + 3 +------------------------ + 72 + 65 + 73 + 2 + 40 +12.6 + 49 +8.4000000000000004 + 49 +-4.2000000000000002 + 0 +LTYPE + 2 +DOT + 70 + 0 + 3 +¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ + 72 + 65 + 73 + 2 + 40 +8.0 + 49 +6.0 + 49 +-2.0 + 0 +LTYPE + 2 +DASHDOT + 70 + 0 + 3 +--¥--¥--¥--¥--¥--¥--¥-- + 72 + 65 + 73 + 4 + 40 +50.5 + 49 +30.0 + 49 +-9.0 + 49 +2.5 + 49 +-9.0 + 0 +LTYPE + 2 +DIVIDE + 70 + 0 + 3 +--¥¥--¥¥--¥¥--¥¥--¥¥-- + 72 + 65 + 73 + 6 + 40 +58.0 + 49 +30.0 + 49 +-9.0 + 49 +2.5 + 49 +-5.0 + 49 +2.5 + 49 +-9.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 70 + 8 + 0 +LAYER + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +1 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +DEFPOINTS + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +NORMAL + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +”ñ•\Ž¦‰æ‘w + 70 + 0 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 2 +ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 2 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 2 +ƒƒbƒN‚³‚ꂽ‰æ‘w + 70 + 4 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 70 + 5 + 0 +STYLE + 2 +STANDARD + 70 + 0 + 40 +300.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +300.0 + 3 +txt.shx + 4 + + 0 +STYLE + 2 +KANJI + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +STYLE + 2 +KANJI2 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +txt.shx + 4 + + 0 +STYLE + 2 +KANJI4 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +txt.shx + 4 + + 0 +STYLE + 2 +KANJI3 + 70 + 4 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 70 + 2 + 0 +APPID + 2 +ACAD + 70 + 0 + 0 +APPID + 2 +CONTENTBLOCKICON + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 70 + 2 + 0 +DIMSTYLE + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 + 0 +DIMSTYLE + 2 +STANDARD + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +0.18 + 42 +0.0625 + 43 +0.38 + 44 +0.18 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +0.18 +141 +0.09 +142 +0.0 +143 +25.399999999999999 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.09 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 8 +0 + 2 +$MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +$MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 + 8 +0 + 0 +BLOCK + 67 + 1 + 8 +0 + 2 +$PAPER_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +$PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D + 67 + 1 + 8 +0 + 0 +BLOCK + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 2 +*U1 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U1 + 1 + + 0 +LINE + 5 +2C + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 10 +0.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2D + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2E + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 10 +42000.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +29700.0 + 31 +0.0 + 0 +LINE + 5 +2F + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 10 +42000.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +29700.0 + 31 +0.0 + 0 +ENDBLK + 5 +31 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D2 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +171A + 8 +0 + 62 + 0 + 10 +32797.788520342467 + 20 +20727.373204668042 + 30 +0.0 + 11 +32470.007095362369 + 21 +21055.154629646859 + 31 +0.0 + 0 +LINE + 5 +171B + 8 +0 + 62 + 0 + 10 +36333.322426275197 + 20 +24262.907110600769 + 30 +0.0 + 11 +36005.541001288249 + 21 +24590.688535586451 + 31 +0.0 + 0 +LINE + 5 +171C + 8 +0 + 62 + 0 + 10 +32735.172138307149 + 20 +21143.542977295689 + 30 +0.0 + 11 +35917.152653640449 + 21 +24325.523492641321 + 31 +0.0 + 0 +SOLID + 5 +171D + 8 +0 + 62 + 0 + 10 +32705.709355757652 + 20 +21173.00575984508 + 30 +0.0 + 11 +32764.63492085665 + 21 +21114.080194746311 + 31 +0.0 + 12 +32558.395443010861 + 22 +20966.766281998709 + 32 +0.0 + 13 +32558.395443010861 + 23 +20966.766281998709 + 33 +0.0 + 0 +SOLID + 5 +171E + 8 +0 + 62 + 0 + 10 +35887.689871090952 + 20 +24354.986275190699 + 30 +0.0 + 11 +35946.615436189939 + 21 +24296.060710091941 + 31 +0.0 + 12 +36093.929348936741 + 22 +24502.300187938301 + 32 +0.0 + 13 +36093.929348936741 + 23 +24502.300187938301 + 33 +0.0 + 0 +TEXT + 5 +171F + 8 +1 + 62 + 0 + 10 +33946.09250108659 + 20 +22442.851687728318 + 30 +0.0 + 40 +300.0 + 1 +5000 + 50 +45.000000000111051 + 0 +POINT + 5 +1720 + 8 +DEFPOINTS + 62 + 0 + 10 +32841.982694166712 + 20 +20683.179030843959 + 30 +0.0 + 0 +POINT + 5 +1721 + 8 +DEFPOINTS + 62 + 0 + 10 +36377.516600099443 + 20 +24218.712936776701 + 30 +0.0 + 0 +POINT + 5 +1722 + 8 +DEFPOINTS + 62 + 0 + 10 +36093.929348936741 + 20 +24502.300187938301 + 30 +0.0 + 0 +ENDBLK + 5 +2B6 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D3 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +1723 + 8 +0 + 62 + 0 + 10 +32797.788520342467 + 20 +20638.984857019888 + 30 +0.0 + 11 +32123.26971235923 + 21 +19964.466049039282 + 31 +0.0 + 0 +LINE + 5 +1724 + 8 +0 + 62 + 0 + 10 +33858.4486921223 + 20 +19578.32468524007 + 30 +0.0 + 11 +33183.929884137011 + 21 +18903.8058772574 + 31 +0.0 + 0 +LINE + 5 +1725 + 8 +0 + 62 + 0 + 10 +32388.434755304021 + 20 +19876.077701390452 + 30 +0.0 + 11 +33095.541536489203 + 21 +19168.97092020253 + 31 +0.0 + 0 +SOLID + 5 +1726 + 8 +0 + 62 + 0 + 10 +32417.897537853511 + 20 +19905.540483939829 + 30 +0.0 + 11 +32358.97197275452 + 21 +19846.614918841071 + 31 +0.0 + 12 +32211.658060007721 + 22 +20052.854396687431 + 32 +0.0 + 13 +32211.658060007721 + 23 +20052.854396687431 + 33 +0.0 + 0 +SOLID + 5 +1727 + 8 +0 + 62 + 0 + 10 +33125.0043190387 + 20 +19198.43370275191 + 30 +0.0 + 11 +33066.078753939699 + 21 +19139.508137653142 + 31 +0.0 + 12 +33272.318231785503 + 22 +18992.19422490555 + 32 +0.0 + 13 +33272.318231785503 + 23 +18992.19422490555 + 33 +0.0 + 0 +TEXT + 5 +1728 + 8 +1 + 62 + 0 + 10 +32467.98426818752 + 20 +19884.91653615512 + 30 +0.0 + 40 +300.0 + 1 +1500 + 50 +314.99999999988893 + 0 +POINT + 5 +1729 + 8 +DEFPOINTS + 62 + 0 + 10 +32841.982694166698 + 20 +20683.17903084397 + 30 +0.0 + 0 +POINT + 5 +172A + 8 +DEFPOINTS + 62 + 0 + 10 +33902.642865946538 + 20 +19622.518859064141 + 30 +0.0 + 0 +POINT + 5 +172B + 8 +DEFPOINTS + 62 + 0 + 10 +33272.318231785503 + 20 +18992.19422490555 + 30 +0.0 + 0 +ENDBLK + 5 +2C3 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D4 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +172C + 8 +0 + 62 + 0 + 10 +34061.617553885691 + 20 +28525.654083678131 + 30 +0.0 + 11 +34061.617553885691 + 21 +28989.207020387759 + 31 +0.0 + 0 +LINE + 5 +172D + 8 +0 + 62 + 0 + 10 +39061.617553885691 + 20 +28525.654083678131 + 30 +0.0 + 11 +39061.617553885691 + 21 +28989.207020387759 + 31 +0.0 + 0 +LINE + 5 +172E + 8 +0 + 62 + 0 + 10 +34311.617553885691 + 20 +28864.207020387759 + 30 +0.0 + 11 +38811.617553885691 + 21 +28864.207020387759 + 31 +0.0 + 0 +SOLID + 5 +172F + 8 +0 + 62 + 0 + 10 +34311.617553885691 + 20 +28905.873687054431 + 30 +0.0 + 11 +34311.617553885691 + 21 +28822.540353721091 + 31 +0.0 + 12 +34061.617553885691 + 22 +28864.207020387759 + 32 +0.0 + 13 +34061.617553885691 + 23 +28864.207020387759 + 33 +0.0 + 0 +SOLID + 5 +1730 + 8 +0 + 62 + 0 + 10 +38811.617553885691 + 20 +28905.873687054431 + 30 +0.0 + 11 +38811.617553885691 + 21 +28822.540353721091 + 31 +0.0 + 12 +39061.617553885691 + 22 +28864.207020387759 + 32 +0.0 + 13 +39061.617553885691 + 23 +28864.207020387759 + 33 +0.0 + 0 +TEXT + 5 +1731 + 8 +1 + 62 + 0 + 10 +36086.617553885691 + 20 +28926.707020387759 + 30 +0.0 + 40 +300.0 + 1 +5000 + 0 +POINT + 5 +1732 + 8 +DEFPOINTS + 62 + 0 + 10 +34061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +POINT + 5 +1733 + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +POINT + 5 +1734 + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +28864.207020387759 + 30 +0.0 + 0 +ENDBLK + 5 +2D3 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D5 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +1735 + 8 +0 + 62 + 0 + 10 +33999.117553885691 + 20 +28463.154083678131 + 30 +0.0 + 11 +33045.203907559007 + 21 +28463.154083678131 + 31 +0.0 + 0 +LINE + 5 +1736 + 8 +0 + 62 + 0 + 10 +33999.117553885691 + 20 +26963.154083678131 + 30 +0.0 + 11 +33045.203907559007 + 21 +26963.154083678131 + 31 +0.0 + 0 +LINE + 5 +1737 + 8 +0 + 62 + 0 + 10 +33170.203907559007 + 20 +28213.154083678131 + 30 +0.0 + 11 +33170.203907559007 + 21 +27213.154083678131 + 31 +0.0 + 0 +SOLID + 5 +1738 + 8 +0 + 62 + 0 + 10 +33128.53724089235 + 20 +28213.154083678131 + 30 +0.0 + 11 +33211.870574225679 + 21 +28213.154083678131 + 31 +0.0 + 12 +33170.203907559007 + 22 +28463.154083678131 + 32 +0.0 + 13 +33170.203907559007 + 23 +28463.154083678131 + 33 +0.0 + 0 +SOLID + 5 +1739 + 8 +0 + 62 + 0 + 10 +33128.53724089235 + 20 +27213.154083678131 + 30 +0.0 + 11 +33211.870574225679 + 21 +27213.154083678131 + 31 +0.0 + 12 +33170.203907559007 + 22 +26963.154083678131 + 32 +0.0 + 13 +33170.203907559007 + 23 +26963.154083678131 + 33 +0.0 + 0 +TEXT + 5 +173A + 8 +1 + 62 + 0 + 10 +33107.703907559 + 20 +27263.154083678131 + 30 +0.0 + 40 +300.0 + 1 +1500 + 50 +90.0 + 0 +POINT + 5 +173B + 8 +DEFPOINTS + 62 + 0 + 10 +34061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +POINT + 5 +173C + 8 +DEFPOINTS + 62 + 0 + 10 +34061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +POINT + 5 +173D + 8 +DEFPOINTS + 62 + 0 + 10 +33170.203907559007 + 20 +26963.154083678131 + 30 +0.0 + 0 +ENDBLK + 5 +2DF + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D6 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +ARC + 5 +211C + 8 +0 + 62 + 0 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 40 +3643.198465986115 + 50 +3.9324667284677068 + 51 +41.067533271532312 + 0 +SOLID + 5 +211D + 8 +0 + 62 + 0 + 10 +37578.905838466562 + 20 +19873.801268951469 + 30 +0.0 + 11 +37495.621570041811 + 21 +19870.942059725308 + 31 +0.0 + 12 +37545.84133193265 + 22 +19622.518859064148 + 32 +0.0 + 13 +37545.84133193265 + 23 +19622.518859064148 + 33 +0.0 + 0 +SOLID + 5 +211E + 8 +0 + 62 + 0 + 10 +36618.924202062743 + 20 +21987.476735597189 + 30 +0.0 + 11 +36679.836839264681 + 21 +22044.345840333841 + 31 +0.0 + 12 +36478.773206453741 + 22 +22198.649199571359 + 32 +0.0 + 13 +36478.773206453741 + 23 +22198.649199571359 + 33 +0.0 + 0 +TEXT + 8 +0 + 40 +300 + 5 +217B + 62 +0 + 72 +0 + 71 +0 + 10 +37464.8 + 20 +20708.0 + 30 +0.000000 + 1 +45‹ + 0 +POINT + 5 +2120 + 8 +DEFPOINTS + 62 + 0 + 10 +37421.702354539237 + 20 +20565.44800714964 + 30 +0.0 + 0 +POINT + 5 +2121 + 8 +DEFPOINTS + 62 + 0 + 10 +37438.176771879283 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +2122 + 8 +DEFPOINTS + 62 + 0 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 0 +POINT + 5 +2123 + 8 +DEFPOINTS + 62 + 0 + 10 +37726.652160292273 + 20 +19622.518859064148 + 30 +0.0 + 0 +POINT + 5 +2124 + 8 +DEFPOINTS + 62 + 0 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 0 +ENDBLK + 5 +335 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D7 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +1747 + 8 +0 + 62 + 0 + 10 +33971.719636084497 + 20 +18916.487506715672 + 30 +0.0 + 11 +33971.719636084497 + 21 +17291.487506715672 + 31 +0.0 + 0 +LINE + 5 +1748 + 8 +0 + 62 + 0 + 10 +33971.719636084497 + 20 +12791.48750671567 + 30 +0.0 + 11 +33971.719636084497 + 21 +12541.48750671567 + 31 +0.0 + 0 +TEXT + 5 +1749 + 8 +1 + 62 + 0 + 10 +33909.21963608449 + 20 +17603.987506715672 + 30 +0.0 + 40 +300.0 + 1 +\U+22054000 + 50 +90.0 + 0 +LINE + 5 +174A + 8 +0 + 62 + 0 + 10 +33971.719636084497 + 20 +13041.48750671567 + 30 +0.0 + 11 +33971.719636084497 + 21 +17041.487506715672 + 31 +0.0 + 0 +SOLID + 5 +174B + 8 +0 + 62 + 0 + 10 +33930.05296941784 + 20 +12791.48750671567 + 30 +0.0 + 11 +34013.386302751162 + 21 +12791.48750671567 + 31 +0.0 + 12 +33971.719636084497 + 22 +13041.48750671567 + 32 +0.0 + 13 +33971.719636084497 + 23 +13041.48750671567 + 33 +0.0 + 0 +SOLID + 5 +174C + 8 +0 + 62 + 0 + 10 +33930.05296941784 + 20 +17291.487506715672 + 30 +0.0 + 11 +34013.386302751162 + 21 +17291.487506715672 + 31 +0.0 + 12 +33971.719636084497 + 22 +17041.487506715672 + 32 +0.0 + 13 +33971.719636084497 + 23 +17041.487506715672 + 33 +0.0 + 0 +POINT + 5 +174D + 8 +DEFPOINTS + 62 + 0 + 10 +33971.719636084497 + 20 +17041.487506715672 + 30 +0.0 + 0 +POINT + 5 +174E + 8 +DEFPOINTS + 62 + 0 + 10 +33971.719636084497 + 20 +13041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +37B + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D8 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +174F + 8 +0 + 62 + 0 + 10 +37235.06246344516 + 20 +17131.037360419479 + 30 +0.0 + 11 +35866.563858422953 + 21 +16254.774518543691 + 31 +0.0 + 0 +TEXT + 5 +1750 + 8 +1 + 62 + 0 + 10 +36096.034250085853 + 20 +16475.921165251431 + 30 +0.0 + 40 +300.0 + 1 +R2000 + 50 +32.631826972857269 + 0 +LINE + 5 +1751 + 8 +0 + 62 + 0 + 10 +33971.719636084512 + 20 +15041.48750671567 + 30 +0.0 + 11 +35656.025611496458 + 21 +16119.964850562799 + 31 +0.0 + 0 +SOLID + 5 +1752 + 8 +0 + 62 + 0 + 10 +35844.095580426139 + 20 +16289.864226364771 + 30 +0.0 + 11 +35889.032136419759 + 21 +16219.6848107226 + 31 +0.0 + 12 +35656.025611496458 + 22 +16119.964850562799 + 32 +0.0 + 13 +35656.025611496458 + 23 +16119.964850562799 + 33 +0.0 + 0 +POINT + 5 +1753 + 8 +DEFPOINTS + 62 + 0 + 10 +35656.025611496458 + 20 +16119.964850562799 + 30 +0.0 + 0 +POINT + 5 +1754 + 8 +DEFPOINTS + 62 + 0 + 10 +33971.719636084512 + 20 +15041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +385 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +NONAME + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NONAME + 1 + + 0 +LINE + 5 +747 + 8 +0 + 10 +24339.43845972023 + 20 +5012.4925338925459 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.6195528147382 + 31 +0.0 + 0 +LINE + 5 +748 + 8 +0 + 10 +24339.43845972023 + 20 +5012.4925338925459 + 30 +0.0 + 11 +19339.43845972023 + 21 +5012.4925338925468 + 31 +0.0 + 0 +LINE + 5 +749 + 8 +0 + 10 +19339.43845972023 + 20 +8260.0877980841906 + 30 +0.0 + 11 +24339.43845972023 + 21 +8260.0877980841906 + 31 +0.0 + 0 +LINE + 5 +74A + 8 +0 + 10 +19339.43845972023 + 20 +8260.0877980841906 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.9607791620001 + 31 +0.0 + 0 +LINE + 5 +74B + 8 +0 + 10 +24339.43845972023 + 20 +8260.0877980841906 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.9607791620001 + 31 +0.0 + 0 +LINE + 5 +74C + 8 +0 + 10 +19339.43845972023 + 20 +5012.4925338925468 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.6195528147382 + 31 +0.0 + 0 +ENDBLK + 5 +746 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D10 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +LINE + 5 +1755 + 8 +0 + 62 + 0 + 10 +834.83167002764822 + 20 +3454.385493772555 + 30 +0.0 + 11 +834.83167002764822 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1756 + 8 +0 + 62 + 0 + 10 +3334.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1757 + 8 +0 + 62 + 0 + 10 +1084.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +3084.8316700276482 + 21 +4323.3548996505697 + 31 +0.0 + 0 +SOLID + 5 +1758 + 8 +0 + 62 + 0 + 10 +1084.831670027648 + 20 +4365.0215663172376 + 30 +0.0 + 11 +1084.831670027648 + 21 +4281.6882329839036 + 31 +0.0 + 12 +834.83167002764822 + 22 +4323.3548996505697 + 32 +0.0 + 13 +834.83167002764822 + 23 +4323.3548996505697 + 33 +0.0 + 0 +SOLID + 5 +1759 + 8 +0 + 62 + 0 + 10 +3084.8316700276482 + 20 +4365.0215663172376 + 30 +0.0 + 11 +3084.8316700276482 + 21 +4281.6882329839036 + 31 +0.0 + 12 +3334.8316700276482 + 22 +4323.3548996505697 + 32 +0.0 + 13 +3334.8316700276482 + 23 +4323.3548996505697 + 33 +0.0 + 0 +TEXT + 5 +175A + 8 +1 + 62 + 0 + 10 +1584.831670027648 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +175B + 8 +DEFPOINTS + 62 + 0 + 10 +834.83167002764822 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175C + 8 +DEFPOINTS + 62 + 0 + 10 +3334.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175D + 8 +DEFPOINTS + 62 + 0 + 10 +3334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +761 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_CLOSEDBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDBLANK + 1 + + 0 +LINE + 5 +7CD + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +7CE + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +7CF + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +ENDBLK + 5 +7D1 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D12 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D12 + 1 + + 0 +LINE + 5 +175E + 8 +0 + 62 + 0 + 10 +3334.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +175F + 8 +0 + 62 + 0 + 10 +5834.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1760 + 8 +0 + 62 + 0 + 10 +3584.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +5584.8316700276482 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +1761 + 8 +0 + 62 + 0 + 2 +_CLOSEDBLANK + 10 +3334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1762 + 8 +0 + 62 + 0 + 2 +_CLOSEDBLANK + 10 +5834.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1763 + 8 +1 + 62 + 0 + 10 +4084.8316700276482 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1764 + 8 +DEFPOINTS + 62 + 0 + 10 +3334.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1765 + 8 +DEFPOINTS + 62 + 0 + 10 +5834.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1766 + 8 +DEFPOINTS + 62 + 0 + 10 +5834.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +80D + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_CLOSED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSED + 1 + + 0 +LINE + 5 +821 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +822 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +823 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +824 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +826 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D14 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D14 + 1 + + 0 +LINE + 5 +1767 + 8 +0 + 62 + 0 + 10 +5834.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1768 + 8 +0 + 62 + 0 + 10 +8334.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1769 + 8 +0 + 62 + 0 + 10 +6084.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +8084.8316700276482 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +176A + 8 +0 + 62 + 0 + 2 +_CLOSED + 10 +5834.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +176B + 8 +0 + 62 + 0 + 2 +_CLOSED + 10 +8334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +176C + 8 +1 + 62 + 0 + 10 +6584.8316700276482 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +176D + 8 +DEFPOINTS + 62 + 0 + 10 +5834.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176E + 8 +DEFPOINTS + 62 + 0 + 10 +8334.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176F + 8 +DEFPOINTS + 62 + 0 + 10 +8334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +849 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D15 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D15 + 1 + + 0 +LINE + 5 +1770 + 8 +0 + 62 + 0 + 10 +8334.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.8316700276482 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1771 + 8 +0 + 62 + 0 + 10 +10834.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1772 + 8 +0 + 62 + 0 + 10 +8584.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +10584.831670027639 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +1773 + 8 +0 + 62 + 0 + 2 +_DOT + 10 +8334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1774 + 8 +0 + 62 + 0 + 2 +_DOT + 10 +10834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1775 + 8 +1 + 62 + 0 + 10 +9084.8316700276482 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1776 + 8 +DEFPOINTS + 62 + 0 + 10 +8334.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1777 + 8 +DEFPOINTS + 62 + 0 + 10 +10834.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1778 + 8 +DEFPOINTS + 62 + 0 + 10 +10834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +872 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_DOT + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOT + 1 + + 0 +POLYLINE + 5 +87D + 8 +0 + 6 +BYBLOCK + 62 + 0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 40 +0.5 + 41 +0.5 + 0 +VERTEX + 5 +214D + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.25 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +VERTEX + 5 +214E + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.25 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +SEQEND + 5 +214F + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +LINE + 5 +87E + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +880 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D17 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D17 + 1 + + 0 +LINE + 5 +1779 + 8 +0 + 62 + 0 + 10 +10834.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +177A + 8 +0 + 62 + 0 + 10 +13334.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +177B + 8 +0 + 62 + 0 + 10 +10834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +13334.831670027639 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +177C + 8 +0 + 62 + 0 + 2 +_ARCHTICK + 10 +10834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +177D + 8 +0 + 62 + 0 + 2 +_ARCHTICK + 10 +13334.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +177E + 8 +1 + 62 + 0 + 10 +11584.831670027639 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +177F + 8 +DEFPOINTS + 62 + 0 + 10 +10834.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1780 + 8 +DEFPOINTS + 62 + 0 + 10 +13334.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1781 + 8 +DEFPOINTS + 62 + 0 + 10 +13334.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +8A9 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_ARCHTICK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ARCHTICK + 1 + + 0 +POLYLINE + 5 +8B4 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.15 + 41 +0.15 + 0 +VERTEX + 5 +2150 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 0 +VERTEX + 5 +2151 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.5 + 20 +0.5 + 30 +0.0 + 0 +SEQEND + 5 +2152 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +ENDBLK + 5 +8B6 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D19 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D19 + 1 + + 0 +LINE + 5 +1782 + 8 +0 + 62 + 0 + 10 +13334.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1783 + 8 +0 + 62 + 0 + 10 +15834.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1784 + 8 +0 + 62 + 0 + 10 +13334.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +15834.831670027639 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +1785 + 8 +0 + 62 + 0 + 2 +_OBLIQUE + 10 +13334.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1786 + 8 +0 + 62 + 0 + 2 +_OBLIQUE + 10 +15834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1787 + 8 +1 + 62 + 0 + 10 +14084.831670027639 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1788 + 8 +DEFPOINTS + 62 + 0 + 10 +13334.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1789 + 8 +DEFPOINTS + 62 + 0 + 10 +15834.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +178A + 8 +DEFPOINTS + 62 + 0 + 10 +15834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +8D6 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_OBLIQUE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OBLIQUE + 1 + + 0 +LINE + 5 +8E1 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +ENDBLK + 5 +8E3 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D21 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D21 + 1 + + 0 +LINE + 5 +178B + 8 +0 + 62 + 0 + 10 +15834.831670027639 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.831670027639 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +178C + 8 +0 + 62 + 0 + 10 +18334.831670027641 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.831670027641 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +178D + 8 +0 + 62 + 0 + 10 +16084.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +18084.831670027648 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +178E + 8 +0 + 62 + 0 + 2 +_OPEN + 10 +15834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +178F + 8 +0 + 62 + 0 + 2 +_OPEN + 10 +18334.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1790 + 8 +1 + 62 + 0 + 10 +16584.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1791 + 8 +DEFPOINTS + 62 + 0 + 10 +15834.831670027639 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1792 + 8 +DEFPOINTS + 62 + 0 + 10 +18334.831670027641 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1793 + 8 +DEFPOINTS + 62 + 0 + 10 +18334.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +904 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_OPEN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN + 1 + + 0 +LINE + 5 +90F + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +910 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +-0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +911 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +913 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D23 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D23 + 1 + + 0 +LINE + 5 +1794 + 8 +0 + 62 + 0 + 10 +18334.831670027641 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.831670027641 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1795 + 8 +0 + 62 + 0 + 10 +20834.831670027641 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.831670027641 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +1796 + 8 +0 + 62 + 0 + 10 +18584.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 11 +20584.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +1797 + 8 +0 + 62 + 0 + 2 +_ORIGIN + 10 +18334.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1798 + 8 +0 + 62 + 0 + 2 +_ORIGIN + 10 +20834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1799 + 8 +1 + 62 + 0 + 10 +19084.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +179A + 8 +DEFPOINTS + 62 + 0 + 10 +18334.831670027641 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179B + 8 +DEFPOINTS + 62 + 0 + 10 +20834.831670027641 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179C + 8 +DEFPOINTS + 62 + 0 + 10 +20834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +93C + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_ORIGIN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN + 1 + + 0 +CIRCLE + 5 +947 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +948 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +94A + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D25 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D25 + 1 + + 0 +LINE + 5 +179D + 8 +0 + 62 + 0 + 10 +20834.831670027641 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.831670027641 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +179E + 8 +0 + 62 + 0 + 10 +23334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +179F + 8 +0 + 62 + 0 + 10 +21084.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +23084.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17A0 + 8 +0 + 62 + 0 + 2 +_ORIGIN2 + 10 +20834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17A1 + 8 +0 + 62 + 0 + 2 +_ORIGIN2 + 10 +23334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17A2 + 8 +1 + 62 + 0 + 10 +21584.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17A3 + 8 +DEFPOINTS + 62 + 0 + 10 +20834.831670027641 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A4 + 8 +DEFPOINTS + 62 + 0 + 10 +23334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A5 + 8 +DEFPOINTS + 62 + 0 + 10 +23334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +98A + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_ORIGIN2 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN2 + 1 + + 0 +CIRCLE + 5 +995 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +CIRCLE + 5 +996 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +LINE + 5 +997 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +999 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D27 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D27 + 1 + + 0 +LINE + 5 +17A6 + 8 +0 + 62 + 0 + 10 +23334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17A7 + 8 +0 + 62 + 0 + 10 +25834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17A8 + 8 +0 + 62 + 0 + 10 +23584.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +25584.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17A9 + 8 +0 + 62 + 0 + 2 +_OPEN90 + 10 +23334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17AA + 8 +0 + 62 + 0 + 2 +_OPEN90 + 10 +25834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17AB + 8 +1 + 62 + 0 + 10 +24084.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17AC + 8 +DEFPOINTS + 62 + 0 + 10 +23334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AD + 8 +DEFPOINTS + 62 + 0 + 10 +25834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AE + 8 +DEFPOINTS + 62 + 0 + 10 +25834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +9D0 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_OPEN90 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN90 + 1 + + 0 +LINE + 5 +9DB + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +9DC + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +9DD + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +9DF + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D29 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D29 + 1 + + 0 +LINE + 5 +17AF + 8 +0 + 62 + 0 + 10 +25834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17B0 + 8 +0 + 62 + 0 + 10 +28334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17B1 + 8 +0 + 62 + 0 + 10 +26084.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +28084.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17B2 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +25834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17B3 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +28334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17B4 + 8 +1 + 62 + 0 + 10 +26584.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17B5 + 8 +DEFPOINTS + 62 + 0 + 10 +25834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B6 + 8 +DEFPOINTS + 62 + 0 + 10 +28334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B7 + 8 +DEFPOINTS + 62 + 0 + 10 +28334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +ABC + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_OPEN30 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN30 + 1 + + 0 +LINE + 5 +AC7 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.26794919 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +AC8 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.26794919 + 31 +0.0 + 0 +LINE + 5 +AC9 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +ACB + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D31 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D31 + 1 + + 0 +LINE + 5 +17B8 + 8 +0 + 62 + 0 + 10 +28334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17B9 + 8 +0 + 62 + 0 + 10 +30834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17BA + 8 +0 + 62 + 0 + 10 +28334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +30834.831670027648 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17BB + 8 +0 + 62 + 0 + 2 +_DOTSMALL + 10 +28334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17BC + 8 +0 + 62 + 0 + 2 +_DOTSMALL + 10 +30834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17BD + 8 +1 + 62 + 0 + 10 +29084.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17BE + 8 +DEFPOINTS + 62 + 0 + 10 +28334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17BF + 8 +DEFPOINTS + 62 + 0 + 10 +30834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C0 + 8 +DEFPOINTS + 62 + 0 + 10 +30834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +AF4 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_DOTSMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTSMALL + 1 + + 0 +POLYLINE + 5 +AFF + 8 +0 + 6 +BYBLOCK + 62 + 0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 40 +0.5 + 41 +0.5 + 0 +VERTEX + 5 +2153 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.0625 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +VERTEX + 5 +2154 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0625 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +SEQEND + 5 +2155 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +ENDBLK + 5 +B01 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D33 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D33 + 1 + + 0 +LINE + 5 +17C1 + 8 +0 + 62 + 0 + 10 +30834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17C2 + 8 +0 + 62 + 0 + 10 +33334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17C3 + 8 +0 + 62 + 0 + 10 +31084.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +33084.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17C4 + 8 +0 + 62 + 0 + 2 +_DOTBLANK + 10 +30834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17C5 + 8 +0 + 62 + 0 + 2 +_DOTBLANK + 10 +33334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17C6 + 8 +1 + 62 + 0 + 10 +31584.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17C7 + 8 +DEFPOINTS + 62 + 0 + 10 +30834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C8 + 8 +DEFPOINTS + 62 + 0 + 10 +33334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C9 + 8 +DEFPOINTS + 62 + 0 + 10 +33334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +B2A + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_DOTBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTBLANK + 1 + + 0 +CIRCLE + 5 +B35 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +B36 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +B38 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D35 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D35 + 1 + + 0 +LINE + 5 +17CA + 8 +0 + 62 + 0 + 10 +33334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17CB + 8 +0 + 62 + 0 + 10 +35834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17CC + 8 +0 + 62 + 0 + 10 +33334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +35834.831670027648 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17CD + 8 +0 + 62 + 0 + 2 +_SMALL + 10 +33334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17CE + 8 +0 + 62 + 0 + 2 +_SMALL + 10 +35834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17CF + 8 +1 + 62 + 0 + 10 +34084.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17D0 + 8 +DEFPOINTS + 62 + 0 + 10 +33334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D1 + 8 +DEFPOINTS + 62 + 0 + 10 +35834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D2 + 8 +DEFPOINTS + 62 + 0 + 10 +35834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +B62 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_SMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_SMALL + 1 + + 0 +CIRCLE + 5 +B6D + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +ENDBLK + 5 +B6F + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D37 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D37 + 1 + + 0 +LINE + 5 +17D3 + 8 +0 + 62 + 0 + 10 +35834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17D4 + 8 +0 + 62 + 0 + 10 +38334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17D5 + 8 +0 + 62 + 0 + 10 +36084.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +38084.831670027641 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17D6 + 8 +0 + 62 + 0 + 2 +_BOXBLANK + 10 +35834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17D7 + 8 +0 + 62 + 0 + 2 +_BOXBLANK + 10 +38334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17D8 + 8 +1 + 62 + 0 + 10 +36584.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17D9 + 8 +DEFPOINTS + 62 + 0 + 10 +35834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DA + 8 +DEFPOINTS + 62 + 0 + 10 +38334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DB + 8 +DEFPOINTS + 62 + 0 + 10 +38334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +B8F + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_BOXBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXBLANK + 1 + + 0 +LINE + 5 +B9A + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9B + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9C + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9D + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9E + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +BA0 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D39 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D39 + 1 + + 0 +LINE + 5 +17DC + 8 +0 + 62 + 0 + 10 +38334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.831670027648 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17DD + 8 +0 + 62 + 0 + 10 +40834.831670027641 + 20 +3454.385493772555 + 30 +0.0 + 11 +40834.831670027641 + 21 +4448.3548996505697 + 31 +0.0 + 0 +LINE + 5 +17DE + 8 +0 + 62 + 0 + 10 +38584.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +40584.831670027648 + 21 +4323.3548996505697 + 31 +0.0 + 0 +INSERT + 5 +17DF + 8 +0 + 62 + 0 + 2 +_BOXFILLED + 10 +38334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17E0 + 8 +0 + 62 + 0 + 2 +_BOXFILLED + 10 +40834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +17E1 + 8 +1 + 62 + 0 + 10 +39084.831670027641 + 20 +4385.8548996505697 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +17E2 + 8 +DEFPOINTS + 62 + 0 + 10 +38334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E3 + 8 +DEFPOINTS + 62 + 0 + 10 +40834.831670027641 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E4 + 8 +DEFPOINTS + 62 + 0 + 10 +40834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 0 +ENDBLK + 5 +E71 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_BOXFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXFILLED + 1 + + 0 +SOLID + 5 +E7C + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 12 +-0.5 + 22 +-0.5 + 32 +0.0 + 13 +0.5 + 23 +-0.5 + 33 +0.0 + 0 +LINE + 5 +E7D + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +E7F + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D41 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D41 + 1 + + 0 +LINE + 5 +1DBB + 8 +0 + 62 + 0 + 10 +3874.0720016190171 + 20 +794.91766210896446 + 30 +0.0 + 11 +3874.0720016190171 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBC + 8 +0 + 62 + 0 + 10 +6374.0720016190171 + 20 +794.91766210896446 + 30 +0.0 + 11 +6374.0720016190171 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBD + 8 +0 + 62 + 0 + 10 +4124.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 11 +6124.0720016190171 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DBE + 8 +0 + 62 + 0 + 2 +_DATUMBLANK + 10 +3874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DBF + 8 +0 + 62 + 0 + 2 +_DATUMBLANK + 10 +6374.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1DC0 + 8 +1 + 62 + 0 + 10 +4624.0720016190171 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1DC1 + 8 +DEFPOINTS + 62 + 0 + 10 +3874.0720016190171 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DC2 + 8 +DEFPOINTS + 62 + 0 + 10 +6374.0720016190171 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DC3 + 8 +DEFPOINTS + 62 + 0 + 10 +6374.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +EA0 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_DATUMBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMBLANK + 1 + + 0 +LINE + 5 +EAB + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +EAC + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-1.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +-0.5773502700000001 + 31 +0.0 + 0 +LINE + 5 +EAD + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +-0.5773502700000001 + 30 +0.0 + 11 +0.0 + 21 +0.5773502700000001 + 31 +0.0 + 0 +ENDBLK + 5 +EAF + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D43 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D43 + 1 + + 0 +LINE + 5 +1DD4 + 8 +0 + 62 + 0 + 10 +6374.0720016190171 + 20 +794.91766210896446 + 30 +0.0 + 11 +6374.0720016190171 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD5 + 8 +0 + 62 + 0 + 10 +8874.0720016190171 + 20 +794.91766210896446 + 30 +0.0 + 11 +8874.0720016190171 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD6 + 8 +0 + 62 + 0 + 10 +6624.0720016190162 + 20 +1663.887067986979 + 30 +0.0 + 11 +8624.0720016190171 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DD7 + 8 +0 + 62 + 0 + 2 +_DATUMFILLED + 10 +6374.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DD8 + 8 +0 + 62 + 0 + 2 +_DATUMFILLED + 10 +8874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1DD9 + 8 +1 + 62 + 0 + 10 +7124.0720016190162 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1DDA + 8 +DEFPOINTS + 62 + 0 + 10 +6374.0720016190171 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DDB + 8 +DEFPOINTS + 62 + 0 + 10 +8874.0720016190171 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DDC + 8 +DEFPOINTS + 62 + 0 + 10 +8874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +F8D + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_DATUMFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMFILLED + 1 + + 0 +SOLID + 5 +F98 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 12 +0.0 + 22 +-0.5773502700000001 + 32 +0.0 + 13 +0.0 + 23 +-0.5773502700000001 + 33 +0.0 + 0 +ENDBLK + 5 +F9A + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D45 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D45 + 1 + + 0 +LINE + 5 +1DCB + 8 +0 + 62 + 0 + 10 +8874.0720016190171 + 20 +794.91766210896446 + 30 +0.0 + 11 +8874.0720016190171 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCC + 8 +0 + 62 + 0 + 10 +11374.07200161901 + 20 +794.91766210896446 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCD + 8 +0 + 62 + 0 + 10 +8874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 11 +11374.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DCE + 8 +0 + 62 + 0 + 2 +_INTEGRAL + 10 +8874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DCF + 8 +0 + 62 + 0 + 2 +_INTEGRAL + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1DD0 + 8 +1 + 62 + 0 + 10 +9624.0720016190171 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1DD1 + 8 +DEFPOINTS + 62 + 0 + 10 +8874.0720016190171 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DD2 + 8 +DEFPOINTS + 62 + 0 + 10 +11374.07200161901 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DD3 + 8 +DEFPOINTS + 62 + 0 + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +115B + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_INTEGRAL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_INTEGRAL + 1 + + 0 +ARC + 5 +1166 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +0.44488802 + 20 +-0.09133463 + 30 +0.0 + 40 +0.4541666700000001 + 50 +101.9999999980395 + 51 +167.99999997991929 + 0 +ARC + 5 +1167 + 8 +0 + 6 +BYBLOCK + 62 + 0 + 10 +-0.44488802 + 20 +0.09133463 + 30 +0.0 + 40 +0.4541666700000001 + 50 +282.00000002154269 + 51 +348.00000000342249 + 0 +ENDBLK + 5 +1169 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D47 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D47 + 1 + + 0 +LINE + 5 +1DC4 + 8 +0 + 62 + 0 + 10 +11374.07200161901 + 20 +794.91766210896446 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC5 + 8 +0 + 62 + 0 + 10 +13874.07200161901 + 20 +794.91766210896446 + 30 +0.0 + 11 +13874.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC6 + 8 +0 + 62 + 0 + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +13874.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +TEXT + 5 +1DC7 + 8 +1 + 62 + 0 + 10 +12124.07200161901 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +2500 + 0 +POINT + 5 +1DC8 + 8 +DEFPOINTS + 62 + 0 + 10 +11374.07200161901 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DC9 + 8 +DEFPOINTS + 62 + 0 + 10 +13874.07200161901 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DCA + 8 +DEFPOINTS + 62 + 0 + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1189 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +_NONE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_NONE + 1 + + 0 +ENDBLK + 5 +1195 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D49 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D49 + 1 + + 0 +LINE + 5 +1DDD + 8 +0 + 62 + 0 + 10 +14608.826121400591 + 20 +794.91766210896446 + 30 +0.0 + 11 +14608.826121400591 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDE + 8 +0 + 62 + 0 + 10 +16108.826121400591 + 20 +794.91766210896446 + 30 +0.0 + 11 +16108.826121400591 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDF + 8 +0 + 62 + 0 + 10 +14858.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 11 +15858.826121400591 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DE0 + 8 +0 + 62 + 0 + 10 +16108.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 11 +17383.826121400591 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DE1 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +14608.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DE2 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +16108.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +TEXT + 5 +1DE3 + 8 +1 + 62 + 0 + 10 +16421.326121400591 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +1500 + 0 +POINT + 5 +1DE4 + 8 +DEFPOINTS + 62 + 0 + 10 +14608.826121400591 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DE5 + 8 +DEFPOINTS + 62 + 0 + 10 +16108.826121400591 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DE6 + 8 +DEFPOINTS + 62 + 0 + 10 +16108.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +13FE + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D50 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D50 + 1 + + 0 +LINE + 5 +1DB0 + 8 +0 + 62 + 0 + 10 +19054.680964136489 + 20 +794.91766210896446 + 30 +0.0 + 11 +19054.680964136489 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB1 + 8 +0 + 62 + 0 + 10 +19554.680964136489 + 20 +794.91766210896446 + 30 +0.0 + 11 +19554.680964136489 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB2 + 8 +0 + 62 + 0 + 10 +18804.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 11 +18554.680964136489 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB3 + 8 +0 + 62 + 0 + 10 +19804.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 11 +20879.680964136489 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB4 + 8 +0 + 62 + 0 + 10 +19054.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 11 +19554.680964136489 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DB5 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +19054.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +INSERT + 5 +1DB6 + 8 +0 + 62 + 0 + 2 +_OPEN30 + 10 +19554.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +TEXT + 5 +1DB7 + 8 +1 + 62 + 0 + 10 +20117.180964136489 + 20 +1726.387067986979 + 30 +0.0 + 40 +300.0 + 1 +500 + 0 +POINT + 5 +1DB8 + 8 +DEFPOINTS + 62 + 0 + 10 +19054.680964136489 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DB9 + 8 +DEFPOINTS + 62 + 0 + 10 +19554.680964136489 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1DBA + 8 +DEFPOINTS + 62 + 0 + 10 +19554.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1488 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D51 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D51 + 1 + + 0 +LINE + 5 +1F3A + 8 +0 + 62 + 0 + 10 +21971.23629970006 + 20 +1700.0 + 30 +0.0 + 11 +22602.860683220821 + 21 +1700.0 + 31 +0.0 + 0 +LINE + 5 +1F3B + 8 +0 + 62 + 0 + 10 +22602.860683220821 + 20 +1700.0 + 30 +0.0 + 11 +22607.86068322081 + 21 +731.28275756195944 + 31 +0.0 + 0 +LINE + 5 +1F3C + 8 +0 + 62 + 0 + 10 +22607.86068322081 + 20 +731.28275756195944 + 30 +0.0 + 11 +24313.48568322081 + 21 +731.28275756195944 + 31 +0.0 + 0 +TEXT + 5 +1F3D + 8 +1 + 62 + 0 + 10 +22613.48568322081 + 20 +731.90775756195944 + 30 +0.0 + 40 +300.0 + 1 +1638.24 + 0 +POINT + 5 +1F3E + 8 +DEFPOINTS + 62 + 0 + 10 +21970.61129970006 + 20 +1700.0 + 30 +0.0 + 0 +POINT + 5 +1F3F + 8 +DEFPOINTS + 62 + 0 + 10 +22612.86068322081 + 20 +731.28275756195944 + 30 +0.0 + 0 +POINT + 5 +1F40 + 8 +DEFPOINTS + 62 + 0 + 10 +51.460251012922981 + 20 +61.75531173110096 + 30 +0.0 + 0 +ENDBLK + 5 +1577 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D52 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D52 + 1 + + 0 +LINE + 5 +1DF5 + 8 +0 + 62 + 0 + 10 +23925.740356702401 + 20 +682.56152228546125 + 30 +0.0 + 11 +23925.740356702401 + 21 +1624.7724056287991 + 31 +0.0 + 0 +LINE + 5 +1DF6 + 8 +0 + 62 + 0 + 10 +23925.740356702401 + 20 +1624.7724056287991 + 30 +0.0 + 11 +25157.97004022932 + 21 +1629.772405628798 + 31 +0.0 + 0 +LINE + 5 +1DF7 + 8 +0 + 62 + 0 + 10 +25157.97004022932 + 20 +1629.772405628798 + 30 +0.0 + 11 +25157.97004022932 + 21 +3735.397405628798 + 31 +0.0 + 0 +TEXT + 5 +1DF8 + 8 +1 + 62 + 0 + 10 +25157.34504022932 + 20 +1635.397405628803 + 30 +0.0 + 40 +300.0 + 1 +26524.29 + 50 +90.0 + 0 +POINT + 5 +1DF9 + 8 +DEFPOINTS + 62 + 0 + 10 +23925.740356702401 + 20 +681.93652228546125 + 30 +0.0 + 0 +POINT + 5 +1DFA + 8 +DEFPOINTS + 62 + 0 + 10 +25157.97004022932 + 20 +1634.7724056287991 + 30 +0.0 + 0 +POINT + 5 +1DFB + 8 +DEFPOINTS + 62 + 0 + 10 +-2598.548049632634 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +15AC + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D53 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D53 + 1 + + 0 +LINE + 5 +181C + 8 +0 + 62 + 0 + 10 +33946.837039770689 + 20 +19578.32468523999 + 30 +0.0 + 11 +34632.087135132409 + 21 +18893.07458987827 + 31 +0.0 + 0 +LINE + 5 +181D + 8 +0 + 62 + 0 + 10 +37482.370945703427 + 20 +23113.85859117272 + 30 +0.0 + 11 +38167.621041065147 + 21 +22428.608495811 + 31 +0.0 + 0 +LINE + 5 +181E + 8 +0 + 62 + 0 + 10 +34720.475482780726 + 20 +19158.239632823221 + 30 +0.0 + 11 +37902.455998120189 + 21 +22340.220148162691 + 31 +0.0 + 0 +SOLID + 5 +181F + 8 +0 + 62 + 0 + 10 +34691.012700231287 + 20 +19187.70241537266 + 30 +0.0 + 11 +34749.938265330173 + 21 +19128.776850273782 + 31 +0.0 + 12 +34543.6987874841 + 22 +18981.462937526579 + 32 +0.0 + 13 +34543.6987874841 + 23 +18981.462937526579 + 33 +0.0 + 0 +SOLID + 5 +1820 + 8 +0 + 62 + 0 + 10 +37872.993215570757 + 20 +22369.68293071213 + 30 +0.0 + 11 +37931.918780669643 + 21 +22310.757365613252 + 31 +0.0 + 12 +38079.23269341683 + 22 +22516.996843459321 + 32 +0.0 + 13 +38079.23269341683 + 23 +22516.996843459321 + 33 +0.0 + 0 +TEXT + 5 +1821 + 8 +1 + 62 + 0 + 10 +35931.3958455627 + 20 +20457.548343253489 + 30 +0.0 + 40 +300.0 + 1 +5000 + 50 +45.0 + 0 +POINT + 5 +1822 + 8 +DEFPOINTS + 62 + 0 + 10 +33902.642865946531 + 20 +19622.518859064148 + 30 +0.0 + 0 +POINT + 5 +1823 + 8 +DEFPOINTS + 62 + 0 + 10 +37438.176771879269 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +1824 + 8 +DEFPOINTS + 62 + 0 + 10 +38079.23269341683 + 20 +22516.996843459321 + 30 +0.0 + 0 +ENDBLK + 5 +168E + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D54 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D54 + 1 + + 0 +LINE + 5 +1825 + 8 +0 + 62 + 0 + 10 +36421.710773923609 + 20 +24262.90711060086 + 30 +0.0 + 11 +37033.396108295223 + 21 +24874.59244497247 + 31 +0.0 + 0 +LINE + 5 +1826 + 8 +0 + 62 + 0 + 10 +37482.370945703427 + 20 +23202.246938821041 + 30 +0.0 + 11 +38094.056280075041 + 21 +23813.932273192651 + 31 +0.0 + 0 +LINE + 5 +1827 + 8 +0 + 62 + 0 + 10 +37121.78445594354 + 20 +24609.427402027519 + 30 +0.0 + 11 +37828.89123713009 + 21 +23902.320620840968 + 31 +0.0 + 0 +SOLID + 5 +1828 + 8 +0 + 62 + 0 + 10 +37151.247238492979 + 20 +24638.890184576951 + 30 +0.0 + 11 +37092.321673394101 + 21 +24579.96461947808 + 31 +0.0 + 12 +36945.007760646899 + 22 +24786.204097324149 + 32 +0.0 + 13 +36945.007760646899 + 23 +24786.204097324149 + 33 +0.0 + 0 +SOLID + 5 +1829 + 8 +0 + 62 + 0 + 10 +37858.354019679529 + 20 +23931.7834033904 + 30 +0.0 + 11 +37799.428454580651 + 21 +23872.857838291529 + 31 +0.0 + 12 +38005.667932426717 + 22 +23725.543925544331 + 32 +0.0 + 13 +38005.667932426717 + 23 +23725.543925544331 + 33 +0.0 + 0 +TEXT + 5 +182A + 8 +1 + 62 + 0 + 10 +37201.333968827021 + 20 +24618.266236792351 + 30 +0.0 + 40 +300.0 + 1 +1500 + 50 +315.0 + 0 +POINT + 5 +182B + 8 +DEFPOINTS + 62 + 0 + 10 +36377.51660009945 + 20 +24218.712936776701 + 30 +0.0 + 0 +POINT + 5 +182C + 8 +DEFPOINTS + 62 + 0 + 10 +37438.176771879269 + 20 +23158.052764996879 + 30 +0.0 + 0 +POINT + 5 +182D + 8 +DEFPOINTS + 62 + 0 + 10 +38005.667932426717 + 20 +23725.543925544331 + 30 +0.0 + 0 +ENDBLK + 5 +169B + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D55 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D55 + 1 + + 0 +LINE + 5 +182E + 8 +0 + 62 + 0 + 10 +34061.617553885691 + 20 +26900.654083678131 + 30 +0.0 + 11 +34061.617553885691 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +182F + 8 +0 + 62 + 0 + 10 +39061.617553885691 + 20 +26900.654083678131 + 30 +0.0 + 11 +39061.617553885691 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +1830 + 8 +0 + 62 + 0 + 10 +34311.617553885691 + 20 +26056.56410520013 + 30 +0.0 + 11 +38811.617553885691 + 21 +26056.56410520013 + 31 +0.0 + 0 +SOLID + 5 +1831 + 8 +0 + 62 + 0 + 10 +34311.617553885691 + 20 +26098.230771866791 + 30 +0.0 + 11 +34311.617553885691 + 21 +26014.897438533459 + 31 +0.0 + 12 +34061.617553885691 + 22 +26056.56410520013 + 32 +0.0 + 13 +34061.617553885691 + 23 +26056.56410520013 + 33 +0.0 + 0 +SOLID + 5 +1832 + 8 +0 + 62 + 0 + 10 +38811.617553885691 + 20 +26098.230771866791 + 30 +0.0 + 11 +38811.617553885691 + 21 +26014.897438533459 + 31 +0.0 + 12 +39061.617553885691 + 22 +26056.56410520013 + 32 +0.0 + 13 +39061.617553885691 + 23 +26056.56410520013 + 33 +0.0 + 0 +TEXT + 5 +1833 + 8 +1 + 62 + 0 + 10 +36086.617553885691 + 20 +26119.064105200119 + 30 +0.0 + 40 +300.0 + 1 +5000 + 0 +POINT + 5 +1834 + 8 +DEFPOINTS + 62 + 0 + 10 +34061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +POINT + 5 +1835 + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +POINT + 5 +1836 + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +26056.56410520013 + 30 +0.0 + 0 +ENDBLK + 5 +16BB + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D56 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D56 + 1 + + 0 +LINE + 5 +1837 + 8 +0 + 62 + 0 + 10 +39124.117553885691 + 20 +28463.154083678131 + 30 +0.0 + 11 +39989.171249658742 + 21 +28463.154083678131 + 31 +0.0 + 0 +LINE + 5 +1838 + 8 +0 + 62 + 0 + 10 +39124.117553885691 + 20 +26963.154083678131 + 30 +0.0 + 11 +39989.171249658742 + 21 +26963.154083678131 + 31 +0.0 + 0 +LINE + 5 +1839 + 8 +0 + 62 + 0 + 10 +39864.171249658742 + 20 +28213.154083678131 + 30 +0.0 + 11 +39864.171249658742 + 21 +27213.154083678131 + 31 +0.0 + 0 +SOLID + 5 +183A + 8 +0 + 62 + 0 + 10 +39822.504582992071 + 20 +28213.154083678131 + 30 +0.0 + 11 +39905.837916325399 + 21 +28213.154083678131 + 31 +0.0 + 12 +39864.171249658742 + 22 +28463.154083678131 + 32 +0.0 + 13 +39864.171249658742 + 23 +28463.154083678131 + 33 +0.0 + 0 +SOLID + 5 +183B + 8 +0 + 62 + 0 + 10 +39822.504582992071 + 20 +27213.154083678131 + 30 +0.0 + 11 +39905.837916325399 + 21 +27213.154083678131 + 31 +0.0 + 12 +39864.171249658742 + 22 +26963.154083678131 + 32 +0.0 + 13 +39864.171249658742 + 23 +26963.154083678131 + 33 +0.0 + 0 +TEXT + 5 +183C + 8 +1 + 62 + 0 + 10 +39801.671249658728 + 20 +27263.154083678131 + 30 +0.0 + 40 +300.0 + 1 +1500 + 50 +90.0 + 0 +POINT + 5 +183D + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +POINT + 5 +183E + 8 +DEFPOINTS + 62 + 0 + 10 +39061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +POINT + 5 +183F + 8 +DEFPOINTS + 62 + 0 + 10 +39864.171249658742 + 20 +26963.154083678131 + 30 +0.0 + 0 +ENDBLK + 5 +16C7 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D57 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D57 + 1 + + 0 +LINE + 5 +1E06 + 8 +1 + 62 + 0 + 10 +24000.0 + 20 +703.98900868305645 + 30 +0.0 + 11 +24000.0 + 21 +1656.7748429744529 + 31 +0.0 + 0 +LINE + 5 +1E07 + 8 +1 + 62 + 0 + 10 +24000.0 + 20 +1656.7748429744529 + 30 +0.0 + 11 +24978.462537397962 + 21 +1661.7748429744529 + 31 +0.0 + 0 +LINE + 5 +1E08 + 8 +1 + 62 + 0 + 10 +24978.462537397962 + 20 +1661.7748429744529 + 30 +0.0 + 11 +24978.462537397962 + 21 +2917.3998429744529 + 31 +0.0 + 0 +TEXT + 5 +1E09 + 8 +1 + 62 + 0 + 10 +24977.837537397962 + 20 +1667.399842974457 + 30 +0.0 + 40 +300.0 + 1 +24000 + 50 +90.0 + 0 +POINT + 5 +1E0A + 8 +DEFPOINTS + 62 + 0 + 10 +24000.0 + 20 +703.36400868305645 + 30 +0.0 + 0 +POINT + 5 +1E0B + 8 +DEFPOINTS + 62 + 0 + 10 +24978.462537397962 + 20 +1666.7748429744529 + 30 +0.0 + 0 +POINT + 5 +1E0C + 8 +DEFPOINTS + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1E05 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D58 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D58 + 1 + + 0 +LINE + 5 +1F20 + 8 +1 + 62 + 0 + 10 +25446.29486998995 + 20 +794.91766210896446 + 30 +0.0 + 11 +25446.29486998995 + 21 +1778.6664119135239 + 31 +0.0 + 0 +LINE + 5 +1F21 + 8 +1 + 62 + 0 + 10 +26446.29486998995 + 20 +794.91766210896446 + 30 +0.0 + 11 +26446.29486998995 + 21 +1778.6664119135239 + 31 +0.0 + 0 +LINE + 5 +1F22 + 8 +1 + 62 + 0 + 10 +25696.29486998995 + 20 +1653.6664119135239 + 30 +0.0 + 11 +26196.294869989961 + 21 +1653.6664119135239 + 31 +0.0 + 0 +LINE + 5 +1F23 + 8 +1 + 62 + 0 + 10 +26446.29486998995 + 20 +1653.6664119135239 + 30 +0.0 + 11 +28171.29486998995 + 21 +1653.6664119135239 + 31 +0.0 + 0 +SOLID + 5 +1F24 + 8 +1 + 62 + 0 + 10 +25696.29486998995 + 20 +1695.33307858019 + 30 +0.0 + 11 +25696.29486998995 + 21 +1611.9997452468569 + 31 +0.0 + 12 +25446.29486998995 + 22 +1653.6664119135239 + 32 +0.0 + 13 +25446.29486998995 + 23 +1653.6664119135239 + 33 +0.0 + 0 +SOLID + 5 +1F25 + 8 +1 + 62 + 0 + 10 +26196.294869989961 + 20 +1695.33307858019 + 30 +0.0 + 11 +26196.294869989961 + 21 +1611.9997452468569 + 31 +0.0 + 12 +26446.29486998995 + 22 +1653.6664119135239 + 32 +0.0 + 13 +26446.29486998995 + 23 +1653.6664119135239 + 33 +0.0 + 0 +TEXT + 5 +1F26 + 8 +1 + 62 + 0 + 10 +26758.79486998995 + 20 +1716.1664119135239 + 30 +0.0 + 40 +300.0 + 1 +<1000> + 0 +POINT + 5 +1F27 + 8 +DEFPOINTS + 62 + 0 + 10 +25446.29486998995 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1F28 + 8 +DEFPOINTS + 62 + 0 + 10 +26446.29486998995 + 20 +732.41766210896446 + 30 +0.0 + 0 +POINT + 5 +1F29 + 8 +DEFPOINTS + 62 + 0 + 10 +26446.29486998995 + 20 +1653.6664119135239 + 30 +0.0 + 0 +ENDBLK + 5 +1E1B + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*D59 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D59 + 1 + + 0 +LINE + 5 +1F64 + 8 +1 + 62 + 0 + 10 +21762.532893255539 + 20 +700.0 + 30 +0.0 + 11 +22509.702402746399 + 21 +700.0 + 31 +0.0 + 0 +LINE + 5 +1F65 + 8 +1 + 62 + 0 + 10 +22509.702402746399 + 20 +700.0 + 30 +0.0 + 11 +22514.702402746399 + 21 +1660.4010289869841 + 31 +0.0 + 0 +LINE + 5 +1F66 + 8 +1 + 62 + 0 + 10 +22514.702402746399 + 20 +1660.4010289869841 + 30 +0.0 + 11 +23220.327402746399 + 21 +1660.4010289869841 + 31 +0.0 + 0 +TEXT + 5 +1F67 + 8 +1 + 62 + 0 + 10 +22520.327402746399 + 20 +1661.0260289869841 + 30 +0.0 + 40 +300.0 + 1 +700 + 0 +POINT + 5 +1F68 + 8 +DEFPOINTS + 62 + 0 + 10 +21761.907893255539 + 20 +700.0 + 30 +0.0 + 0 +POINT + 5 +1F69 + 8 +DEFPOINTS + 62 + 0 + 10 +22519.702402746399 + 20 +1660.4010289869841 + 30 +0.0 + 0 +POINT + 5 +1F6A + 8 +DEFPOINTS + 62 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1F5C + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*U60 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U60 + 1 + + 0 +TEXT + 5 +2113 + 8 +1 + 10 +16593.569701355282 + 20 +28715.175552153119 + 30 +0.0 + 40 +500.0 + 1 +‚Qs‚Ì + 50 +270.0 + 7 +KANJI4 + 0 +TEXT + 5 +2114 + 8 +1 + 10 +15729.77951523007 + 20 +28715.175552153119 + 30 +0.0 + 40 +500.0 + 1 +ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 50 +270.0 + 7 +KANJI4 + 0 +ENDBLK + 5 +2116 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*X61 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*X61 + 1 + + 0 +LINE + 5 +2131 + 8 +0 + 62 + 0 + 10 +40081.717347096652 + 20 +13879.054869113421 + 30 +0.0 + 11 +40498.453572004983 + 21 +14295.79109402177 + 31 +0.0 + 0 +LINE + 5 +2132 + 8 +0 + 62 + 0 + 10 +39632.704541043189 + 20 +13879.054869113421 + 30 +0.0 + 11 +40498.45357200499 + 21 +14744.80390007522 + 31 +0.0 + 0 +LINE + 5 +2133 + 8 +0 + 62 + 0 + 10 +39183.691734989727 + 20 +13879.054869113421 + 30 +0.0 + 11 +40498.453572004983 + 21 +15193.81670612868 + 31 +0.0 + 0 +LINE + 5 +2134 + 8 +0 + 62 + 0 + 10 +38734.678928936279 + 20 +13879.054869113421 + 30 +0.0 + 11 +40498.453572004983 + 21 +15642.82951218213 + 31 +0.0 + 0 +LINE + 5 +2135 + 8 +0 + 62 + 0 + 10 +38285.666122882809 + 20 +13879.054869113421 + 30 +0.0 + 11 +40285.666122882809 + 21 +15879.054869113421 + 31 +0.0 + 0 +LINE + 5 +2136 + 8 +0 + 62 + 0 + 10 +37836.653316829361 + 20 +13879.054869113421 + 30 +0.0 + 11 +39836.653316829361 + 21 +15879.054869113421 + 31 +0.0 + 0 +LINE + 5 +2137 + 8 +0 + 62 + 0 + 10 +37649.984925865952 + 20 +14141.39928420347 + 30 +0.0 + 11 +39387.640510775898 + 21 +15879.054869113421 + 31 +0.0 + 0 +LINE + 5 +2138 + 8 +0 + 62 + 0 + 10 +37649.984925865952 + 20 +14590.412090256919 + 30 +0.0 + 11 +38938.627704722443 + 21 +15879.054869113421 + 31 +0.0 + 0 +LINE + 5 +2139 + 8 +0 + 62 + 0 + 10 +37649.984925865952 + 20 +15039.42489631038 + 30 +0.0 + 11 +38489.614898668988 + 21 +15879.054869113421 + 31 +0.0 + 0 +LINE + 5 +213A + 8 +0 + 62 + 0 + 10 +37649.984925865952 + 20 +15488.437702363841 + 30 +0.0 + 11 +38040.602092615532 + 21 +15879.054869113421 + 31 +0.0 + 0 +ENDBLK + 5 +213C + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*U62 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U62 + 1 + + 0 +TEXT + 5 +213E + 8 +1 + 10 +804.37481723576946 + 20 +14004.754277329281 + 30 +0.0 + 40 +500.0 + 1 +2s‚Ì + 7 +KANJI2 + 0 +TEXT + 5 +213F + 8 +1 + 10 +834.83167002764765 + 20 +13156.1925176 + 30 +0.0 + 40 +500.0 + 1 +ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI2 + 0 +ENDBLK + 5 +2141 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*U63 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U63 + 1 + + 0 +TEXT + 5 +2143 + 8 +1 + 10 +8432.9106362633847 + 20 +14017.44463265931 + 30 +0.0 + 40 +500.0 + 1 +2s‚Ì + 7 +KANJI + 0 +TEXT + 5 +2144 + 8 +1 + 10 +8432.9106362633847 + 20 +13184.111299325979 + 30 +0.0 + 40 +500.0 + 1 +ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI + 0 +ENDBLK + 5 +2146 + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*U64 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U64 + 1 + + 0 +TEXT + 5 +2148 + 8 +1 + 10 +16113.20602565925 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +2s‚Ì + 7 +KANJI3 + 0 +TEXT + 5 +2149 + 8 +1 + 10 +16879.87269232592 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI3 + 0 +ENDBLK + 5 +214B + 8 +0 + 0 +BLOCK + 8 +0 + 2 +*U65 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U65 + 1 + + 0 +LINE + 5 +216D + 8 +1 + 10 +22959.563446334669 + 20 +9465.4792345465085 + 30 +0.0 + 11 +22397.063446334669 + 21 +8491.2006552890161 + 31 +0.0 + 0 +LINE + 5 +216E + 8 +1 + 10 +21834.56344633468 + 20 +9465.4792345465085 + 30 +0.0 + 11 +22959.563446334669 + 21 +9465.4792345465085 + 31 +0.0 + 0 +LINE + 5 +216F + 8 +1 + 10 +22959.563446334669 + 20 +7516.9220760315229 + 30 +0.0 + 11 +22397.063446334669 + 21 +8491.2006552890161 + 31 +0.0 + 0 +LINE + 5 +2170 + 8 +1 + 10 +21834.56344633468 + 20 +9465.4792345465085 + 30 +0.0 + 11 +21459.563446334669 + 21 +10114.998287384829 + 31 +0.0 + 0 +LINE + 5 +2171 + 8 +1 + 10 +22959.563446334669 + 20 +7516.9220760315229 + 30 +0.0 + 11 +21834.56344633468 + 21 +7516.9220760315229 + 31 +0.0 + 0 +LINE + 5 +2172 + 8 +1 + 10 +21084.563446334669 + 20 +9465.4792345465085 + 30 +0.0 + 11 +21459.563446334669 + 21 +10114.998287384829 + 31 +0.0 + 0 +LINE + 5 +2173 + 8 +1 + 10 +21834.56344633468 + 20 +7516.9220760315229 + 30 +0.0 + 11 +21459.563446334669 + 21 +6867.4030231931938 + 31 +0.0 + 0 +LINE + 5 +2174 + 8 +1 + 10 +19959.56344633468 + 20 +9465.4792345465085 + 30 +0.0 + 11 +21084.563446334669 + 21 +9465.4792345465085 + 31 +0.0 + 0 +LINE + 5 +2175 + 8 +1 + 10 +21084.563446334669 + 20 +7516.9220760315229 + 30 +0.0 + 11 +21459.563446334669 + 21 +6867.4030231931938 + 31 +0.0 + 0 +LINE + 5 +2176 + 8 +1 + 10 +19959.56344633468 + 20 +9465.4792345465085 + 30 +0.0 + 11 +20522.063446334669 + 21 +8491.2006552890161 + 31 +0.0 + 0 +LINE + 5 +2177 + 8 +1 + 10 +21084.563446334669 + 20 +7516.9220760315229 + 30 +0.0 + 11 +19959.56344633468 + 21 +7516.9220760315229 + 31 +0.0 + 0 +LINE + 5 +2178 + 8 +1 + 10 +19959.56344633468 + 20 +7516.9220760315229 + 30 +0.0 + 11 +20522.063446334669 + 21 +8491.2006552890161 + 31 +0.0 + 0 +ENDBLK + 5 +217A + 8 +0 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +POLYLINE + 5 +16E + 8 +1 + 62 + 0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +210D + 8 +1 + 62 + 0 + 10 +32841.982694166712 + 20 +20683.17903084397 + 30 +0.0 + 0 +VERTEX + 5 +210E + 8 +1 + 62 + 0 + 10 +36377.51660009945 + 20 +24218.712936776701 + 30 +0.0 + 0 +VERTEX + 5 +210F + 8 +1 + 62 + 0 + 10 +37438.176771879269 + 20 +23158.052764996879 + 30 +0.0 + 0 +VERTEX + 5 +2110 + 8 +1 + 62 + 0 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 0 +SEQEND + 5 +2111 + 8 +1 + 62 + 0 + 0 +INSERT + 5 +170 + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 2 +*U1 + 10 +51.460251012922981 + 20 +61.75531173110096 + 30 +0.0 + 0 +TEXT + 5 +171 + 8 +1 + 6 +CONTINUOUS + 62 + 7 + 10 +51.460251012922981 + 20 +61.75531173110096 + 30 +0.0 + 40 +1000.0 + 1 +A3 1/100 + 41 +0.5200000000000001 + 7 +KANJI + 0 +TEXT + 5 +172 + 8 +1 + 10 +834.83167002764822 + 20 +8032.8686155686946 + 30 +0.0 + 40 +500.0 + 1 +DOT + 7 +KANJI2 + 0 +LINE + 5 +173 + 8 +1 + 10 +834.83167002764822 + 20 +12032.86861556869 + 30 +0.0 + 11 +7734.4503301242512 + 21 +12032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +174 + 8 +1 + 10 +834.83167002764822 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(CONTINUOUS) + 7 +KANJI2 + 0 +LINE + 5 +175 + 8 +1 + 6 +CONTINUOUS + 10 +834.83167002764822 + 20 +11032.86861556869 + 30 +0.0 + 11 +7734.4503301242512 + 21 +11032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +176 + 8 +1 + 10 +834.83167002764822 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +CONTINUOUS + 7 +KANJI2 + 0 +TEXT + 5 +177 + 8 +1 + 10 +834.83167002764822 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +DASHDOT + 7 +KANJI2 + 0 +LINE + 5 +178 + 8 +1 + 6 +DASHDOT + 10 +834.83167002764822 + 20 +10032.86861556869 + 30 +0.0 + 11 +7734.4503301242512 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +179 + 8 +1 + 6 +DIVIDE + 10 +834.83167002764822 + 20 +9032.8686155686955 + 30 +0.0 + 11 +7734.4503301242512 + 21 +9032.8686155686955 + 31 +0.0 + 0 +TEXT + 5 +17A + 8 +1 + 10 +834.83167002764822 + 20 +9032.8686155686955 + 30 +0.0 + 40 +500.0 + 1 +DIVIDE + 7 +KANJI2 + 0 +LINE + 5 +17B + 8 +1 + 6 +DOT + 10 +834.83167002764822 + 20 +8032.8686155686946 + 30 +0.0 + 11 +7734.4503301242512 + 21 +8032.8686155686946 + 31 +0.0 + 0 +LINE + 5 +17C + 8 +1 + 6 +HIDDEN + 10 +834.83167002764822 + 20 +7032.8686155686946 + 30 +0.0 + 11 +7734.4503301242512 + 21 +7032.8686155686946 + 31 +0.0 + 0 +TEXT + 5 +17D + 8 +1 + 10 +834.83167002764822 + 20 +7032.8686155686946 + 30 +0.0 + 40 +500.0 + 1 +HIDDEN + 7 +KANJI2 + 0 +LINE + 5 +17E + 8 +1 + 10 +15709.47494670215 + 20 +28715.175552153119 + 30 +0.0 + 11 +15709.47494670215 + 21 +24182.269967974469 + 31 +0.0 + 0 +LINE + 5 +17F + 8 +1 + 10 +17116.412340949191 + 20 +28715.175552153119 + 30 +0.0 + 11 +17116.412340949191 + 21 +24182.269967974469 + 31 +0.0 + 0 +INSERT + 5 +180 + 8 +1 + 2 +*U60 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +LINE + 5 +181 + 8 +1 + 10 +17116.412340949191 + 20 +28715.175552153119 + 30 +0.0 + 11 +15709.47494670215 + 21 +28715.175552153119 + 31 +0.0 + 0 +LINE + 5 +182 + 8 +1 + 10 +15709.47494670215 + 20 +24182.269967974469 + 30 +0.0 + 11 +17116.412340949191 + 21 +24182.269967974469 + 31 +0.0 + 0 +TEXT + 5 +183 + 8 +1 + 10 +8432.9106362633902 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(White/Black) + 7 +KANJI2 + 0 +LINE + 5 +184 + 8 +1 + 62 + 1 + 10 +8432.9106362633902 + 20 +11032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +11032.86861556869 + 31 +0.0 + 0 +LINE + 5 +185 + 8 +1 + 10 +8432.9106362633902 + 20 +12032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +12032.86861556869 + 31 +0.0 + 0 +LINE + 5 +186 + 8 +1 + 62 + 2 + 10 +8432.9106362633902 + 20 +10032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +187 + 8 +1 + 62 + 3 + 10 +8432.9106362633902 + 20 +9032.8686155686955 + 30 +0.0 + 11 +15332.52929635998 + 21 +9032.8686155686955 + 31 +0.0 + 0 +LINE + 5 +188 + 8 +1 + 62 + 4 + 10 +8432.9106362633902 + 20 +8032.8686155686946 + 30 +0.0 + 11 +15332.52929635998 + 21 +8032.8686155686946 + 31 +0.0 + 0 +LINE + 5 +189 + 8 +1 + 62 + 113 + 10 +8432.9106362633902 + 20 +7032.8686155686946 + 30 +0.0 + 11 +15332.52929635998 + 21 +7032.8686155686946 + 31 +0.0 + 0 +TEXT + 5 +18A + 8 +1 + 62 + 2 + 10 +8432.9106362633902 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Yellow + 7 +KANJI2 + 0 +TEXT + 5 +18B + 8 +1 + 62 + 113 + 10 +8432.9106362633902 + 20 +7032.8686155686946 + 30 +0.0 + 40 +500.0 + 1 +ƒpƒŒƒbƒg113 + 7 +KANJI2 + 0 +TEXT + 5 +18C + 8 +1 + 62 + 4 + 10 +8432.9106362633902 + 20 +8032.8686155686946 + 30 +0.0 + 40 +500.0 + 1 +Cyan + 7 +KANJI2 + 0 +TEXT + 5 +18D + 8 +1 + 62 + 3 + 10 +8432.9106362633902 + 20 +9032.8686155686955 + 30 +0.0 + 40 +500.0 + 1 +Green + 7 +KANJI2 + 0 +TEXT + 5 +18E + 8 +1 + 62 + 1 + 10 +8432.9106362633902 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Red + 7 +KANJI2 + 0 +TEXT + 5 +18F + 8 +1 + 10 +26269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +26769.848383258621 + 21 +25791.317684132831 + 31 +0.0 + 73 + 3 + 0 +LINE + 5 +190 + 8 +1 + 10 +18739.863999123081 + 20 +23517.206009005899 + 30 +0.0 + 11 +18739.863999123081 + 21 +28715.175552153119 + 31 +0.0 + 0 +TEXT + 5 +191 + 8 +1 + 10 +17739.86399912307 + 20 +28715.175552153119 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +17739.86399912307 + 21 +23517.206009005909 + 31 +0.0 + 0 +LINE + 5 +192 + 8 +1 + 10 +17739.86399912307 + 20 +28715.175552153119 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.206009005899 + 31 +0.0 + 0 +LINE + 5 +193 + 8 +1 + 10 +19769.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +19769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +194 + 8 +1 + 10 +19269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +19269.848383258632 + 21 +23517.210080071902 + 31 +0.0 + 0 +TEXT + 5 +195 + 8 +1 + 10 +19269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +19178.47782488299 + 21 +23517.206009005909 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +196 + 8 +1 + 10 +20269.848383258632 + 20 +28715.175552153119 + 30 +0.0 + 11 +20269.848383258632 + 21 +22867.465922711501 + 31 +0.0 + 0 +LINE + 5 +197 + 8 +1 + 10 +20769.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +20769.848383258632 + 21 +22867.465922711501 + 31 +0.0 + 0 +TEXT + 5 +198 + 8 +1 + 10 +20269.848383258632 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +20178.47782488299 + 21 +25791.31768413282 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +199 + 8 +1 + 10 +21269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +21269.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +19A + 8 +1 + 10 +21769.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +21769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +19B + 8 +1 + 10 +21269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 50 +270.0 + 7 +KANJI4 + 11 +21178.47782488299 + 21 +28715.175552153119 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +19C + 8 +1 + 10 +22769.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.848383258632 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +19D + 8 +1 + 10 +22269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +22269.848383258639 + 21 +22867.465922711512 + 31 +0.0 + 0 +TEXT + 5 +19E + 8 +1 + 10 +22269.848383258632 + 20 +28715.175552153119 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +22519.848383258632 + 21 +22867.459816112521 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +19F + 8 +1 + 10 +23769.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1A0 + 8 +1 + 10 +23269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +23269.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +TEXT + 5 +1A1 + 8 +1 + 10 +23269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +23519.848383258621 + 21 +26116.19078057952 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +1A2 + 8 +1 + 10 +24769.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.848383258632 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +1A3 + 8 +1 + 10 +24269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +24269.848383258632 + 21 +22867.465922711512 + 31 +0.0 + 0 +TEXT + 5 +1A4 + 8 +1 + 10 +24269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 50 +270.0 + 7 +KANJI4 + 11 +24519.848383258621 + 21 +28715.17555215313 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +1A5 + 8 +1 + 10 +25269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 11 +25269.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1A6 + 8 +1 + 10 +25769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +25769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +TEXT + 5 +1A7 + 8 +1 + 10 +25269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +25769.848383258632 + 21 +23517.206009005931 + 31 +0.0 + 73 + 3 + 0 +LINE + 5 +1A8 + 8 +1 + 10 +26269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +26269.848383258639 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +1A9 + 8 +1 + 10 +26769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +26769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +1AA + 8 +1 + 10 +17739.86399912307 + 20 +28715.175552153119 + 30 +0.0 + 11 +18739.86399912307 + 21 +28715.175552153119 + 31 +0.0 + 0 +LINE + 5 +1AB + 8 +1 + 10 +19269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +19769.848383258621 + 21 +28715.175552153119 + 31 +0.0 + 0 +LINE + 5 +1AC + 8 +1 + 10 +20269.848383258632 + 20 +28715.175552153119 + 30 +0.0 + 11 +20769.848383258621 + 21 +28715.175552153119 + 31 +0.0 + 0 +LINE + 5 +1AD + 8 +1 + 10 +21269.848383258621 + 20 +28715.175552153119 + 30 +0.0 + 11 +21769.848383258621 + 21 +28715.175552153119 + 31 +0.0 + 0 +LINE + 5 +1AE + 8 +1 + 10 +24269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.848383258621 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1AF + 8 +1 + 10 +23269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.848383258621 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B0 + 8 +1 + 10 +22269.848383258621 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.848383258621 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B1 + 8 +1 + 10 +25269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 11 +25769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +1B2 + 8 +1 + 10 +26269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +26769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +1B3 + 8 +1 + 10 +19269.848383258621 + 20 +28065.428952153121 + 30 +0.0 + 11 +19769.848383258621 + 21 +28065.428952153121 + 31 +0.0 + 0 +LINE + 5 +1B4 + 8 +1 + 10 +19269.848383258621 + 20 +27415.682352153119 + 30 +0.0 + 11 +19769.848383258621 + 21 +27415.682352153119 + 31 +0.0 + 0 +LINE + 5 +1B5 + 8 +1 + 10 +19269.848383258621 + 20 +26765.93575215312 + 30 +0.0 + 11 +19769.848383258621 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1B6 + 8 +1 + 10 +19269.848383258621 + 20 +26116.189152153122 + 30 +0.0 + 11 +19769.848383258621 + 21 +26116.189152153122 + 31 +0.0 + 0 +LINE + 5 +1B7 + 8 +1 + 10 +19269.848383258621 + 20 +25466.442552153119 + 30 +0.0 + 11 +19769.848383258621 + 21 +25466.442552153119 + 31 +0.0 + 0 +LINE + 5 +1B8 + 8 +1 + 10 +20269.848383258632 + 20 +27415.682352153119 + 30 +0.0 + 11 +20769.848383258621 + 21 +27415.682352153119 + 31 +0.0 + 0 +LINE + 5 +1B9 + 8 +1 + 10 +20269.848383258632 + 20 +28065.428952153121 + 30 +0.0 + 11 +20769.848383258621 + 21 +28065.428952153121 + 31 +0.0 + 0 +LINE + 5 +1BA + 8 +1 + 10 +20269.848383258632 + 20 +26765.93575215312 + 30 +0.0 + 11 +20769.848383258621 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BB + 8 +1 + 10 +21269.848383258621 + 20 +27415.682352153119 + 30 +0.0 + 11 +21769.848383258621 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1BC + 8 +1 + 10 +21269.848383258621 + 20 +28065.428952153121 + 30 +0.0 + 11 +21769.848383258621 + 21 +28065.428952153121 + 31 +0.0 + 0 +LINE + 5 +1BD + 8 +1 + 10 +21269.848383258621 + 20 +26765.93575215312 + 30 +0.0 + 11 +21769.848383258621 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BE + 8 +1 + 10 +20269.848383258632 + 20 +26116.189152153129 + 30 +0.0 + 11 +20769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1BF + 8 +1 + 10 +20269.848383258632 + 20 +25466.442552153119 + 30 +0.0 + 11 +20769.848383258621 + 21 +25466.442552153119 + 31 +0.0 + 0 +LINE + 5 +1C0 + 8 +1 + 10 +21269.848383258621 + 20 +26116.189152153129 + 30 +0.0 + 11 +21769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1C1 + 8 +1 + 10 +21269.848383258621 + 20 +25466.44255215313 + 30 +0.0 + 11 +21769.848383258621 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1C2 + 8 +1 + 10 +19269.848383258632 + 20 +24816.698394792711 + 30 +0.0 + 11 +19269.848383258632 + 21 +24816.698394792711 + 31 +0.0 + 0 +LINE + 5 +1C3 + 8 +1 + 10 +19269.848383258632 + 20 +24816.698394792711 + 30 +0.0 + 11 +19769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1C4 + 8 +1 + 10 +19269.848383258639 + 20 +24166.95423743231 + 30 +0.0 + 11 +19269.848383258639 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C5 + 8 +1 + 10 +19269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +19769.848383258632 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C6 + 8 +1 + 10 +19269.848383258639 + 20 +23517.210080071902 + 30 +0.0 + 11 +19269.848383258639 + 21 +23517.210080071902 + 31 +0.0 + 0 +LINE + 5 +1C7 + 8 +1 + 10 +19269.848383258632 + 20 +23517.210080071902 + 30 +0.0 + 11 +19769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1C9 + 8 +1 + 10 +20269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +20769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1CA + 8 +1 + 10 +20269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +20769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1CB + 8 +1 + 10 +20269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +20269.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1CC + 8 +1 + 10 +20269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +20269.848383258632 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1CD + 8 +1 + 10 +20269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +20769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1CE + 8 +1 + 10 +20269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +20269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1CF + 8 +1 + 10 +21269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +21769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1D0 + 8 +1 + 10 +21269.848383258632 + 20 +24166.954237432321 + 30 +0.0 + 11 +21769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1D1 + 8 +1 + 10 +21269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +21269.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1D2 + 8 +1 + 10 +21269.848383258639 + 20 +24166.954237432321 + 30 +0.0 + 11 +21269.848383258639 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1D3 + 8 +1 + 10 +21269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +21769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1D4 + 8 +1 + 10 +21269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +21269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1D5 + 8 +1 + 10 +20269.848383258632 + 20 +22867.465922711501 + 30 +0.0 + 11 +20769.848383258632 + 21 +22867.465922711501 + 31 +0.0 + 0 +LINE + 5 +1D6 + 8 +1 + 10 +20269.848383258639 + 20 +22867.465922711501 + 30 +0.0 + 11 +20269.848383258639 + 21 +22867.465922711501 + 31 +0.0 + 0 +LINE + 5 +1D7 + 8 +1 + 10 +24269.848383258621 + 20 +25466.44255215313 + 30 +0.0 + 11 +24769.848383258621 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1D8 + 8 +1 + 10 +24269.848383258621 + 20 +26116.189152153129 + 30 +0.0 + 11 +24769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1D9 + 8 +1 + 10 +24269.848383258621 + 20 +26765.935752153131 + 30 +0.0 + 11 +24769.848383258621 + 21 +26765.935752153131 + 31 +0.0 + 0 +LINE + 5 +1DA + 8 +1 + 10 +24269.848383258621 + 20 +27415.68235215313 + 30 +0.0 + 11 +24769.848383258621 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DB + 8 +1 + 10 +24269.848383258621 + 20 +28065.428952153128 + 30 +0.0 + 11 +24769.848383258621 + 21 +28065.428952153128 + 31 +0.0 + 0 +LINE + 5 +1DC + 8 +1 + 10 +23269.848383258621 + 20 +26765.935752153131 + 30 +0.0 + 11 +23769.848383258621 + 21 +26765.935752153131 + 31 +0.0 + 0 +LINE + 5 +1DD + 8 +1 + 10 +23269.848383258621 + 20 +27415.68235215313 + 30 +0.0 + 11 +23769.848383258621 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DE + 8 +1 + 10 +23269.848383258621 + 20 +28065.428952153128 + 30 +0.0 + 11 +23769.848383258621 + 21 +28065.428952153128 + 31 +0.0 + 0 +LINE + 5 +1DF + 8 +1 + 10 +22269.848383258621 + 20 +27415.68235215313 + 30 +0.0 + 11 +22769.848383258621 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E0 + 8 +1 + 10 +22269.848383258621 + 20 +28065.428952153121 + 30 +0.0 + 11 +22769.848383258621 + 21 +28065.428952153128 + 31 +0.0 + 0 +LINE + 5 +1E1 + 8 +1 + 10 +22269.848383258621 + 20 +26765.935752153131 + 30 +0.0 + 11 +22769.848383258621 + 21 +26765.935752153131 + 31 +0.0 + 0 +LINE + 5 +1E2 + 8 +1 + 10 +23269.848383258621 + 20 +25466.442552153119 + 30 +0.0 + 11 +23769.848383258621 + 21 +25466.442552153119 + 31 +0.0 + 0 +LINE + 5 +1E3 + 8 +1 + 10 +23269.848383258621 + 20 +26116.189152153129 + 30 +0.0 + 11 +23769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1E4 + 8 +1 + 10 +22269.848383258621 + 20 +26116.189152153129 + 30 +0.0 + 11 +22769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1E5 + 8 +1 + 10 +22269.848383258621 + 20 +25466.44255215313 + 30 +0.0 + 11 +22769.848383258621 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1E6 + 8 +1 + 10 +25269.848383258632 + 20 +26765.935752153138 + 30 +0.0 + 11 +25769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +1E7 + 8 +1 + 10 +25269.848383258632 + 20 +27415.68235215313 + 30 +0.0 + 11 +25769.848383258621 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E8 + 8 +1 + 10 +25269.848383258632 + 20 +28065.428952153128 + 30 +0.0 + 11 +25769.848383258621 + 21 +28065.428952153128 + 31 +0.0 + 0 +LINE + 5 +1E9 + 8 +1 + 10 +26269.848383258621 + 20 +28065.428952153139 + 30 +0.0 + 11 +26769.848383258621 + 21 +28065.428952153139 + 31 +0.0 + 0 +LINE + 5 +1EA + 8 +1 + 10 +26269.848383258621 + 20 +27415.682352153141 + 30 +0.0 + 11 +26769.848383258621 + 21 +27415.682352153141 + 31 +0.0 + 0 +LINE + 5 +1EB + 8 +1 + 10 +26269.848383258621 + 20 +26765.935752153138 + 30 +0.0 + 11 +26769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +1EC + 8 +1 + 10 +25269.848383258632 + 20 +25466.44255215313 + 30 +0.0 + 11 +25769.848383258621 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1ED + 8 +1 + 10 +25269.848383258632 + 20 +26116.189152153129 + 30 +0.0 + 11 +25769.848383258621 + 21 +26116.189152153129 + 31 +0.0 + 0 +LINE + 5 +1EE + 8 +1 + 10 +26269.848383258621 + 20 +26116.18915215314 + 30 +0.0 + 11 +26769.848383258621 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +1EF + 8 +1 + 10 +26269.848383258621 + 20 +25466.44255215313 + 30 +0.0 + 11 +26769.848383258621 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1F0 + 8 +1 + 10 +24269.848383258632 + 20 +22867.465922711512 + 30 +0.0 + 11 +24769.848383258632 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +1F1 + 8 +1 + 10 +24269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +24769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1F2 + 8 +1 + 10 +24269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +24769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1F3 + 8 +1 + 10 +24269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +24769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1F4 + 8 +1 + 10 +23269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +23769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +1F5 + 8 +1 + 10 +23269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +23769.848383258632 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1F6 + 8 +1 + 10 +23269.848383258632 + 20 +24816.698394792711 + 30 +0.0 + 11 +23769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1F7 + 8 +1 + 10 +22269.848383258632 + 20 +24166.954237432321 + 30 +0.0 + 11 +22769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1F8 + 8 +1 + 10 +22269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +22769.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1F9 + 8 +1 + 10 +22269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +22269.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +1FA + 8 +1 + 10 +22269.848383258639 + 20 +24166.954237432321 + 30 +0.0 + 11 +22269.848383258639 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +1FB + 8 +1 + 10 +23269.848383258632 + 20 +24816.698394792711 + 30 +0.0 + 11 +23269.848383258632 + 21 +24816.698394792711 + 31 +0.0 + 0 +LINE + 5 +1FC + 8 +1 + 10 +23269.848383258639 + 20 +24166.95423743231 + 30 +0.0 + 11 +23269.848383258639 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1FD + 8 +1 + 10 +22269.848383258632 + 20 +23517.21008007192 + 30 +0.0 + 11 +22769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FE + 8 +1 + 10 +22269.848383258639 + 20 +23517.21008007192 + 30 +0.0 + 11 +22269.848383258639 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FF + 8 +1 + 10 +23269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +23269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +200 + 8 +1 + 10 +24269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +24269.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +201 + 8 +1 + 10 +24269.848383258632 + 20 +24166.95423743231 + 30 +0.0 + 11 +24269.848383258632 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +202 + 8 +1 + 10 +24269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +24269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +203 + 8 +1 + 10 +22269.848383258639 + 20 +22867.465922711512 + 30 +0.0 + 11 +22769.848383258632 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +204 + 8 +1 + 10 +22269.848383258639 + 20 +22867.465922711512 + 30 +0.0 + 11 +22269.848383258639 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +205 + 8 +1 + 10 +24269.848383258639 + 20 +22867.465922711512 + 30 +0.0 + 11 +24269.848383258639 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +206 + 8 +1 + 10 +25269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +25769.848383258632 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +207 + 8 +1 + 10 +25269.848383258632 + 20 +24166.954237432321 + 30 +0.0 + 11 +25769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +208 + 8 +1 + 10 +25269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +25769.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +209 + 8 +1 + 10 +25269.848383258632 + 20 +24816.698394792718 + 30 +0.0 + 11 +25269.848383258632 + 21 +24816.698394792718 + 31 +0.0 + 0 +LINE + 5 +20A + 8 +1 + 10 +25269.848383258632 + 20 +24166.954237432321 + 30 +0.0 + 11 +25269.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +20B + 8 +1 + 10 +25269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +25269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +20C + 8 +1 + 10 +26269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +26269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +20D + 8 +1 + 10 +26269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +26769.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +20E + 8 +1 + 10 +26269.848383258639 + 20 +24166.954237432321 + 30 +0.0 + 11 +26269.848383258639 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +20F + 8 +1 + 10 +26269.848383258632 + 20 +24166.954237432321 + 30 +0.0 + 11 +26769.848383258632 + 21 +24166.954237432321 + 31 +0.0 + 0 +LINE + 5 +210 + 8 +1 + 10 +26269.848383258639 + 20 +23517.210080071909 + 30 +0.0 + 11 +26269.848383258639 + 21 +23517.210080071909 + 31 +0.0 + 0 +LINE + 5 +211 + 8 +1 + 10 +26269.848383258632 + 20 +23517.210080071909 + 30 +0.0 + 11 +26769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +212 + 8 +1 + 10 +26269.848383258639 + 20 +22867.465922711512 + 30 +0.0 + 11 +26269.848383258639 + 21 +22867.465922711512 + 31 +0.0 + 0 +LINE + 5 +213 + 8 +1 + 10 +26269.848383258639 + 20 +22867.465922711512 + 30 +0.0 + 11 +26769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +214 + 8 +1 + 10 +30269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 11 +30269.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +215 + 8 +1 + 10 +30769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +30769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +TEXT + 5 +216 + 8 +1 + 10 +30269.848383258639 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 50 +270.0 + 41 +0.9000000000000005 + 7 +KANJI4 + 72 + 5 + 11 +30269.848383258639 + 21 +22867.459816112529 + 31 +0.0 + 0 +LINE + 5 +217 + 8 +1 + 10 +27769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +27769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +218 + 8 +1 + 10 +27269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +27269.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +219 + 8 +1 + 10 +27269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 50 +270.0 + 7 +KANJI4 + 11 +27769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +21A + 8 +1 + 10 +28263.50320559365 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 4 + 11 +28504.61995686268 + 21 +26116.190780579542 + 31 +0.0 + 0 +LINE + 5 +21B + 8 +1 + 10 +28769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +28769.848383258632 + 21 +23517.210080071931 + 31 +0.0 + 0 +LINE + 5 +21C + 8 +1 + 10 +28269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +28269.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +21D + 8 +1 + 10 +29269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +29269.848383258632 + 21 +22867.459816112529 + 31 +0.0 + 0 +LINE + 5 +21E + 8 +1 + 10 +29769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +29769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +21F + 8 +1 + 10 +29269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +29269.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +220 + 8 +1 + 10 +31769.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +31769.848383258621 + 21 +24816.698394792729 + 31 +0.0 + 0 +TEXT + 5 +221 + 8 +1 + 10 +31269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 50 +270.0 + 7 +KANJI4 + 0 +LINE + 5 +222 + 8 +1 + 10 +31269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +31269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +223 + 8 +1 + 10 +31269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +31769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +224 + 8 +1 + 10 +27269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +27769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +225 + 8 +1 + 10 +28269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +28769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +226 + 8 +1 + 10 +30269.848383258632 + 20 +28715.175552153141 + 30 +0.0 + 11 +30769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +227 + 8 +1 + 10 +29269.848383258621 + 20 +28715.175552153141 + 30 +0.0 + 11 +29769.848383258621 + 21 +28715.175552153141 + 31 +0.0 + 0 +LINE + 5 +228 + 8 +1 + 10 +31269.848383258621 + 20 +25466.442552153141 + 30 +0.0 + 11 +31769.848383258621 + 21 +25466.442552153141 + 31 +0.0 + 0 +LINE + 5 +229 + 8 +1 + 10 +31269.848383258621 + 20 +26116.18915215314 + 30 +0.0 + 11 +31769.848383258621 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +22A + 8 +1 + 10 +31269.848383258621 + 20 +26765.935752153138 + 30 +0.0 + 11 +31769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +22B + 8 +1 + 10 +31269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +31769.848383258621 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +22C + 8 +1 + 10 +31269.848383258621 + 20 +27415.682352153141 + 30 +0.0 + 11 +31769.848383258621 + 21 +27415.682352153141 + 31 +0.0 + 0 +LINE + 5 +22D + 8 +1 + 10 +31269.848383258621 + 20 +28065.428952153139 + 30 +0.0 + 11 +31769.848383258621 + 21 +28065.428952153139 + 31 +0.0 + 0 +LINE + 5 +22E + 8 +1 + 10 +27269.848383258621 + 20 +27415.682352153141 + 30 +0.0 + 11 +27769.848383258621 + 21 +27415.682352153141 + 31 +0.0 + 0 +LINE + 5 +22F + 8 +1 + 10 +27269.848383258621 + 20 +28065.428952153139 + 30 +0.0 + 11 +27769.848383258621 + 21 +28065.428952153139 + 31 +0.0 + 0 +LINE + 5 +230 + 8 +1 + 10 +27269.848383258621 + 20 +26765.935752153138 + 30 +0.0 + 11 +27769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +231 + 8 +1 + 10 +28269.848383258621 + 20 +27415.682352153141 + 30 +0.0 + 11 +28769.848383258621 + 21 +27415.682352153141 + 31 +0.0 + 0 +LINE + 5 +232 + 8 +1 + 10 +28269.848383258621 + 20 +28065.428952153139 + 30 +0.0 + 11 +28769.848383258621 + 21 +28065.428952153139 + 31 +0.0 + 0 +LINE + 5 +233 + 8 +1 + 10 +28269.848383258621 + 20 +26765.935752153138 + 30 +0.0 + 11 +28769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +234 + 8 +1 + 10 +27269.848383258621 + 20 +26116.18915215314 + 30 +0.0 + 11 +27769.848383258621 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +235 + 8 +1 + 10 +27269.848383258621 + 20 +25466.442552153141 + 30 +0.0 + 11 +27769.848383258621 + 21 +25466.442552153141 + 31 +0.0 + 0 +LINE + 5 +236 + 8 +1 + 10 +28269.848383258621 + 20 +26116.18915215314 + 30 +0.0 + 11 +28769.848383258621 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +237 + 8 +1 + 10 +28269.848383258621 + 20 +25466.442552153141 + 30 +0.0 + 11 +28769.848383258621 + 21 +25466.442552153141 + 31 +0.0 + 0 +LINE + 5 +238 + 8 +1 + 10 +29269.848383258621 + 20 +27415.682352153141 + 30 +0.0 + 11 +29769.848383258621 + 21 +27415.682352153141 + 31 +0.0 + 0 +LINE + 5 +239 + 8 +1 + 10 +29269.848383258621 + 20 +28065.428952153139 + 30 +0.0 + 11 +29769.848383258621 + 21 +28065.428952153139 + 31 +0.0 + 0 +LINE + 5 +23A + 8 +1 + 10 +29269.848383258621 + 20 +26765.935752153138 + 30 +0.0 + 11 +29769.848383258621 + 21 +26765.935752153138 + 31 +0.0 + 0 +LINE + 5 +23B + 8 +1 + 10 +29269.848383258621 + 20 +26116.18915215314 + 30 +0.0 + 11 +29769.848383258621 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +23C + 8 +1 + 10 +29269.848383258621 + 20 +25466.442552153141 + 30 +0.0 + 11 +29769.848383258621 + 21 +25466.442552153141 + 31 +0.0 + 0 +LINE + 5 +23D + 8 +1 + 10 +27269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +27769.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +23E + 8 +1 + 10 +27269.848383258621 + 20 +24816.698394792729 + 30 +0.0 + 11 +27769.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +23F + 8 +1 + 10 +27269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +27269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +240 + 8 +1 + 10 +27269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +27269.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +241 + 8 +1 + 10 +27269.848383258632 + 20 +23517.21008007192 + 30 +0.0 + 11 +27769.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +242 + 8 +1 + 10 +27269.848383258639 + 20 +23517.21008007192 + 30 +0.0 + 11 +27269.848383258639 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +243 + 8 +1 + 10 +28269.848383258621 + 20 +24816.698394792729 + 30 +0.0 + 11 +28769.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +244 + 8 +1 + 10 +28269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +28769.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +245 + 8 +1 + 10 +28269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +28269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +246 + 8 +1 + 10 +28269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +28269.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +247 + 8 +1 + 10 +28269.848383258632 + 20 +23517.21008007192 + 30 +0.0 + 11 +28769.848383258632 + 21 +23517.210080071931 + 31 +0.0 + 0 +LINE + 5 +248 + 8 +1 + 10 +28269.848383258639 + 20 +23517.21008007192 + 30 +0.0 + 11 +28269.848383258639 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +249 + 8 +1 + 10 +29269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +29769.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +24A + 8 +1 + 10 +29269.848383258621 + 20 +24816.698394792729 + 30 +0.0 + 11 +29769.848383258621 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +24B + 8 +1 + 10 +29269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +29269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +24C + 8 +1 + 10 +29269.848383258632 + 20 +24166.954237432328 + 30 +0.0 + 11 +29269.848383258632 + 21 +24166.954237432328 + 31 +0.0 + 0 +LINE + 5 +24D + 8 +1 + 10 +29269.848383258632 + 20 +23517.21008007192 + 30 +0.0 + 11 +29769.848383258632 + 21 +23517.210080071931 + 31 +0.0 + 0 +LINE + 5 +24E + 8 +1 + 10 +29269.848383258632 + 20 +23517.21008007192 + 30 +0.0 + 11 +29269.848383258632 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +24F + 8 +1 + 10 +31269.848383258632 + 20 +24816.698394792729 + 30 +0.0 + 11 +31269.848383258632 + 21 +24816.698394792729 + 31 +0.0 + 0 +LINE + 5 +250 + 8 +1 + 10 +30269.848383258632 + 20 +22867.465922711519 + 30 +0.0 + 11 +30769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +251 + 8 +1 + 10 +29269.848383258632 + 20 +22867.465922711519 + 30 +0.0 + 11 +29769.848383258632 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +252 + 8 +1 + 10 +29269.848383258639 + 20 +22867.465922711519 + 30 +0.0 + 11 +29269.848383258639 + 21 +22867.465922711519 + 31 +0.0 + 0 +LINE + 5 +253 + 8 +1 + 10 +30269.848383258639 + 20 +22867.465922711519 + 30 +0.0 + 11 +30269.848383258639 + 21 +22867.465922711519 + 31 +0.0 + 0 +DIMENSION + 5 +2AA + 8 +0 + 2 +*D2 + 10 +36093.929348936741 + 20 +24502.300187938301 + 30 +0.0 + 11 +34175.902204971368 + 21 +22884.793425970351 + 31 +0.0 + 70 + 0 + 13 +32841.982694166712 + 23 +20683.17903084397 + 33 +0.0 + 14 +36377.51660009945 + 24 +24218.712936776701 + 34 +0.0 + 50 +45.000000000111051 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +2B7 + 8 +0 + 2 +*D3 + 10 +33272.318231785503 + 20 +18992.19422490555 + 30 +0.0 + 11 +32892.248336899043 + 21 +19672.784501798342 + 31 +0.0 + 70 + 0 + 13 +32841.982694166712 + 23 +20683.17903084397 + 33 +0.0 + 14 +33902.642865946531 + 24 +19622.518859064141 + 34 +0.0 + 50 +134.9999999998889 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +2C4 + 8 +1 + 62 + 0 + 10 +33472.538295501778 + 20 +20318.356640421549 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI + 0 +DIMENSION + 5 +2C5 + 8 +0 + 2 +*D4 + 10 +39061.617553885691 + 20 +28864.207020387759 + 30 +0.0 + 11 +36561.617553885691 + 21 +29076.707020387759 + 31 +0.0 + 70 + 0 + 13 +34061.617553885691 + 23 +28463.154083678131 + 33 +0.0 + 14 +39061.617553885691 + 24 +28463.154083678131 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +POLYLINE + 5 +2C6 + 8 +1 + 62 + 0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +2117 + 8 +1 + 62 + 0 + 10 +34061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +VERTEX + 5 +2118 + 8 +1 + 62 + 0 + 10 +39061.617553885691 + 20 +28463.154083678131 + 30 +0.0 + 0 +VERTEX + 5 +2119 + 8 +1 + 62 + 0 + 10 +39061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +VERTEX + 5 +211A + 8 +1 + 62 + 0 + 10 +34061.617553885691 + 20 +26963.154083678131 + 30 +0.0 + 0 +SEQEND + 5 +211B + 8 +1 + 62 + 0 + 0 +DIMENSION + 5 +2C7 + 8 +0 + 2 +*D5 + 10 +33170.203907559007 + 20 +26963.154083678131 + 30 +0.0 + 11 +32957.703907559007 + 21 +27713.154083678139 + 31 +0.0 + 70 + 0 + 13 +34061.617553885691 + 23 +28463.154083678131 + 33 +0.0 + 14 +34061.617553885691 + 24 +26963.154083678131 + 34 +0.0 + 50 +90.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +328 + 8 +0 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 11 +37726.652160292258 + 21 +19622.518859064141 + 31 +0.0 + 0 +DIMENSION + 5 +329 + 8 +0 + 2 +*D6 + 10 +33902.642865946531 + 20 +19622.518859064141 + 30 +0.0 + 11 +37464.843762206277 + 21 +21098.03078219252 + 31 +0.0 + 70 + 2 + 13 +33902.642865946531 + 23 +19622.518859064141 + 33 +0.0 + 14 +37726.652160292258 + 24 +19622.518859064141 + 34 +0.0 + 15 +37438.176771879269 + 25 +23158.052764996879 + 35 +0.0 + 16 +37421.702354539237 + 26 +20565.44800714964 + 36 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 271 +1070 + 0 +1070 + 271 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 79 +1070 + 2 +1070 + 271 +1070 + 0 +1002 +} + 0 +CIRCLE + 5 +371 + 8 +0 + 10 +33971.719636084497 + 20 +15041.48750671567 + 30 +0.0 + 40 +1808.760328193126 + 0 +DIMENSION + 5 +373 + 8 +0 + 2 +*D7 + 10 +33971.719636084497 + 20 +13041.48750671567 + 30 +0.0 + 11 +33759.21963608449 + 21 +18228.987506715672 + 31 +0.0 + 70 + 3 + 15 +33971.719636084497 + 25 +17041.487506715672 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +DIMENSION + 5 +37C + 8 +0 + 2 +*D8 + 10 +33971.719636084512 + 20 +15041.48750671567 + 30 +0.0 + 11 +36541.494066613552 + 21 +16939.268283359561 + 31 +0.0 + 70 + 4 + 15 +35656.025611496458 + 25 +16119.964850562799 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +POLYLINE + 5 +3A0 + 8 +0 + 10 +35780.47996427762 + 20 +15041.487506715674 + 30 +0.0 + 66 + 1 + 70 + 8 + 0 +VERTEX + 8 +0 + 5 +217C + 10 +35780.5 + 20 +15041.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +217D + 10 +35778.3 + 20 +15090.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +217E + 10 +35771.8 + 20 +15139.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +217F + 10 +35760.9 + 20 +15188.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2180 + 10 +35745.7 + 20 +15236.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2181 + 10 +35726.3 + 20 +15284.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2182 + 10 +35702.6 + 20 +15331.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2183 + 10 +35674.7 + 20 +15378.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2184 + 10 +35642.8 + 20 +15424.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2185 + 10 +35606.8 + 20 +15469.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2186 + 10 +35566.9 + 20 +15512.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2187 + 10 +35523.1 + 20 +15555.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2188 + 10 +35475.6 + 20 +15597.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2189 + 10 +35424.5 + 20 +15637.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218A + 10 +35369.9 + 20 +15675.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218B + 10 +35311.9 + 20 +15713.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218C + 10 +35250.7 + 20 +15748.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218D + 10 +35186.4 + 20 +15782.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218E + 10 +35119.2 + 20 +15814.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +218F + 10 +35049.2 + 20 +15844.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2190 + 10 +34976.6 + 20 +15873.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2191 + 10 +34901.6 + 20 +15899.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2192 + 10 +34824.4 + 20 +15923.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2193 + 10 +34745.1 + 20 +15945.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2194 + 10 +34663.9 + 20 +15965.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2195 + 10 +34581.1 + 20 +15983.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2196 + 10 +34496.8 + 20 +15998.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2197 + 10 +34411.2 + 20 +16011.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2198 + 10 +34324.6 + 20 +16022.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2199 + 10 +34237.1 + 20 +16030.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219A + 10 +34149.0 + 20 +16036.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219B + 10 +34060.5 + 20 +16040.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219C + 10 +33971.7 + 20 +16041.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219D + 10 +33883.0 + 20 +16040.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219E + 10 +33794.4 + 20 +16036.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +219F + 10 +33706.3 + 20 +16030.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A0 + 10 +33618.8 + 20 +16022.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A1 + 10 +33532.2 + 20 +16011.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A2 + 10 +33446.7 + 20 +15998.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A3 + 10 +33362.4 + 20 +15983.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A4 + 10 +33279.5 + 20 +15965.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A5 + 10 +33198.4 + 20 +15945.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A6 + 10 +33119.1 + 20 +15923.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A7 + 10 +33041.8 + 20 +15899.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A8 + 10 +32966.8 + 20 +15873.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21A9 + 10 +32894.2 + 20 +15844.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AA + 10 +32824.3 + 20 +15814.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AB + 10 +32757.0 + 20 +15782.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AC + 10 +32692.7 + 20 +15748.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AD + 10 +32631.5 + 20 +15713.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AE + 10 +32573.5 + 20 +15675.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21AF + 10 +32518.9 + 20 +15637.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B0 + 10 +32467.8 + 20 +15597.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B1 + 10 +32420.3 + 20 +15555.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B2 + 10 +32376.5 + 20 +15512.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B3 + 10 +32336.6 + 20 +15469.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B4 + 10 +32300.6 + 20 +15424.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B5 + 10 +32268.7 + 20 +15378.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B6 + 10 +32240.8 + 20 +15331.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B7 + 10 +32217.2 + 20 +15284.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B8 + 10 +32197.7 + 20 +15236.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21B9 + 10 +32182.5 + 20 +15188.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BA + 10 +32171.7 + 20 +15139.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BB + 10 +32165.1 + 20 +15090.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BC + 10 +32163.0 + 20 +15041.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BD + 10 +32165.1 + 20 +14992.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BE + 10 +32171.7 + 20 +14943.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21BF + 10 +32182.5 + 20 +14894.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C0 + 10 +32197.7 + 20 +14846.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C1 + 10 +32217.2 + 20 +14798.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C2 + 10 +32240.8 + 20 +14751.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C3 + 10 +32268.7 + 20 +14704.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C4 + 10 +32300.6 + 20 +14658.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C5 + 10 +32336.6 + 20 +14613.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C6 + 10 +32376.5 + 20 +14570.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C7 + 10 +32420.3 + 20 +14527.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C8 + 10 +32467.8 + 20 +14485.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21C9 + 10 +32518.9 + 20 +14445.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CA + 10 +32573.5 + 20 +14407.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CB + 10 +32631.5 + 20 +14369.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CC + 10 +32692.7 + 20 +14334.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CD + 10 +32757.0 + 20 +14300.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CE + 10 +32824.3 + 20 +14268.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21CF + 10 +32894.2 + 20 +14238.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D0 + 10 +32966.8 + 20 +14210.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D1 + 10 +33041.8 + 20 +14183.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D2 + 10 +33119.1 + 20 +14159.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D3 + 10 +33198.4 + 20 +14137.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D4 + 10 +33279.5 + 20 +14117.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D5 + 10 +33362.4 + 20 +14099.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D6 + 10 +33446.7 + 20 +14084.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D7 + 10 +33532.2 + 20 +14071.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D8 + 10 +33618.8 + 20 +14060.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21D9 + 10 +33706.3 + 20 +14052.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DA + 10 +33794.4 + 20 +14046.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DB + 10 +33883.0 + 20 +14042.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DC + 10 +33971.7 + 20 +14041.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DD + 10 +34060.5 + 20 +14042.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DE + 10 +34149.0 + 20 +14046.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21DF + 10 +34237.1 + 20 +14052.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E0 + 10 +34324.6 + 20 +14060.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E1 + 10 +34411.2 + 20 +14071.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E2 + 10 +34496.8 + 20 +14084.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E3 + 10 +34581.1 + 20 +14099.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E4 + 10 +34663.9 + 20 +14117.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E5 + 10 +34745.1 + 20 +14137.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E6 + 10 +34824.4 + 20 +14159.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E7 + 10 +34901.6 + 20 +14183.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E8 + 10 +34976.6 + 20 +14210.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21E9 + 10 +35049.2 + 20 +14238.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21EA + 10 +35119.2 + 20 +14268.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21EB + 10 +35186.4 + 20 +14300.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21EC + 10 +35250.7 + 20 +14334.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21ED + 10 +35311.9 + 20 +14369.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21EE + 10 +35369.9 + 20 +14407.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21EF + 10 +35424.5 + 20 +14445.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F0 + 10 +35475.6 + 20 +14485.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F1 + 10 +35523.1 + 20 +14527.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F2 + 10 +35566.9 + 20 +14570.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F3 + 10 +35606.8 + 20 +14613.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F4 + 10 +35642.8 + 20 +14658.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F5 + 10 +35674.7 + 20 +14704.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F6 + 10 +35702.6 + 20 +14751.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F7 + 10 +35726.3 + 20 +14798.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F8 + 10 +35745.7 + 20 +14846.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21F9 + 10 +35760.9 + 20 +14894.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21FA + 10 +35771.8 + 20 +14943.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21FB + 10 +35778.3 + 20 +14992.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +21FC + 10 +35780.5 + 20 +15041.5 + 30 +0.000000 + 70 + 32 + 0 +SEQEND + 8 +0 + 5 +21FD + 0 +LINE + 5 +3EB + 8 +0 + 10 +32162.959307891371 + 20 +10886.19105157217 + 30 +0.0 + 11 +40162.959307891368 + 21 +10886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3EC + 8 +0 + 10 +32162.959307891371 + 20 +11886.19105157217 + 30 +0.0 + 11 +32162.959307891371 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3EE + 8 +0 + 10 +33162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +33162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3EF + 8 +0 + 10 +34162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +34162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F0 + 8 +0 + 10 +32162.959307891371 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.959307891368 + 21 +11886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3F1 + 8 +0 + 10 +32162.959307891371 + 20 +9886.1910515721756 + 30 +0.0 + 11 +40162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F2 + 8 +0 + 10 +35162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +35162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F3 + 8 +0 + 10 +36162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +36162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F4 + 8 +0 + 10 +37162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +37162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F5 + 8 +0 + 10 +38162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +38162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F7 + 8 +0 + 10 +40162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +LINE + 5 +3F8 + 8 +0 + 10 +39162.959307891368 + 20 +11886.19105157217 + 30 +0.0 + 11 +39162.959307891368 + 21 +9886.1910515721756 + 31 +0.0 + 0 +POLYLINE + 8 +0 + 5 +21FE + 66 + 1 + 10 +0.000000 + 20 +0.000000 + 30 +0.000000 + 70 + 8 + 0 +VERTEX + 8 +0 + 5 +21FF + 10 +32163.0 + 20 +10886.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2200 + 10 +32185.7 + 20 +10920.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2201 + 10 +32208.4 + 20 +10954.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2202 + 10 +32231.1 + 20 +10988.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2203 + 10 +32253.9 + 20 +11022.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2204 + 10 +32276.6 + 20 +11055.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2205 + 10 +32299.3 + 20 +11089.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2206 + 10 +32322.0 + 20 +11122.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2207 + 10 +32344.7 + 20 +11155.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2208 + 10 +32367.5 + 20 +11188.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2209 + 10 +32390.2 + 20 +11221.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220A + 10 +32412.9 + 20 +11253.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220B + 10 +32435.6 + 20 +11285.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220C + 10 +32458.4 + 20 +11316.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220D + 10 +32481.1 + 20 +11347.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220E + 10 +32503.8 + 20 +11377.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +220F + 10 +32526.5 + 20 +11407.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2210 + 10 +32549.2 + 20 +11436.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2211 + 10 +32572.0 + 20 +11465.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2212 + 10 +32594.7 + 20 +11493.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2213 + 10 +32617.4 + 20 +11520.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2214 + 10 +32640.1 + 20 +11547.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2215 + 10 +32662.9 + 20 +11573.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2216 + 10 +32685.6 + 20 +11598.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2217 + 10 +32708.3 + 20 +11623.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2218 + 10 +32731.0 + 20 +11646.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2219 + 10 +32753.8 + 20 +11669.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221A + 10 +32776.5 + 20 +11691.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221B + 10 +32799.2 + 20 +11711.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221C + 10 +32821.9 + 20 +11731.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221D + 10 +32844.6 + 20 +11750.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221E + 10 +32867.4 + 20 +11768.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +221F + 10 +32890.1 + 20 +11784.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2220 + 10 +32912.8 + 20 +11800.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2221 + 10 +32935.5 + 20 +11814.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2222 + 10 +32958.3 + 20 +11827.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2223 + 10 +32981.0 + 20 +11839.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2224 + 10 +33003.7 + 20 +11850.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2225 + 10 +33026.4 + 20 +11859.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2226 + 10 +33049.2 + 20 +11867.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2227 + 10 +33071.9 + 20 +11874.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2228 + 10 +33094.6 + 20 +11879.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2229 + 10 +33117.3 + 20 +11883.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222A + 10 +33140.0 + 20 +11885.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222B + 10 +33162.8 + 20 +11886.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222C + 10 +33185.5 + 20 +11885.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222D + 10 +33208.2 + 20 +11883.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222E + 10 +33230.9 + 20 +11879.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +222F + 10 +33253.7 + 20 +11874.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2230 + 10 +33276.4 + 20 +11867.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2231 + 10 +33299.1 + 20 +11859.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2232 + 10 +33321.8 + 20 +11850.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2233 + 10 +33344.5 + 20 +11839.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2234 + 10 +33367.3 + 20 +11827.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2235 + 10 +33390.0 + 20 +11814.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2236 + 10 +33412.7 + 20 +11800.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2237 + 10 +33435.4 + 20 +11784.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2238 + 10 +33458.2 + 20 +11768.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2239 + 10 +33480.9 + 20 +11750.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223A + 10 +33503.6 + 20 +11731.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223B + 10 +33526.3 + 20 +11712.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223C + 10 +33549.1 + 20 +11691.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223D + 10 +33571.8 + 20 +11669.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223E + 10 +33594.5 + 20 +11647.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +223F + 10 +33617.2 + 20 +11623.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2240 + 10 +33639.9 + 20 +11599.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2241 + 10 +33662.7 + 20 +11574.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2242 + 10 +33685.4 + 20 +11548.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2243 + 10 +33708.1 + 20 +11521.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2244 + 10 +33730.8 + 20 +11494.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2245 + 10 +33753.6 + 20 +11466.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2246 + 10 +33776.3 + 20 +11437.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2247 + 10 +33799.0 + 20 +11408.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2248 + 10 +33821.7 + 20 +11378.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2249 + 10 +33844.5 + 20 +11347.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224A + 10 +33867.2 + 20 +11316.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224B + 10 +33889.9 + 20 +11285.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224C + 10 +33912.6 + 20 +11253.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224D + 10 +33935.3 + 20 +11221.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224E + 10 +33958.1 + 20 +11189.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +224F + 10 +33980.8 + 20 +11156.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2250 + 10 +34003.5 + 20 +11123.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2251 + 10 +34026.2 + 20 +11090.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2252 + 10 +34049.0 + 20 +11056.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2253 + 10 +34071.7 + 20 +11022.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2254 + 10 +34094.4 + 20 +10988.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2255 + 10 +34117.1 + 20 +10954.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2256 + 10 +34139.8 + 20 +10920.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2257 + 10 +34162.6 + 20 +10886.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2258 + 10 +34185.3 + 20 +10852.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2259 + 10 +34208.0 + 20 +10818.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225A + 10 +34230.7 + 20 +10784.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225B + 10 +34253.5 + 20 +10750.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225C + 10 +34276.2 + 20 +10717.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225D + 10 +34298.9 + 20 +10683.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225E + 10 +34321.6 + 20 +10650.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +225F + 10 +34344.4 + 20 +10617.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2260 + 10 +34367.1 + 20 +10584.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2261 + 10 +34389.8 + 20 +10551.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2262 + 10 +34412.5 + 20 +10519.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2263 + 10 +34435.2 + 20 +10487.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2264 + 10 +34458.0 + 20 +10456.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2265 + 10 +34480.7 + 20 +10425.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2266 + 10 +34503.4 + 20 +10395.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2267 + 10 +34526.1 + 20 +10365.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2268 + 10 +34548.9 + 20 +10336.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2269 + 10 +34571.6 + 20 +10307.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226A + 10 +34594.3 + 20 +10279.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226B + 10 +34617.0 + 20 +10251.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226C + 10 +34639.7 + 20 +10225.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226D + 10 +34662.5 + 20 +10199.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226E + 10 +34685.2 + 20 +10174.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +226F + 10 +34707.9 + 20 +10149.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2270 + 10 +34730.6 + 20 +10126.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2271 + 10 +34753.4 + 20 +10103.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2272 + 10 +34776.1 + 20 +10081.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2273 + 10 +34798.8 + 20 +10061.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2274 + 10 +34821.5 + 20 +10041.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2275 + 10 +34844.2 + 20 +10022.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2276 + 10 +34867.0 + 20 +10004.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2277 + 10 +34889.7 + 20 +9987.99 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2278 + 10 +34912.4 + 20 +9972.48 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2279 + 10 +34935.1 + 20 +9958.13 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227A + 10 +34957.9 + 20 +9944.97 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227B + 10 +34980.6 + 20 +9933.04 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227C + 10 +35003.3 + 20 +9922.39 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227D + 10 +35026.0 + 20 +9913.03 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227E + 10 +35048.8 + 20 +9905.01 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +227F + 10 +35071.5 + 20 +9898.36 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2280 + 10 +35094.2 + 20 +9893.12 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2281 + 10 +35116.9 + 20 +9889.32 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2282 + 10 +35139.7 + 20 +9887.00 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2283 + 10 +35162.4 + 20 +9886.19 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2284 + 10 +35185.1 + 20 +9886.92 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2285 + 10 +35207.8 + 20 +9889.17 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2286 + 10 +35230.6 + 20 +9892.89 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2287 + 10 +35253.3 + 20 +9898.06 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2288 + 10 +35276.0 + 20 +9904.63 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2289 + 10 +35298.7 + 20 +9912.58 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228A + 10 +35321.4 + 20 +9921.87 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228B + 10 +35344.2 + 20 +9932.47 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228C + 10 +35366.9 + 20 +9944.33 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228D + 10 +35389.6 + 20 +9957.42 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228E + 10 +35412.3 + 20 +9971.71 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +228F + 10 +35435.1 + 20 +9987.17 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2290 + 10 +35457.8 + 20 +10003.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2291 + 10 +35480.5 + 20 +10021.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2292 + 10 +35503.2 + 20 +10040.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2293 + 10 +35526.0 + 20 +10059.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2294 + 10 +35548.7 + 20 +10080.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2295 + 10 +35571.4 + 20 +10102.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2296 + 10 +35594.1 + 20 +10125.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2297 + 10 +35616.9 + 20 +10148.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2298 + 10 +35639.6 + 20 +10172.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2299 + 10 +35662.3 + 20 +10197.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229A + 10 +35685.0 + 20 +10223.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229B + 10 +35707.8 + 20 +10250.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229C + 10 +35730.5 + 20 +10277.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229D + 10 +35753.2 + 20 +10305.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229E + 10 +35775.9 + 20 +10334.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +229F + 10 +35798.7 + 20 +10363.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A0 + 10 +35821.4 + 20 +10393.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A1 + 10 +35844.1 + 20 +10424.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A2 + 10 +35866.8 + 20 +10454.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A3 + 10 +35889.5 + 20 +10486.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A4 + 10 +35912.3 + 20 +10518.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A5 + 10 +35935.0 + 20 +10550.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A6 + 10 +35957.7 + 20 +10582.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A7 + 10 +35980.4 + 20 +10615.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A8 + 10 +36003.2 + 20 +10648.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22A9 + 10 +36025.9 + 20 +10681.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AA + 10 +36048.6 + 20 +10715.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AB + 10 +36071.3 + 20 +10749.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AC + 10 +36094.0 + 20 +10782.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AD + 10 +36116.7 + 20 +10816.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AE + 10 +36139.5 + 20 +10851.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22AF + 10 +36162.2 + 20 +10885.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B0 + 10 +36184.9 + 20 +10919.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B1 + 10 +36207.6 + 20 +10953.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B2 + 10 +36230.3 + 20 +10987.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B3 + 10 +36253.1 + 20 +11021.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B4 + 10 +36275.8 + 20 +11054.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B5 + 10 +36298.5 + 20 +11088.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B6 + 10 +36321.2 + 20 +11121.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B7 + 10 +36343.9 + 20 +11154.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B8 + 10 +36366.6 + 20 +11187.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22B9 + 10 +36389.3 + 20 +11220.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BA + 10 +36412.1 + 20 +11252.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BB + 10 +36434.8 + 20 +11284.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BC + 10 +36457.5 + 20 +11315.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BD + 10 +36480.2 + 20 +11346.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BE + 10 +36502.9 + 20 +11376.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22BF + 10 +36525.6 + 20 +11406.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C0 + 10 +36548.4 + 20 +11435.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C1 + 10 +36571.1 + 20 +11464.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C2 + 10 +36593.8 + 20 +11492.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C3 + 10 +36616.5 + 20 +11520.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C4 + 10 +36639.2 + 20 +11546.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C5 + 10 +36662.0 + 20 +11572.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C6 + 10 +36684.7 + 20 +11597.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C7 + 10 +36707.4 + 20 +11622.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C8 + 10 +36730.1 + 20 +11645.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22C9 + 10 +36752.8 + 20 +11668.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CA + 10 +36775.6 + 20 +11690.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CB + 10 +36798.3 + 20 +11711.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CC + 10 +36821.0 + 20 +11730.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CD + 10 +36843.7 + 20 +11749.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CE + 10 +36866.5 + 20 +11767.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22CF + 10 +36889.2 + 20 +11784.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D0 + 10 +36911.9 + 20 +11799.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D1 + 10 +36934.6 + 20 +11814.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D2 + 10 +36957.4 + 20 +11827.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D3 + 10 +36980.1 + 20 +11839.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D4 + 10 +37002.8 + 20 +11849.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D5 + 10 +37025.6 + 20 +11859.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D6 + 10 +37048.3 + 20 +11867.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D7 + 10 +37071.0 + 20 +11873.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D8 + 10 +37093.8 + 20 +11879.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22D9 + 10 +37116.5 + 20 +11883.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DA + 10 +37139.2 + 20 +11885.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DB + 10 +37162.0 + 20 +11886.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DC + 10 +37184.7 + 20 +11885.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DD + 10 +37207.5 + 20 +11883.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DE + 10 +37230.2 + 20 +11879.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22DF + 10 +37253.0 + 20 +11874.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E0 + 10 +37275.7 + 20 +11867.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E1 + 10 +37298.5 + 20 +11859.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E2 + 10 +37321.2 + 20 +11850.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E3 + 10 +37344.0 + 20 +11840.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E4 + 10 +37366.7 + 20 +11828.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E5 + 10 +37389.5 + 20 +11815.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E6 + 10 +37412.2 + 20 +11800.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E7 + 10 +37435.0 + 20 +11785.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E8 + 10 +37457.7 + 20 +11768.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22E9 + 10 +37480.5 + 20 +11751.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22EA + 10 +37503.2 + 20 +11732.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22EB + 10 +37525.9 + 20 +11712.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22EC + 10 +37548.7 + 20 +11692.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22ED + 10 +37571.4 + 20 +11670.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22EE + 10 +37594.2 + 20 +11647.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22EF + 10 +37616.9 + 20 +11624.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F0 + 10 +37639.7 + 20 +11600.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F1 + 10 +37662.4 + 20 +11574.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F2 + 10 +37685.1 + 20 +11549.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F3 + 10 +37707.9 + 20 +11522.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F4 + 10 +37730.6 + 20 +11494.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F5 + 10 +37753.3 + 20 +11466.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F6 + 10 +37776.0 + 20 +11438.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F7 + 10 +37798.8 + 20 +11409.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F8 + 10 +37821.5 + 20 +11379.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22F9 + 10 +37844.2 + 20 +11348.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FA + 10 +37866.9 + 20 +11318.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FB + 10 +37889.6 + 20 +11286.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FC + 10 +37912.3 + 20 +11254.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FD + 10 +37935.0 + 20 +11222.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FE + 10 +37957.7 + 20 +11190.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +22FF + 10 +37980.4 + 20 +11157.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2300 + 10 +38003.1 + 20 +11124.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2301 + 10 +38025.8 + 20 +11091.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2302 + 10 +38048.5 + 20 +11057.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2303 + 10 +38071.2 + 20 +11023.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2304 + 10 +38093.8 + 20 +10990.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2305 + 10 +38116.5 + 20 +10956.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2306 + 10 +38139.1 + 20 +10922.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2307 + 10 +38161.8 + 20 +10887.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2308 + 10 +38184.5 + 20 +10853.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2309 + 10 +38207.1 + 20 +10819.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230A + 10 +38229.7 + 20 +10785.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230B + 10 +38252.4 + 20 +10752.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230C + 10 +38275.0 + 20 +10718.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230D + 10 +38297.6 + 20 +10684.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230E + 10 +38320.3 + 20 +10651.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +230F + 10 +38342.9 + 20 +10618.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2310 + 10 +38365.5 + 20 +10585.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2311 + 10 +38388.1 + 20 +10552.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2312 + 10 +38410.8 + 20 +10520.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2313 + 10 +38433.4 + 20 +10489.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2314 + 10 +38456.0 + 20 +10457.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2315 + 10 +38478.7 + 20 +10426.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2316 + 10 +38501.3 + 20 +10396.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2317 + 10 +38523.9 + 20 +10366.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2318 + 10 +38546.6 + 20 +10337.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2319 + 10 +38569.2 + 20 +10308.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231A + 10 +38591.9 + 20 +10280.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231B + 10 +38614.5 + 20 +10252.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231C + 10 +38637.2 + 20 +10226.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231D + 10 +38659.8 + 20 +10200.2 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231E + 10 +38682.5 + 20 +10175.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +231F + 10 +38705.2 + 20 +10150.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2320 + 10 +38727.9 + 20 +10127.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2321 + 10 +38750.6 + 20 +10104.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2322 + 10 +38773.3 + 20 +10082.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2323 + 10 +38796.1 + 20 +10061.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2324 + 10 +38818.8 + 20 +10041.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2325 + 10 +38841.5 + 20 +10023.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2326 + 10 +38864.3 + 20 +10005.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2327 + 10 +38887.1 + 20 +9988.63 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2328 + 10 +38909.9 + 20 +9973.08 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2329 + 10 +38932.7 + 20 +9958.68 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232A + 10 +38955.5 + 20 +9945.48 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232B + 10 +38978.3 + 20 +9933.50 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232C + 10 +39001.2 + 20 +9922.80 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232D + 10 +39024.0 + 20 +9913.39 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232E + 10 +39046.9 + 20 +9905.31 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +232F + 10 +39069.8 + 20 +9898.61 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2330 + 10 +39092.7 + 20 +9893.31 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2331 + 10 +39115.7 + 20 +9889.45 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2332 + 10 +39138.6 + 20 +9887.07 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2333 + 10 +39161.6 + 20 +9886.19 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2334 + 10 +39184.6 + 20 +9886.86 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2335 + 10 +39207.6 + 20 +9889.04 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2336 + 10 +39230.6 + 20 +9892.69 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2337 + 10 +39253.7 + 20 +9897.79 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2338 + 10 +39276.8 + 20 +9904.29 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2339 + 10 +39299.9 + 20 +9912.16 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233A + 10 +39323.0 + 20 +9921.37 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233B + 10 +39346.1 + 20 +9931.88 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233C + 10 +39369.3 + 20 +9943.64 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233D + 10 +39392.4 + 20 +9956.63 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233E + 10 +39415.6 + 20 +9970.82 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +233F + 10 +39438.8 + 20 +9986.15 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2340 + 10 +39462.0 + 20 +10002.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2341 + 10 +39485.2 + 20 +10020.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2342 + 10 +39508.5 + 20 +10038.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2343 + 10 +39531.7 + 20 +10058.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2344 + 10 +39555.0 + 20 +10078.9 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2345 + 10 +39578.3 + 20 +10100.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2346 + 10 +39601.6 + 20 +10122.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2347 + 10 +39624.9 + 20 +10146.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2348 + 10 +39648.2 + 20 +10170.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2349 + 10 +39671.5 + 20 +10195.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234A + 10 +39694.9 + 20 +10220.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234B + 10 +39718.2 + 20 +10247.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234C + 10 +39741.6 + 20 +10274.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234D + 10 +39764.9 + 20 +10301.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234E + 10 +39788.3 + 20 +10330.1 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +234F + 10 +39811.7 + 20 +10359.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2350 + 10 +39835.1 + 20 +10388.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2351 + 10 +39858.4 + 20 +10418.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2352 + 10 +39881.8 + 20 +10448.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2353 + 10 +39905.3 + 20 +10479.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2354 + 10 +39928.7 + 20 +10510.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2355 + 10 +39952.1 + 20 +10542.4 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2356 + 10 +39975.5 + 20 +10574.3 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2357 + 10 +39998.9 + 20 +10606.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2358 + 10 +40022.3 + 20 +10639.0 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +2359 + 10 +40045.8 + 20 +10671.7 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +235A + 10 +40069.2 + 20 +10704.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +235B + 10 +40092.6 + 20 +10737.5 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +235C + 10 +40116.1 + 20 +10770.6 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +235D + 10 +40139.5 + 20 +10803.8 + 30 +0.000000 + 70 + 32 + 0 +VERTEX + 8 +0 + 5 +235E + 10 +40163.0 + 20 +10837.0 + 30 +0.000000 + 70 + 32 + 0 +SEQEND + 8 +0 + 5 +235F + 0 +TEXT + 5 +3FC + 8 +0 + 10 +32162.959307891371 + 20 +11886.19105157217 + 30 +0.0 + 40 +500.0 + 1 +ƒXƒvƒ‰ƒCƒ“‹Èü + 7 +KANJI + 0 +LINE + 5 +40C + 8 +0 + 10 +32162.959307891371 + 20 +8789.5158270274333 + 30 +0.0 + 11 +40162.959307891368 + 21 +8789.5158270274333 + 31 +0.0 + 0 +LINE + 5 +40D + 8 +0 + 10 +32162.959307891371 + 20 +6789.5158270274333 + 30 +0.0 + 11 +40118.791045835002 + 21 +6789.515827027426 + 31 +0.0 + 0 +POLYLINE + 5 +40E + 8 +0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +VERTEX + 5 +2125 + 8 +0 + 10 +32162.959307891371 + 20 +6789.5158270274351 + 30 +0.0 + 0 +VERTEX + 5 +2126 + 8 +0 + 10 +34144.217405715019 + 20 +8789.5158270274333 + 30 +0.0 + 0 +VERTEX + 5 +2127 + 8 +0 + 10 +36162.959307891368 + 20 +6789.5158270274351 + 30 +0.0 + 0 +VERTEX + 5 +2128 + 8 +0 + 10 +38110.783546968618 + 20 +8789.5158270274333 + 30 +0.0 + 0 +VERTEX + 5 +2129 + 8 +0 + 10 +40118.791045835009 + 20 +6789.5158270274324 + 30 +0.0 + 0 +SEQEND + 5 +212A + 8 +0 + 0 +TEXT + 5 +40F + 8 +0 + 10 +32162.959307891371 + 20 +8789.5158270274333 + 30 +0.0 + 40 +500.0 + 1 +ƒ|ƒŠƒ‰ƒCƒ“ + 7 +KANJI + 0 +POLYLINE + 5 +411 + 8 +0 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 +1001 +ACAD +1000 +ASC_BOUNDS +1002 +{ +1070 + 19 +1005 +434 +1002 +} + 0 +VERTEX + 5 +212B + 8 +0 + 10 +37649.984925865952 + 20 +15879.054869113421 + 30 +0.0 + 0 +VERTEX + 5 +212C + 8 +0 + 10 +40498.45357200499 + 20 +15879.054869113421 + 30 +0.0 + 0 +VERTEX + 5 +212D + 8 +0 + 10 +40498.45357200499 + 20 +13879.054869113421 + 30 +0.0 + 0 +VERTEX + 5 +212E + 8 +0 + 10 +37649.984925865952 + 20 +13879.054869113421 + 30 +0.0 + 0 +SEQEND + 5 +212F + 8 +0 + 0 +INSERT + 5 +434 + 8 +0 + 6 +CONTINUOUS + 2 +*X61 + 10 +0.0 + 20 +0.0 + 30 +0.0 +1001 +ACAD +1000 +HATCH +1002 +{ +1070 + 19 +1000 +ANSI31 +1040 +100.0 +1040 +0.0 +1000 +ASC_BOUNDS +1070 + 1 +1070 + 1 +1070 + 1 +1005 +411 +1000 +ASC_SEEDPOINT +1011 +39291.359956737419 +1021 +0.0 +1031 +0.0 +1021 +15049.923234904731 +1031 +0.0 +1000 +R14_HATCH_DATA +1000 +434 +1011 +1.0 +1021 +0.0 +1031 +0.0 +1021 +0.0 +1031 +0.0 +1011 +0.0 +1021 +0.0 +1031 +0.0 +1021 +1.0 +1031 +0.0 +1011 +0.0 +1021 +0.0 +1031 +0.0 +1021 +0.0 +1031 +1.0 +1040 +0.0 +1010 +0.0 +1020 +0.0 +1030 +1.0 +1000 +ANSI31 +1070 + 0 +1070 + 1 +1071 + 1 +1071 + 7 +1070 + 0 +1070 + 1 +1071 + 4 +1040 +37649.984925865952 +1040 +15879.054869113421 +1040 +37649.984925865952 +1040 +13879.054869113421 +1040 +40498.45357200499 +1040 +13879.054869113421 +1040 +40498.453572004983 +1040 +15879.054869113421 +1071 + 1 +1005 +411 +1070 + 0 +1070 + 1 +1040 +0.0 +1040 +100.0 +1070 + 0 +1070 + 1 +1040 +0.7853981633974483 +1040 +21081.924720094939 +1040 +7900.6336176619898 +1040 +-224.50640302672869 +1040 +224.5064030267288 +1070 + 0 +1040 +12.72318334023255 +1071 + 1 +1040 +39291.359956737419 +1040 +15049.923234904731 +1040 +0.0 +1002 +} + 0 +TEXT + 5 +435 + 8 +0 + 10 +37649.984925865952 + 20 +16479.054869113421 + 30 +0.0 + 40 +500.0 + 1 +ƒnƒbƒ`ƒ“ƒO + 7 +KANJI + 0 +TEXT + 5 +436 + 8 +0 + 10 +37649.984925865952 + 20 +15879.054869113421 + 30 +0.0 + 40 +500.0 + 1 +ANSI31 + 7 +KANJI + 0 +POINT + 5 +43E + 8 +0 + 10 +36750.93264721553 + 20 +18178.721898943571 + 30 +0.0 + 0 +POINT + 5 +43F + 8 +0 + 10 +37495.843494396839 + 20 +18178.721898943571 + 30 +0.0 + 0 +POINT + 5 +440 + 8 +0 + 10 +38240.754341578147 + 20 +18178.721898943571 + 30 +0.0 + 0 +POINT + 5 +441 + 8 +0 + 10 +38985.665188759449 + 20 +18178.721898943571 + 30 +0.0 + 0 +POINT + 5 +442 + 8 +0 + 10 +39730.57603594075 + 20 +18178.721898943571 + 30 +0.0 + 0 +TEXT + 5 +443 + 8 +0 + 10 +36750.93264721553 + 20 +18486.489105717661 + 30 +0.0 + 40 +500.0 + 1 +“_(â‘Î’PˆÊ300) + 7 +KANJI + 0 +POINT + 5 +444 + 8 +0 + 10 +40475.486883122067 + 20 +18178.721898943571 + 30 +0.0 + 0 +POINT + 5 +445 + 8 +0 + 10 +41220.397730303368 + 20 +18178.721898943571 + 30 +0.0 + 0 +TEXT + 5 +564 + 8 +1 + 10 +834.83167002763105 + 20 +22670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 7 +KANJI2 + 72 + 2 + 11 +6032.8012131748383 + 21 +23170.88067496867 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +565 + 8 +1 + 10 +834.83167002763355 + 20 +21670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 7 +KANJI2 + 11 +834.83167002763355 + 21 +21920.880674968659 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +566 + 8 +1 + 10 +834.83167002763355 + 20 +21670.880674968659 + 30 +0.0 + 11 +6682.5412994692533 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +567 + 8 +1 + 10 +834.83167002763184 + 20 +22170.880674968659 + 30 +0.0 + 11 +6682.5412994692506 + 21 +22170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +568 + 8 +1 + 10 +834.83167002763514 + 20 +20670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 1 + 11 +3433.8164416012391 + 21 +20920.880674968659 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +569 + 8 +1 + 10 +834.83167002763537 + 20 +20670.880674968659 + 30 +0.0 + 11 +6032.7971421088514 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56A + 8 +1 + 10 +834.83167002763537 + 20 +21170.880674968659 + 30 +0.0 + 11 +6032.7971421088469 + 21 +21170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56B + 8 +1 + 10 +834.83167002763719 + 20 +19670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 7 +KANJI2 + 72 + 2 + 11 +6682.5474060682473 + 21 +19920.88067496867 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +56C + 8 +1 + 10 +834.83167002763719 + 20 +19670.880674968659 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56D + 8 +1 + 10 +834.83167002763719 + 20 +20170.880674968659 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56E + 8 +1 + 10 +834.83167002763923 + 20 +18670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 7 +KANJI2 + 11 +834.83167002763923 + 21 +18579.510116593028 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +56F + 8 +1 + 10 +834.83167002763923 + 20 +19170.880674968659 + 30 +0.0 + 11 +6032.7971421088514 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +570 + 8 +1 + 10 +834.83167002763923 + 20 +18670.880674968659 + 30 +0.0 + 11 +6032.7971421088541 + 21 +18670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +571 + 8 +1 + 10 +834.83167002764264 + 20 +17670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.6895380479468 + 21 +17579.510116593028 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +572 + 8 +1 + 10 +834.83167002764094 + 20 +18170.880674968659 + 30 +0.0 + 11 +6682.5412994692597 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +573 + 8 +1 + 10 +834.83167002764264 + 20 +17670.880674968659 + 30 +0.0 + 11 +6682.5412994692597 + 21 +17670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +574 + 8 +1 + 10 +834.83167002764355 + 20 +16670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 7 +KANJI2 + 72 + 2 + 11 +6032.801213174851 + 21 +16579.510116593028 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +575 + 8 +1 + 10 +834.83167002764446 + 20 +16670.880674968659 + 30 +0.0 + 11 +6032.7971421088587 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +576 + 8 +1 + 10 +834.83167002764446 + 20 +17170.880674968659 + 30 +0.0 + 11 +6032.7971421088541 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +577 + 8 +1 + 10 +834.83167002764822 + 20 +15140.89629083311 + 30 +0.0 + 11 +7332.2935989616581 + 21 +15140.89629083312 + 31 +0.0 + 0 +TEXT + 5 +578 + 8 +1 + 10 +834.83167002764822 + 20 +15140.89629083311 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI2 + 72 + 2 + 11 +7332.2935989616581 + 21 +15140.89629083311 + 31 +0.0 + 0 +LINE + 5 +579 + 8 +1 + 10 +7332.2935989616581 + 20 +16140.89629083311 + 30 +0.0 + 11 +834.83167002764822 + 21 +16140.89629083311 + 31 +0.0 + 0 +INSERT + 5 +57A + 8 +1 + 2 +*U62 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +LINE + 5 +57B + 8 +1 + 10 +834.83167002764822 + 20 +14517.44463265923 + 30 +0.0 + 11 +5367.7372542063003 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +57C + 8 +1 + 10 +834.83167002764822 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.7372542062976 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57D + 8 +1 + 10 +834.83167002764446 + 20 +16670.880674968659 + 30 +0.0 + 11 +834.83167002764446 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +57E + 8 +1 + 10 +834.83167002764822 + 20 +14517.44463265923 + 30 +0.0 + 11 +834.83167002764822 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57F + 8 +1 + 10 +834.83167002764822 + 20 +15140.89629083311 + 30 +0.0 + 11 +834.83167002764822 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +580 + 8 +1 + 10 +834.83167002763719 + 20 +19670.880674968659 + 30 +0.0 + 11 +834.83167002763719 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +581 + 8 +1 + 10 +834.83167002764264 + 20 +17670.880674968659 + 30 +0.0 + 11 +834.83167002764094 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +582 + 8 +1 + 10 +834.83167002763923 + 20 +18670.880674968659 + 30 +0.0 + 11 +834.83167002763923 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +583 + 8 +1 + 10 +834.83167002763537 + 20 +20670.880674968659 + 30 +0.0 + 11 +834.83167002763537 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +584 + 8 +1 + 10 +834.83167002763355 + 20 +21670.880674968659 + 30 +0.0 + 11 +834.83167002763184 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +585 + 8 +1 + 10 +6032.7971421088587 + 20 +16670.88067496867 + 30 +0.0 + 11 +6032.7971421088541 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +586 + 8 +1 + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.0529847484522 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +587 + 8 +1 + 10 +4733.3088273880512 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.3088273880494 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +588 + 8 +1 + 10 +4083.5646700276438 + 20 +16670.880674968659 + 30 +0.0 + 11 +4083.5646700276438 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +589 + 8 +1 + 10 +3433.8180700276439 + 20 +16670.880674968659 + 30 +0.0 + 11 +3433.8180700276439 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +58A + 8 +1 + 10 +2784.071470027644 + 20 +16670.880674968659 + 30 +0.0 + 11 +2784.071470027644 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +58B + 8 +1 + 10 +2134.3248700276449 + 20 +16670.880674968659 + 30 +0.0 + 11 +2134.3248700276431 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +58C + 8 +1 + 10 +1484.578270027645 + 20 +16670.880674968659 + 30 +0.0 + 11 +1484.5782700276429 + 21 +17170.880674968659 + 31 +0.0 + 0 +LINE + 5 +58D + 8 +1 + 10 +5367.7372542062976 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.7372542063003 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +58E + 8 +1 + 10 +4733.3088273880512 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.3088273880512 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +58F + 8 +1 + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.052984748454 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +590 + 8 +1 + 10 +6032.7971421088587 + 20 +16670.880674968681 + 30 +0.0 + 11 +6032.7971421088587 + 21 +16670.880674968681 + 31 +0.0 + 0 +LINE + 5 +591 + 8 +1 + 10 +7332.2935989616581 + 20 +15140.89629083312 + 30 +0.0 + 11 +7332.2935989616581 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +592 + 8 +1 + 10 +4083.564670027637 + 20 +19670.880674968659 + 30 +0.0 + 11 +4083.564670027637 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +593 + 8 +1 + 10 +3433.8180700276371 + 20 +19670.880674968659 + 30 +0.0 + 11 +3433.8180700276371 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +594 + 8 +1 + 10 +2784.0714700276371 + 20 +19670.880674968659 + 30 +0.0 + 11 +2784.0714700276371 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +595 + 8 +1 + 10 +1484.578270027637 + 20 +19670.880674968659 + 30 +0.0 + 11 +1484.578270027637 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +596 + 8 +1 + 10 +2134.3248700276381 + 20 +19670.880674968659 + 30 +0.0 + 11 +2134.3248700276358 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +597 + 8 +1 + 10 +1484.5782700276411 + 20 +17670.880674968659 + 30 +0.0 + 11 +1484.5782700276411 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +598 + 8 +1 + 10 +2134.3248700276408 + 20 +17670.880674968659 + 30 +0.0 + 11 +2134.3248700276399 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +599 + 8 +1 + 10 +2784.0714700276399 + 20 +17670.880674968659 + 30 +0.0 + 11 +2784.0714700276399 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59A + 8 +1 + 10 +1484.5782700276391 + 20 +18670.880674968659 + 30 +0.0 + 11 +1484.5782700276391 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59B + 8 +1 + 10 +2134.3248700276399 + 20 +18670.880674968659 + 30 +0.0 + 11 +2134.3248700276381 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59C + 8 +1 + 10 +2784.071470027638 + 20 +18670.880674968659 + 30 +0.0 + 11 +2784.071470027638 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59D + 8 +1 + 10 +3433.8180700276412 + 20 +17670.880674968659 + 30 +0.0 + 11 +3433.8180700276412 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59E + 8 +1 + 10 +4083.5646700276411 + 20 +17670.880674968659 + 30 +0.0 + 11 +4083.5646700276411 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +59F + 8 +1 + 10 +3433.8180700276389 + 20 +18670.880674968659 + 30 +0.0 + 11 +3433.8180700276389 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A0 + 8 +1 + 10 +4083.5646700276388 + 20 +18670.880674968659 + 30 +0.0 + 11 +4083.5646700276388 + 21 +19170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A1 + 8 +1 + 10 +1484.578270027635 + 20 +20670.880674968659 + 30 +0.0 + 11 +1484.5782700276341 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A2 + 8 +1 + 10 +2134.3248700276358 + 20 +20670.880674968659 + 30 +0.0 + 11 +2134.324870027634 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A3 + 8 +1 + 10 +2784.0714700276349 + 20 +20670.880674968659 + 30 +0.0 + 11 +2784.0714700276349 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A4 + 8 +1 + 10 +1484.578270027632 + 20 +21670.880674968659 + 30 +0.0 + 11 +1484.578270027632 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A5 + 8 +1 + 10 +2134.3248700276322 + 20 +21670.880674968659 + 30 +0.0 + 11 +2134.3248700276308 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A6 + 8 +1 + 10 +2784.0714700276312 + 20 +21670.880674968659 + 30 +0.0 + 11 +2784.0714700276312 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A7 + 8 +1 + 10 +3433.8180700276348 + 20 +20670.880674968659 + 30 +0.0 + 11 +3433.8180700276348 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A8 + 8 +1 + 10 +4083.5646700276361 + 20 +20670.880674968659 + 30 +0.0 + 11 +4083.5646700276361 + 21 +21170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5A9 + 8 +1 + 10 +3433.8180700276321 + 20 +21670.880674968659 + 30 +0.0 + 11 +3433.8180700276321 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5AA + 8 +1 + 10 +4083.564670027632 + 20 +21670.880674968659 + 30 +0.0 + 11 +4083.564670027632 + 21 +22170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5AB + 8 +1 + 10 +6682.541299469256 + 20 +19670.88067496867 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AC + 8 +1 + 10 +6032.7971421088514 + 20 +19670.88067496867 + 30 +0.0 + 11 +6032.7971421088514 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AD + 8 +1 + 10 +4733.3088273880439 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.3088273880421 + 21 +20170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5AE + 8 +1 + 10 +5383.0529847484486 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.0529847484468 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AF + 8 +1 + 10 +4733.3088273880467 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.3088273880467 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B0 + 8 +1 + 10 +4733.3088273880467 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.3088273880458 + 21 +18170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5B1 + 8 +1 + 10 +5383.0529847484522 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.0529847484522 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B2 + 8 +1 + 10 +5383.0529847484522 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.0529847484504 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B3 + 8 +1 + 10 +6032.7971421088541 + 20 +17670.880674968681 + 30 +0.0 + 11 +6032.7971421088541 + 21 +17670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5B4 + 8 +1 + 10 +6032.7971421088541 + 20 +17670.88067496867 + 30 +0.0 + 11 +6032.7971421088541 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B5 + 8 +1 + 10 +5383.0529847484504 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.0529847484486 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B6 + 8 +1 + 10 +4733.3088273880458 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.3088273880439 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B7 + 8 +1 + 10 +4733.3088273880458 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.3088273880458 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B8 + 8 +1 + 10 +5383.0529847484504 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.0529847484504 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B9 + 8 +1 + 10 +4733.3088273880439 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.3088273880439 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BA + 8 +1 + 10 +5383.0529847484486 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.0529847484486 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BB + 8 +1 + 10 +6032.7971421088541 + 20 +18670.88067496867 + 30 +0.0 + 11 +6032.7971421088514 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BC + 8 +1 + 10 +6032.7971421088541 + 20 +18670.880674968681 + 30 +0.0 + 11 +6032.7971421088541 + 21 +18670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5BD + 8 +1 + 10 +6032.7971421088514 + 20 +19670.880674968681 + 30 +0.0 + 11 +6032.7971421088514 + 21 +19670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5BE + 8 +1 + 10 +6682.5412994692597 + 20 +17670.880674968681 + 30 +0.0 + 11 +6682.5412994692597 + 21 +17670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5BF + 8 +1 + 10 +6682.5412994692597 + 20 +17670.88067496867 + 30 +0.0 + 11 +6682.5412994692597 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C0 + 8 +1 + 10 +6682.541299469256 + 20 +19670.880674968681 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5C1 + 8 +1 + 10 +4733.3088273880421 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.3088273880421 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C2 + 8 +1 + 10 +4733.3088273880421 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.3088273880403 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C3 + 8 +1 + 10 +5383.0529847484449 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.0529847484449 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C4 + 8 +1 + 10 +5383.0529847484449 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.0529847484431 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C5 + 8 +1 + 10 +6032.7971421088514 + 20 +20670.880674968681 + 30 +0.0 + 11 +6032.7971421088514 + 21 +20670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5C6 + 8 +1 + 10 +6032.7971421088514 + 20 +20670.88067496867 + 30 +0.0 + 11 +6032.7971421088469 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C7 + 8 +1 + 10 +4733.3088273880394 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.3088273880367 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C8 + 8 +1 + 10 +5383.0529847484431 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.0529847484422 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C9 + 8 +1 + 10 +4733.3088273880394 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.3088273880394 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CA + 8 +1 + 10 +5383.0529847484431 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.0529847484431 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CB + 8 +1 + 10 +6032.7971421088469 + 20 +21670.88067496867 + 30 +0.0 + 11 +6032.7971421088459 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CC + 8 +1 + 10 +6032.7971421088469 + 20 +21670.880674968681 + 30 +0.0 + 11 +6032.7971421088469 + 21 +21670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5CD + 8 +1 + 10 +6682.5412994692533 + 20 +21670.88067496867 + 30 +0.0 + 11 +6682.5412994692506 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CE + 8 +1 + 10 +6682.5412994692533 + 20 +21670.880674968681 + 30 +0.0 + 11 +6682.5412994692533 + 21 +21670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5CF + 8 +1 + 10 +834.83167002762264 + 20 +28670.880674968659 + 30 +0.0 + 11 +4733.3088273880294 + 21 +28670.880674968659 + 31 +0.0 + 0 +TEXT + 5 +5D0 + 8 +1 + 10 +834.83167002762264 + 20 +28670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 7 +KANJI2 + 0 +LINE + 5 +5D1 + 8 +1 + 10 +834.83167002762264 + 20 +29170.880674968659 + 30 +0.0 + 11 +4733.3088273880276 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5D2 + 8 +1 + 10 +834.83167002762264 + 20 +26670.880674968659 + 30 +0.0 + 11 +6682.5412994692406 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D3 + 8 +1 + 10 +834.83167002762264 + 20 +27170.880674968659 + 30 +0.0 + 11 +6682.5412994692424 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D4 + 8 +1 + 10 +834.83167002762264 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 7 +KANJI2 + 72 + 2 + 11 +6682.5474060682318 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D5 + 8 +1 + 10 +834.83167002762264 + 20 +25670.880674968659 + 30 +0.0 + 11 +6032.7971421088378 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D6 + 8 +1 + 10 +834.83167002762264 + 20 +26170.880674968659 + 30 +0.0 + 11 +6032.7971421088369 + 21 +26170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D7 + 8 +1 + 10 +834.83167002762411 + 20 +25672.149710501661 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 4 + 11 +3433.8164416012269 + 21 +25905.652248572718 + 31 +0.0 + 0 +TEXT + 5 +5D8 + 8 +1 + 10 +834.83167002762639 + 20 +24670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 7 +KANJI2 + 11 +834.83167002762639 + 21 +25170.880674968659 + 31 +0.0 + 73 + 3 + 0 +LINE + 5 +5D9 + 8 +1 + 10 +834.83167002762639 + 20 +24670.880674968659 + 30 +0.0 + 11 +6032.7971421088396 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DA + 8 +1 + 10 +834.83167002762457 + 20 +25170.880674968659 + 30 +0.0 + 11 +6032.7971421088378 + 21 +25170.880674968659 + 31 +0.0 + 0 +TEXT + 5 +5DB + 8 +1 + 10 +834.83167002762264 + 20 +27670.880674968681 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 41 +0.9 + 7 +KANJI2 + 72 + 5 + 11 +6682.5474060682318 + 21 +27670.880674968681 + 31 +0.0 + 0 +LINE + 5 +5DC + 8 +1 + 10 +834.83167002762264 + 20 +28170.880674968659 + 30 +0.0 + 11 +6682.5412994692424 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DD + 8 +1 + 10 +834.83167002762264 + 20 +27670.880674968659 + 30 +0.0 + 11 +6682.5412994692406 + 21 +27670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DE + 8 +1 + 10 +834.83167002762809 + 20 +24170.880674968659 + 30 +0.0 + 11 +6682.5412994692424 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DF + 8 +1 + 10 +834.83167002762809 + 20 +23670.880674968659 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E0 + 8 +1 + 10 +834.83167002762991 + 20 +23170.880674968659 + 30 +0.0 + 11 +6032.7971421088441 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E1 + 8 +1 + 10 +834.83167002762991 + 20 +22670.880674968659 + 30 +0.0 + 11 +6032.7971421088459 + 21 +22670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5E2 + 8 +1 + 10 +834.83167002762809 + 20 +23670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.6895380479318 + 21 +24170.880674968659 + 31 +0.0 + 73 + 3 + 0 +LINE + 5 +5E3 + 8 +1 + 10 +834.83167002762809 + 20 +23670.880674968659 + 30 +0.0 + 11 +834.83167002762809 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E4 + 8 +1 + 10 +834.83167002762991 + 20 +22670.880674968659 + 30 +0.0 + 11 +834.83167002762991 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E5 + 8 +1 + 10 +834.83167002762639 + 20 +24670.880674968659 + 30 +0.0 + 11 +834.83167002762457 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E6 + 8 +1 + 10 +834.83167002762264 + 20 +26670.880674968659 + 30 +0.0 + 11 +834.83167002762264 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E7 + 8 +1 + 10 +834.83167002762264 + 20 +25670.880674968659 + 30 +0.0 + 11 +834.83167002762264 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E8 + 8 +1 + 10 +834.83167002762264 + 20 +27670.880674968659 + 30 +0.0 + 11 +834.83167002762264 + 21 +28170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5E9 + 8 +1 + 10 +834.83167002762264 + 20 +28670.880674968659 + 30 +0.0 + 11 +834.83167002762264 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5EA + 8 +1 + 10 +2784.0714700276271 + 20 +23670.880674968659 + 30 +0.0 + 11 +2784.0714700276271 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5EB + 8 +1 + 10 +2134.324870027629 + 20 +23670.880674968659 + 30 +0.0 + 11 +2134.3248700276272 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5EC + 8 +1 + 10 +1484.5782700276279 + 20 +23670.880674968659 + 30 +0.0 + 11 +1484.5782700276279 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5ED + 8 +1 + 10 +1484.57827002763 + 20 +22670.880674968659 + 30 +0.0 + 11 +1484.57827002763 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5EE + 8 +1 + 10 +2134.3248700276308 + 20 +22670.880674968659 + 30 +0.0 + 11 +2134.324870027629 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5EF + 8 +1 + 10 +2784.0714700276289 + 20 +22670.880674968659 + 30 +0.0 + 11 +2784.0714700276289 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F0 + 8 +1 + 10 +1484.578270027625 + 20 +24670.880674968659 + 30 +0.0 + 11 +1484.578270027625 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F1 + 8 +1 + 10 +2134.3248700276249 + 20 +24670.880674968659 + 30 +0.0 + 11 +2134.3248700276231 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F2 + 8 +1 + 10 +2784.0714700276239 + 20 +24670.880674968659 + 30 +0.0 + 11 +2784.0714700276239 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F3 + 8 +1 + 10 +4083.5646700276279 + 20 +23670.880674968659 + 30 +0.0 + 11 +4083.5646700276279 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F4 + 8 +1 + 10 +3433.818070027628 + 20 +23670.880674968659 + 30 +0.0 + 11 +3433.818070027628 + 21 +24170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F5 + 8 +1 + 10 +3433.8180700276289 + 20 +22670.880674968659 + 30 +0.0 + 11 +3433.8180700276289 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F6 + 8 +1 + 10 +4083.5646700276288 + 20 +22670.880674968659 + 30 +0.0 + 11 +4083.5646700276288 + 21 +23170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F7 + 8 +1 + 10 +3433.8180700276248 + 20 +24670.880674968659 + 30 +0.0 + 11 +3433.8180700276248 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F8 + 8 +1 + 10 +4083.5646700276252 + 20 +24670.880674968659 + 30 +0.0 + 11 +4083.5646700276252 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5F9 + 8 +1 + 10 +2784.0714700276221 + 20 +26670.880674968659 + 30 +0.0 + 11 +2784.0714700276221 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FA + 8 +1 + 10 +1484.5782700276229 + 20 +26670.880674968659 + 30 +0.0 + 11 +1484.5782700276229 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FB + 8 +1 + 10 +2134.3248700276231 + 20 +26670.880674968659 + 30 +0.0 + 11 +2134.3248700276208 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FC + 8 +1 + 10 +1484.5782700276229 + 20 +25670.880674968659 + 30 +0.0 + 11 +1484.5782700276229 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FD + 8 +1 + 10 +2134.3248700276231 + 20 +25670.880674968659 + 30 +0.0 + 11 +2134.3248700276208 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FE + 8 +1 + 10 +2784.0714700276221 + 20 +25670.880674968659 + 30 +0.0 + 11 +2784.0714700276221 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +5FF + 8 +1 + 10 +4083.564670027622 + 20 +26670.880674968659 + 30 +0.0 + 11 +4083.564670027622 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +600 + 8 +1 + 10 +3433.8180700276221 + 20 +26670.880674968659 + 30 +0.0 + 11 +3433.8180700276221 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +601 + 8 +1 + 10 +3433.8180700276221 + 20 +25670.880674968659 + 30 +0.0 + 11 +3433.8180700276221 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +602 + 8 +1 + 10 +4083.564670027622 + 20 +25670.880674968659 + 30 +0.0 + 11 +4083.564670027622 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +603 + 8 +1 + 10 +6032.7971421088441 + 20 +23670.88067496867 + 30 +0.0 + 11 +6032.7971421088396 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +604 + 8 +1 + 10 +5383.0529847484404 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.0529847484377 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +605 + 8 +1 + 10 +4733.3088273880348 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.3088273880321 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +606 + 8 +1 + 10 +4733.3088273880367 + 20 +22670.88067496867 + 30 +0.0 + 11 +4733.3088273880367 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +607 + 8 +1 + 10 +4733.3088273880367 + 20 +22670.880674968659 + 30 +0.0 + 11 +4733.3088273880348 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +608 + 8 +1 + 10 +5383.0529847484422 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.0529847484422 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +609 + 8 +1 + 10 +5383.0529847484422 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.0529847484404 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60A + 8 +1 + 10 +4733.3088273880348 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.3088273880348 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60B + 8 +1 + 10 +5383.0529847484404 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.0529847484404 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60C + 8 +1 + 10 +6032.7971421088459 + 20 +22670.880674968681 + 30 +0.0 + 11 +6032.7971421088459 + 21 +22670.880674968681 + 31 +0.0 + 0 +LINE + 5 +60D + 8 +1 + 10 +6032.7971421088459 + 20 +22670.88067496867 + 30 +0.0 + 11 +6032.7971421088441 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60E + 8 +1 + 10 +6032.7971421088441 + 20 +23670.880674968681 + 30 +0.0 + 11 +6032.7971421088441 + 21 +23670.880674968681 + 31 +0.0 + 0 +LINE + 5 +60F + 8 +1 + 10 +4733.3088273880312 + 20 +24670.880674968659 + 30 +0.0 + 11 +4733.3088273880294 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +610 + 8 +1 + 10 +5383.0529847484349 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +611 + 8 +1 + 10 +4733.3088273880312 + 20 +24670.88067496867 + 30 +0.0 + 11 +4733.3088273880312 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +612 + 8 +1 + 10 +5383.0529847484349 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.0529847484349 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +613 + 8 +1 + 10 +6032.7971421088396 + 20 +24670.88067496867 + 30 +0.0 + 11 +6032.7971421088378 + 21 +25170.880674968659 + 31 +0.0 + 0 +LINE + 5 +614 + 8 +1 + 10 +6032.7971421088396 + 20 +24670.880674968681 + 30 +0.0 + 11 +6032.7971421088396 + 21 +24670.880674968681 + 31 +0.0 + 0 +LINE + 5 +615 + 8 +1 + 10 +6682.541299469247 + 20 +23670.88067496867 + 30 +0.0 + 11 +6682.5412994692424 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +616 + 8 +1 + 10 +6682.541299469247 + 20 +23670.880674968681 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.880674968681 + 31 +0.0 + 0 +LINE + 5 +617 + 8 +1 + 10 +6032.7971421088378 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.7971421088369 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +618 + 8 +1 + 10 +4733.3088273880294 + 20 +26670.880674968659 + 30 +0.0 + 11 +4733.3088273880276 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +619 + 8 +1 + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.0529847484322 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61A + 8 +1 + 10 +4733.3088273880294 + 20 +25670.88067496867 + 30 +0.0 + 11 +4733.3088273880294 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61B + 8 +1 + 10 +4733.3088273880294 + 20 +25670.880674968659 + 30 +0.0 + 11 +4733.3088273880276 + 21 +26170.880674968659 + 31 +0.0 + 0 +LINE + 5 +61C + 8 +1 + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61D + 8 +1 + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.0529847484322 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61E + 8 +1 + 10 +4733.3088273880294 + 20 +26670.88067496867 + 30 +0.0 + 11 +4733.3088273880294 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61F + 8 +1 + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +620 + 8 +1 + 10 +6032.7971421088378 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.7971421088378 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +621 + 8 +1 + 10 +6032.7971421088378 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.7971421088369 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +622 + 8 +1 + 10 +6032.7971421088378 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.7971421088378 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +623 + 8 +1 + 10 +6682.5412994692406 + 20 +26670.88067496867 + 30 +0.0 + 11 +6682.5412994692424 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +624 + 8 +1 + 10 +6682.5412994692424 + 20 +26670.880674968681 + 30 +0.0 + 11 +6682.5412994692424 + 21 +26670.880674968681 + 31 +0.0 + 0 +LINE + 5 +625 + 8 +1 + 10 +6682.5412994692406 + 20 +27670.88067496867 + 30 +0.0 + 11 +6682.5412994692424 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +626 + 8 +1 + 10 +6682.5412994692424 + 20 +27670.880674968681 + 30 +0.0 + 11 +6682.5412994692424 + 21 +27670.880674968681 + 31 +0.0 + 0 +LINE + 5 +627 + 8 +1 + 10 +1484.5782700276229 + 20 +28670.880674968659 + 30 +0.0 + 11 +1484.5782700276229 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +628 + 8 +1 + 10 +2134.3248700276231 + 20 +28670.880674968659 + 30 +0.0 + 11 +2134.3248700276208 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +629 + 8 +1 + 10 +2784.0714700276221 + 20 +28670.880674968659 + 30 +0.0 + 11 +2784.0714700276221 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +62A + 8 +1 + 10 +3433.8180700276221 + 20 +28670.880674968659 + 30 +0.0 + 11 +3433.8180700276221 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +62B + 8 +1 + 10 +4083.564670027622 + 20 +28670.880674968659 + 30 +0.0 + 11 +4083.564670027622 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +62C + 8 +1 + 10 +4733.3088273880294 + 20 +28670.88067496867 + 30 +0.0 + 11 +4733.3088273880294 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +62D + 8 +1 + 10 +4733.3088273880294 + 20 +28670.880674968659 + 30 +0.0 + 11 +4733.3088273880276 + 21 +29170.880674968659 + 31 +0.0 + 0 +TEXT + 5 +62E + 8 +1 + 10 +8432.9106362633793 + 20 +22670.880674968688 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +23170.880674968688 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +62F + 8 +1 + 10 +8432.9106362633793 + 20 +21670.880674968688 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI + 11 +8432.9106362633793 + 21 +21920.880674968688 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +630 + 8 +1 + 10 +8432.9106362633793 + 20 +22170.880674968688 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.880674968688 + 31 +0.0 + 0 +LINE + 5 +631 + 8 +1 + 10 +8432.9106362633793 + 20 +21670.880674968688 + 30 +0.0 + 11 +15266.24396959671 + 21 +21670.880674968688 + 31 +0.0 + 0 +LINE + 5 +632 + 8 +1 + 10 +8432.9106362633793 + 20 +20670.880674968699 + 30 +0.0 + 11 +14666.24396959671 + 21 +20670.880674968699 + 31 +0.0 + 0 +LINE + 5 +633 + 8 +1 + 10 +8432.9106362633793 + 20 +21170.880674968699 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.880674968699 + 31 +0.0 + 0 +TEXT + 5 +634 + 8 +1 + 10 +8432.9106362633793 + 20 +20670.880674968699 + 30 +0.0 + 40 +500.00000000000028 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 1 + 11 +11549.57730293004 + 21 +20920.880674968699 + 31 +0.0 + 73 + 2 + 0 +LINE + 5 +635 + 8 +1 + 10 +8432.9106362633793 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +19670.88067496871 + 31 +0.0 + 0 +LINE + 5 +636 + 8 +1 + 10 +8432.9106362633793 + 20 +20170.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +TEXT + 5 +637 + 8 +1 + 10 +8432.9106362633793 + 20 +19670.88067496871 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI + 72 + 2 + 11 +15266.24396959671 + 21 +19920.88067496871 + 31 +0.0 + 73 + 2 + 0 +TEXT + 5 +638 + 8 +1 + 10 +8432.9106362633793 + 20 +18737.547341635389 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI + 11 +8432.9106362633793 + 21 +18670.880674968721 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +639 + 8 +1 + 10 +8432.9106362633793 + 20 +19170.880674968721 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.880674968721 + 31 +0.0 + 0 +LINE + 5 +63A + 8 +1 + 10 +8432.9106362633793 + 20 +18670.880674968721 + 30 +0.0 + 11 +14666.24396959671 + 21 +18670.880674968721 + 31 +0.0 + 0 +TEXT + 5 +63B + 8 +1 + 10 +8432.9106362633793 + 20 +17670.880674968739 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +17604.214008302071 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +63C + 8 +1 + 10 +8432.9106362633793 + 20 +18170.880674968728 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.880674968728 + 31 +0.0 + 0 +LINE + 5 +63D + 8 +1 + 10 +8432.9106362633793 + 20 +17670.880674968739 + 30 +0.0 + 11 +15266.24396959671 + 21 +17670.880674968728 + 31 +0.0 + 0 +TEXT + 5 +63E + 8 +1 + 10 +8432.9106362633847 + 20 +16670.88067496875 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +16604.214008302079 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +63F + 8 +1 + 10 +8432.9106362633793 + 20 +16670.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +16670.880674968739 + 31 +0.0 + 0 +LINE + 5 +640 + 8 +1 + 10 +8432.9106362633793 + 20 +17170.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +641 + 8 +1 + 10 +8432.9106362633793 + 20 +16670.88067496875 + 30 +0.0 + 11 +8432.9106362633793 + 21 +17170.880674968739 + 31 +0.0 + 0 +LINE + 5 +642 + 8 +0 + 10 +8432.9106362633847 + 20 +13184.111299325979 + 30 +0.0 + 11 +12965.81622044203 + 21 +13184.11129932597 + 31 +0.0 + 0 +LINE + 5 +643 + 8 +1 + 10 +8432.9106362633847 + 20 +14517.44463265931 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +INSERT + 5 +644 + 8 +1 + 2 +*U63 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +LINE + 5 +645 + 8 +1 + 10 +8432.9106362633847 + 20 +15140.896290833191 + 30 +0.0 + 11 +14166.24396959671 + 21 +15140.896290833191 + 31 +0.0 + 0 +TEXT + 5 +646 + 8 +1 + 10 +8432.9106362633847 + 20 +15140.896290833191 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI + 72 + 2 + 11 +14166.24396959671 + 21 +15140.896290833191 + 31 +0.0 + 0 +LINE + 5 +647 + 8 +1 + 10 +8432.9106362633847 + 20 +16140.896290833191 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.896290833191 + 31 +0.0 + 0 +LINE + 5 +648 + 8 +1 + 10 +8432.9106362633847 + 20 +14517.44463265931 + 30 +0.0 + 11 +8432.9106362633847 + 21 +13184.111299325979 + 31 +0.0 + 0 +LINE + 5 +649 + 8 +1 + 10 +8432.9106362633847 + 20 +15140.896290833191 + 30 +0.0 + 11 +8432.9106362633847 + 21 +16140.896290833191 + 31 +0.0 + 0 +LINE + 5 +64A + 8 +1 + 10 +12965.81622044203 + 20 +13184.11129932597 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +LINE + 5 +64D + 8 +1 + 10 +14166.24396959671 + 20 +15140.896290833191 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.896290833191 + 31 +0.0 + 0 +LINE + 5 +64E + 8 +1 + 10 +8432.9106362633793 + 20 +19670.88067496871 + 30 +0.0 + 11 +8432.9106362633793 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +64F + 8 +1 + 10 +8432.9106362633793 + 20 +17670.880674968739 + 30 +0.0 + 11 +8432.9106362633793 + 21 +18170.880674968728 + 31 +0.0 + 0 +LINE + 5 +650 + 8 +1 + 10 +8432.9106362633793 + 20 +18670.880674968721 + 30 +0.0 + 11 +8432.9106362633793 + 21 +19170.880674968721 + 31 +0.0 + 0 +LINE + 5 +651 + 8 +1 + 10 +8432.9106362633793 + 20 +20670.880674968699 + 30 +0.0 + 11 +8432.9106362633793 + 21 +21170.880674968699 + 31 +0.0 + 0 +LINE + 5 +652 + 8 +1 + 10 +8432.9106362633793 + 20 +21670.880674968688 + 30 +0.0 + 11 +8432.9106362633793 + 21 +22170.880674968688 + 31 +0.0 + 0 +LINE + 5 +653 + 8 +1 + 10 +14666.24396959671 + 20 +16670.880674968739 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +654 + 8 +1 + 10 +15266.24396959671 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +655 + 8 +1 + 10 +15266.24396959671 + 20 +17670.880674968728 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.880674968728 + 31 +0.0 + 0 +LINE + 5 +656 + 8 +1 + 10 +14666.24396959671 + 20 +18670.880674968721 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.880674968721 + 31 +0.0 + 0 +LINE + 5 +657 + 8 +1 + 10 +14666.24396959671 + 20 +20670.880674968699 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.880674968699 + 31 +0.0 + 0 +LINE + 5 +658 + 8 +1 + 10 +15266.24396959671 + 20 +21670.880674968688 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.880674968688 + 31 +0.0 + 0 +LINE + 5 +659 + 8 +1 + 10 +8432.9106362633793 + 20 +26670.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +26670.880674968659 + 31 +0.0 + 0 +LINE + 5 +65A + 8 +1 + 10 +8432.9106362633793 + 20 +27170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +65B + 8 +1 + 10 +8432.9106362633811 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI + 72 + 2 + 11 +15232.91063626337 + 21 +26670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +65C + 8 +1 + 10 +8432.9106362633793 + 20 +25670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +65D + 8 +1 + 10 +8432.9106362633793 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +65E + 8 +1 + 10 +8432.9106362633793 + 20 +26170.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +65F + 8 +1 + 10 +8432.9106362633793 + 20 +24670.880674968681 + 30 +0.0 + 11 +14666.24396959671 + 21 +24670.880674968681 + 31 +0.0 + 0 +LINE + 5 +660 + 8 +1 + 10 +8432.9106362633793 + 20 +25170.880674968681 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.880674968681 + 31 +0.0 + 0 +TEXT + 5 +661 + 8 +1 + 10 +8432.9106362633793 + 20 +24670.880674968681 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI + 11 +8432.9106362633793 + 21 +25170.880674968681 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +662 + 8 +1 + 10 +8432.9106362633793 + 20 +27670.880674968659 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.9272727272727273 + 7 +KANJI + 72 + 5 + 11 +15232.91063626337 + 21 +27670.880674968659 + 31 +0.0 + 0 +LINE + 5 +663 + 8 +1 + 10 +8432.9106362633793 + 20 +27670.880674968659 + 30 +0.0 + 11 +15232.91063626337 + 21 +27670.880674968659 + 31 +0.0 + 0 +LINE + 5 +664 + 8 +1 + 10 +8432.9106362633793 + 20 +28170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +665 + 8 +1 + 10 +8432.9106362633793 + 20 +22670.880674968688 + 30 +0.0 + 11 +14666.24396959671 + 21 +22670.880674968681 + 31 +0.0 + 0 +LINE + 5 +666 + 8 +1 + 10 +8432.9106362633793 + 20 +23170.880674968688 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.880674968688 + 31 +0.0 + 0 +LINE + 5 +667 + 8 +1 + 10 +8432.9106362633793 + 20 +23670.880674968681 + 30 +0.0 + 11 +15266.24396959671 + 21 +23670.880674968681 + 31 +0.0 + 0 +LINE + 5 +668 + 8 +1 + 10 +8432.9106362633793 + 20 +24170.880674968688 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.880674968688 + 31 +0.0 + 0 +TEXT + 5 +669 + 8 +1 + 10 +8432.9106362633793 + 20 +23670.880674968681 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +24170.880674968688 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +66A + 8 +1 + 10 +8432.9106362633793 + 20 +28670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI + 0 +LINE + 5 +66B + 8 +1 + 10 +8432.9106362633793 + 20 +23670.880674968681 + 30 +0.0 + 11 +8432.9106362633793 + 21 +24170.880674968681 + 31 +0.0 + 0 +LINE + 5 +66C + 8 +1 + 10 +8432.9106362633793 + 20 +22670.880674968688 + 30 +0.0 + 11 +8432.9106362633793 + 21 +23170.880674968688 + 31 +0.0 + 0 +LINE + 5 +66D + 8 +1 + 10 +8432.9106362633793 + 20 +24670.880674968681 + 30 +0.0 + 11 +8432.9106362633793 + 21 +25170.88067496867 + 31 +0.0 + 0 +LINE + 5 +66E + 8 +1 + 10 +8432.9106362633793 + 20 +26670.88067496867 + 30 +0.0 + 11 +8432.9106362633793 + 21 +27170.880674968659 + 31 +0.0 + 0 +LINE + 5 +66F + 8 +1 + 10 +8432.9106362633793 + 20 +25670.88067496867 + 30 +0.0 + 11 +8432.9106362633793 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +670 + 8 +1 + 10 +8432.9106362633793 + 20 +27670.880674968659 + 30 +0.0 + 11 +8432.9106362633793 + 21 +28170.880674968659 + 31 +0.0 + 0 +LINE + 5 +671 + 8 +1 + 10 +8432.9106362633793 + 20 +29170.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +672 + 8 +1 + 10 +8432.9106362633793 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +673 + 8 +1 + 10 +8432.9106362633793 + 20 +28670.88067496867 + 30 +0.0 + 11 +8432.9106362633793 + 21 +29170.880674968659 + 31 +0.0 + 0 +LINE + 5 +674 + 8 +1 + 10 +13432.91063626337 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +675 + 8 +1 + 10 +15266.24396959671 + 20 +23670.880674968681 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.880674968688 + 31 +0.0 + 0 +LINE + 5 +676 + 8 +1 + 10 +14666.24396959671 + 20 +22670.880674968681 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.880674968688 + 31 +0.0 + 0 +LINE + 5 +677 + 8 +1 + 10 +14666.24396959671 + 20 +24670.880674968681 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.880674968681 + 31 +0.0 + 0 +LINE + 5 +678 + 8 +1 + 10 +15232.91063626337 + 20 +26670.880674968659 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +679 + 8 +1 + 10 +14666.24396959671 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67A + 8 +1 + 10 +15232.91063626337 + 20 +27670.880674968659 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67D + 8 +0 + 10 +17739.86399912307 + 20 +23517.206009005909 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.206009005909 + 31 +0.0 + 0 +LINE + 5 +67E + 8 +0 + 10 +17739.86399912307 + 20 +23517.206009005909 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.206009005909 + 31 +0.0 + 0 +LINE + 5 +680 + 8 +0 + 10 +17739.86399912307 + 20 +23517.206009005899 + 30 +0.0 + 11 +18739.863999123081 + 21 +23517.206009005899 + 31 +0.0 + 0 +TEXT + 5 +681 + 8 +1 + 10 +25683.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI3 + 72 + 2 + 11 +25683.308734635291 + 21 +12102.105483787929 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +685 + 8 +1 + 10 +21683.30873463532 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI3 + 11 +21683.30873463532 + 21 +21085.438817121259 + 31 +0.0 + 73 + 1 + 0 +TEXT + 5 +686 + 8 +1 + 10 +22683.30873463531 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI3 + 72 + 2 + 11 +22683.30873463531 + 21 +11468.772150454601 + 31 +0.0 + 73 + 2 + 0 +TEXT + 5 +689 + 8 +1 + 10 +23683.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 1 + 11 +23683.308734635299 + 21 +16577.10548378792 + 31 +0.0 + 73 + 2 + 0 +TEXT + 5 +68E + 8 +1 + 10 +24683.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI3 + 11 +24683.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 73 + 2 + 0 +TEXT + 5 +697 + 8 +1 + 10 +26683.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI3 + 72 + 1 + 11 +26683.30873463528 + 21 +16277.105483787929 + 31 +0.0 + 73 + 3 + 0 +TEXT + 5 +69E + 8 +1 + 10 +30683.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.6677577741407528 + 7 +KANJI3 + 72 + 2 + 11 +30683.30873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +TEXT + 5 +69F + 8 +1 + 10 +27683.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI3 + 11 +27683.30873463528 + 21 +21085.438817121259 + 31 +0.0 + 73 + 3 + 0 +LINE + 5 +6A2 + 8 +1 + 10 +28933.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6A3 + 8 +1 + 10 +28433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +28433.308734635259 + 21 +12068.77215045459 + 31 +0.0 + 0 +TEXT + 5 +6A4 + 8 +1 + 10 +28683.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 2 + 11 +28683.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +TEXT + 5 +6A5 + 8 +1 + 10 +29683.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI3 + 72 + 2 + 11 +29683.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +TEXT + 5 +6A8 + 8 +1 + 10 +31683.308734635259 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI3 + 72 + 2 + 11 +31683.308734635259 + 21 +13418.77215045459 + 31 +0.0 + 0 +TEXT + 5 +6BB + 8 +1 + 10 +19683.30873463535 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI3 + 72 + 2 + 11 +19683.30873463535 + 21 +12068.772150454601 + 31 +0.0 + 73 + 1 + 0 +TEXT + 5 +6BD + 8 +1 + 10 +20683.308734635331 + 20 +21085.438817121259 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI3 + 72 + 1 + 11 +20683.308734635331 + 21 +16277.105483787929 + 31 +0.0 + 73 + 1 + 0 +LINE + 5 +6BF + 8 +1 + 10 +18903.324350499799 + 20 +21085.438817121259 + 30 +0.0 + 11 +18903.324350499799 + 21 +16485.438817121259 + 31 +0.0 + 0 +TEXT + 5 +6C0 + 8 +1 + 10 +18403.324350499799 + 20 +21085.438817121259 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 7 +KANJI3 + 0 +LINE + 5 +6C1 + 8 +1 + 10 +17903.324350499799 + 20 +21085.438817121259 + 30 +0.0 + 11 +17903.324350499799 + 21 +16485.438817121259 + 31 +0.0 + 0 +INSERT + 5 +6C2 + 8 +1 + 2 +*U64 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +LINE + 5 +6C3 + 8 +1 + 10 +17479.87269232592 + 20 +21085.438817121259 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.245518275209 + 31 +0.0 + 0 +LINE + 5 +6C4 + 8 +0 + 10 +15946.539358992581 + 20 +21085.438817121259 + 30 +0.0 + 11 +15946.53935899257 + 21 +15002.245518275209 + 31 +0.0 + 0 +LINE + 5 +6C5 + 8 +1 + 10 +17479.87269232592 + 20 +21085.438817121259 + 30 +0.0 + 11 +15946.539358992581 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6C6 + 8 +1 + 10 +17903.324350499799 + 20 +21085.438817121259 + 30 +0.0 + 11 +18903.324350499799 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6C7 + 8 +1 + 10 +15946.53935899257 + 20 +15002.245518275209 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.245518275209 + 31 +0.0 + 0 +LINE + 5 +6CC + 8 +0 + 10 +17903.324350499799 + 20 +16485.438817121259 + 30 +0.0 + 11 +18903.324350499799 + 21 +16485.438817121259 + 31 +0.0 + 0 +LINE + 5 +6CD + 8 +0 + 10 +28433.308734635259 + 20 +12068.77215045459 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6CF + 8 +0 + 10 +28433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +28933.30873463527 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6D0 + 8 +1 + 10 +27433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +27433.30873463527 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6D1 + 8 +1 + 10 +27933.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6D3 + 8 +0 + 10 +27433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +27933.30873463528 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6D4 + 8 +0 + 10 +26433.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6D8 + 8 +0 + 10 +25433.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +25933.30873463528 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6D9 + 8 +0 + 10 +25433.30873463527 + 20 +12102.105483787929 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6DA + 8 +1 + 10 +25433.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +25433.30873463527 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6DB + 8 +1 + 10 +25933.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6DC + 8 +0 + 10 +24433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +24933.308734635291 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6F0 + 8 +0 + 10 +27433.30873463527 + 20 +12102.105483787929 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.105483787929 + 31 +0.0 + 0 +LINE + 5 +6F1 + 8 +1 + 10 +29433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +29433.308734635259 + 21 +11502.105483787929 + 31 +0.0 + 0 +LINE + 5 +6F2 + 8 +1 + 10 +29933.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F3 + 8 +0 + 10 +29433.308734635259 + 20 +11502.105483787929 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F4 + 8 +0 + 10 +29433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +29933.30873463527 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6FA + 8 +1 + 10 +26433.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +26433.30873463528 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +6FB + 8 +1 + 10 +26933.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +6FD + 8 +0 + 10 +26433.30873463528 + 20 +21085.438817121259 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +6FE + 8 +0 + 10 +26433.30873463528 + 20 +11468.772150454601 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +6FF + 8 +1 + 10 +24433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +24433.308734635291 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +700 + 8 +1 + 10 +24933.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +701 + 8 +0 + 10 +24433.308734635291 + 20 +11468.772150454601 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +702 + 8 +0 + 10 +24433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +24933.308734635291 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +703 + 8 +0 + 10 +24433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +24933.308734635291 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +704 + 8 +1 + 10 +23433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +23433.30873463528 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +705 + 8 +1 + 10 +23933.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +23933.308734635291 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +706 + 8 +0 + 10 +23433.30873463528 + 20 +12068.77215045459 + 30 +0.0 + 11 +23933.308734635291 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +707 + 8 +0 + 10 +23433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +23933.308734635291 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +708 + 8 +1 + 10 +22933.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +22933.308734635291 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +709 + 8 +1 + 10 +22433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +22433.308734635291 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +70A + 8 +0 + 10 +22433.308734635291 + 20 +11468.772150454601 + 30 +0.0 + 11 +22933.308734635291 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +70B + 8 +0 + 10 +22433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +22933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +70C + 8 +0 + 10 +22433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +22933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +70D + 8 +0 + 10 +22433.308734635291 + 20 +21085.438817121259 + 30 +0.0 + 11 +22933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +70E + 8 +1 + 10 +21933.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +21933.308734635291 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +70F + 8 +1 + 10 +21433.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +21433.308734635291 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +710 + 8 +0 + 10 +21433.308734635291 + 20 +12068.77215045459 + 30 +0.0 + 11 +21933.308734635291 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +711 + 8 +0 + 10 +21433.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +21933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +712 + 8 +1 + 10 +20433.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +20433.308734635299 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +713 + 8 +1 + 10 +20933.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +20933.308734635299 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +714 + 8 +0 + 10 +20433.308734635299 + 20 +11468.772150454601 + 30 +0.0 + 11 +20933.308734635299 + 21 +11468.772150454601 + 31 +0.0 + 0 +LINE + 5 +715 + 8 +0 + 10 +20433.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +20933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +716 + 8 +0 + 10 +20433.308734635299 + 20 +21085.438817121259 + 30 +0.0 + 11 +20933.308734635299 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +717 + 8 +1 + 10 +19433.30873463531 + 20 +21085.438817121259 + 30 +0.0 + 11 +19433.308734635299 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +718 + 8 +1 + 10 +19933.30873463531 + 20 +21085.438817121259 + 30 +0.0 + 11 +19933.308734635299 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +719 + 8 +0 + 10 +19433.308734635299 + 20 +12068.77215045459 + 30 +0.0 + 11 +19933.308734635299 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +71A + 8 +0 + 10 +19433.30873463531 + 20 +21085.438817121259 + 30 +0.0 + 11 +19933.30873463531 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +720 + 8 +1 + 10 +31433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +31433.308734635259 + 21 +13418.772150454601 + 31 +0.0 + 0 +LINE + 5 +721 + 8 +1 + 10 +31933.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +722 + 8 +0 + 10 +31433.308734635259 + 20 +13418.772150454601 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +723 + 8 +0 + 10 +31433.30873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +31933.30873463527 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +726 + 8 +1 + 10 +30516.608734635261 + 20 +21085.438817121259 + 30 +0.0 + 11 +30516.608734635261 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +727 + 8 +1 + 10 +30850.00873463527 + 20 +21085.438817121259 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +729 + 8 +0 + 10 +30516.608734635261 + 20 +10902.10548378792 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +72A + 8 +0 + 10 +30516.608734635261 + 20 +21085.438817121259 + 30 +0.0 + 11 +30850.00873463527 + 21 +21085.438817121259 + 31 +0.0 + 0 +LINE + 5 +730 + 8 +0 + 10 +30731.972455416279 + 20 +7516.9220760315229 + 30 +0.0 + 11 +29231.972455416279 + 21 +10114.998287384829 + 31 +0.0 + 0 +LINE + 5 +731 + 8 +0 + 10 +30731.972455416279 + 20 +7516.9220760315229 + 30 +0.0 + 11 +27731.972455416279 + 21 +7516.9220760315229 + 31 +0.0 + 0 +LINE + 5 +732 + 8 +0 + 10 +27731.972455416279 + 20 +7516.9220760315229 + 30 +0.0 + 11 +29231.972455416279 + 21 +10114.998287384829 + 31 +0.0 + 0 +LINE + 5 +735 + 8 +0 + 10 +27731.972455416279 + 20 +9465.4792345465085 + 30 +0.0 + 11 +29231.972455416279 + 21 +6867.4030231931938 + 31 +0.0 + 0 +LINE + 5 +736 + 8 +0 + 10 +27731.972455416279 + 20 +9465.4792345465085 + 30 +0.0 + 11 +30731.972455416279 + 21 +9465.4792345465085 + 31 +0.0 + 0 +LINE + 5 +737 + 8 +0 + 10 +30731.972455416279 + 20 +9465.4792345465085 + 30 +0.0 + 11 +29231.972455416279 + 21 +6867.4030231931938 + 31 +0.0 + 0 +TEXT + 5 +73B + 8 +0 + 10 +27375.985220361581 + 20 +10232.278067765081 + 30 +0.0 + 40 +500.0 + 1 +ƒOƒ‹[ƒv}Œ` + 7 +KANJI + 0 +TEXT + 5 +73C + 8 +0 + 10 +23443.86458478673 + 20 +10232.278067765081 + 30 +0.0 + 40 +500.0 + 1 +ƒuƒƒbƒN}Œ` + 7 +KANJI + 0 +INSERT + 5 +74D + 8 +0 + 2 +NONAME + 10 +12199.75897743096 + 20 +4508.9789285402103 + 30 +0.0 + 41 +0.6 + 42 +0.6 + 43 +0.6 + 0 +LINE + 5 +74E + 8 +0 + 10 +40162.959307891368 + 20 +8789.5158270274333 + 30 +0.0 + 11 +40162.959307891368 + 21 +6789.515827027426 + 31 +0.0 + 0 +LINE + 5 +74F + 8 +0 + 10 +38110.783546968618 + 20 +8789.5158270274333 + 30 +0.0 + 11 +38110.783546968618 + 21 +6789.5158270274278 + 31 +0.0 + 0 +LINE + 5 +750 + 8 +0 + 10 +36162.959307891382 + 20 +6789.5158270274287 + 30 +0.0 + 11 +36162.959307891382 + 21 +8789.5158270274333 + 31 +0.0 + 0 +LINE + 5 +752 + 8 +0 + 10 +34144.217405715019 + 20 +8789.5158270274333 + 30 +0.0 + 11 +34144.217405715019 + 21 +6789.5158270274324 + 31 +0.0 + 0 +LINE + 5 +753 + 8 +0 + 10 +32162.959307891371 + 20 +8789.5158270274333 + 30 +0.0 + 11 +32162.959307891371 + 21 +6789.5158270274351 + 31 +0.0 + 0 +DIMENSION + 5 +755 + 8 +0 + 2 +*D10 + 10 +3334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +2084.8316700276482 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +834.83167002764822 + 23 +3391.885493772555 + 33 +0.0 + 14 +3334.8316700276482 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 + +1070 + 173 +1070 + 1 +1070 + 7 +1000 + +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +801 + 8 +0 + 2 +*D12 + 10 +5834.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +4584.8316700276482 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +3334.8316700276482 + 23 +3391.885493772555 + 33 +0.0 + 14 +5834.8316700276482 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSEDBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSEDBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +83A + 8 +0 + 10 +684.83167002764753 + 20 +5515.901028694454 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +2084.8316700276469 + 21 +5515.901028694454 + 31 +0.0 + 0 +TEXT + 5 +83B + 8 +0 + 10 +1568.165003360981 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +–îˆó + 7 +KANJI + 72 + 1 + 11 +2084.8316700276482 + 21 +4919.6279641725123 + 31 +0.0 + 0 +TEXT + 5 +83C + 8 +0 + 10 +3768.1650033609822 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +‹ó–îˆó + 7 +KANJI + 72 + 1 + 11 +4584.8316700276482 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +83D + 8 +0 + 2 +*D14 + 10 +8334.8316700276482 + 20 +4323.3548996505697 + 30 +0.0 + 11 +7084.8316700276482 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +5834.8316700276482 + 23 +3391.885493772555 + 33 +0.0 + 14 +8334.8316700276482 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +865 + 8 +0 + 10 +6251.4983366943152 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +•Â–îˆó + 7 +KANJI + 72 + 1 + 11 +7084.8316700276482 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +866 + 8 +0 + 2 +*D15 + 10 +10834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +9584.8316700276482 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +8334.8316700276482 + 23 +3391.885493772555 + 33 +0.0 + 14 +10834.831670027639 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOT +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOT +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +893 + 8 +0 + 10 +9051.4983366943125 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +•ŠÛ + 7 +KANJI + 72 + 1 + 11 +9584.8316700276482 + 21 +4919.6279641725123 + 31 +0.0 + 0 +TEXT + 5 +89C + 8 +0 + 10 +11534.831670027639 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +(‘¾) + 7 +KANJI + 72 + 1 + 11 +12084.831670027639 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +89D + 8 +0 + 2 +*D17 + 10 +13334.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +12084.831670027639 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +10834.831670027639 + 23 +3391.885493772555 + 33 +0.0 + 14 +13334.831670027639 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ARCHTICK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ARCHTICK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8C9 + 8 +0 + 10 +13468.16500336098 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +14584.831670027639 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +8CA + 8 +0 + 2 +*D19 + 10 +15834.831670027639 + 20 +4323.3548996505697 + 30 +0.0 + 11 +14584.831670027639 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +13334.831670027639 + 23 +3391.885493772555 + 33 +0.0 + 14 +15834.831670027639 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OBLIQUE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OBLIQUE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F6 + 8 +0 + 10 +10968.16500336098 + 20 +5452.8942228734086 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +12084.831670027639 + 21 +5452.8942228734086 + 31 +0.0 + 0 +DIMENSION + 5 +8F7 + 8 +0 + 2 +*D21 + 10 +18334.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 11 +17084.831670027641 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +15834.831670027639 + 23 +3391.885493772555 + 33 +0.0 + 14 +18334.831670027641 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F8 + 8 +0 + 10 +16251.498336694311 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +ŠJ–îˆó + 7 +KANJI + 72 + 1 + 11 +17084.831670027641 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +92F + 8 +0 + 2 +*D23 + 10 +20834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 11 +19584.831670027641 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +18334.831670027641 + 23 +3391.885493772555 + 33 +0.0 + 14 +20834.831670027641 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +930 + 8 +0 + 10 +18868.16500336098 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ1 + 7 +KANJI + 72 + 1 + 11 +19584.831670027641 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +97D + 8 +0 + 2 +*D25 + 10 +23334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +22084.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +20834.831670027641 + 23 +3391.885493772555 + 33 +0.0 + 14 +23334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN2 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN2 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +97E + 8 +0 + 10 +21284.831670027648 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ2 + 7 +KANJI + 72 + 1 + 11 +22084.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +9C3 + 8 +0 + 2 +*D27 + 10 +25834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +24584.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 13 +23334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +25834.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN90 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN90 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +9C4 + 8 +0 + 10 +23468.16500336098 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +’¼Šp–îˆó + 7 +KANJI + 72 + 1 + 11 +24584.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +AAF + 8 +0 + 2 +*D29 + 10 +28334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +27084.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +25834.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +28334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN30 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN30 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +AB0 + 8 +0 + 10 +25809.831670027641 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +30‹–îˆó + 7 +KANJI + 72 + 1 + 11 +27084.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +TEXT + 5 +AE7 + 8 +0 + 10 +28751.498336694309 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +¬•ŠÛ + 7 +KANJI + 72 + 1 + 11 +29584.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +AE8 + 8 +0 + 2 +*D31 + 10 +30834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +29584.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +28334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +30834.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTSMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTSMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +B1D + 8 +0 + 2 +*D33 + 10 +33334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +32084.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +30834.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +33334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B1E + 8 +0 + 10 +31251.498336694309 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +32084.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +B55 + 8 +0 + 2 +*D35 + 10 +35834.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +34584.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +33334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +35834.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +SMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +SMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B56 + 8 +0 + 10 +33451.498336694312 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +¬‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +34584.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +TEXT + 5 +B82 + 8 +0 + 10 +36551.498336694312 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +37084.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +B83 + 8 +0 + 2 +*D37 + 10 +38334.831670027648 + 20 +4323.3548996505697 + 30 +0.0 + 11 +37084.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +35834.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +38334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E64 + 8 +0 + 10 +39051.498336694312 + 20 +4919.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +39584.831670027648 + 21 +4919.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +E65 + 8 +0 + 2 +*D39 + 10 +40834.831670027641 + 20 +4323.3548996505697 + 30 +0.0 + 11 +39584.831670027648 + 21 +4535.8548996505697 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +38334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +40834.831670027641 + 24 +3391.885493772555 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E92 + 8 +0 + 10 +38184.831670027648 + 20 +5419.6279641725123 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +39584.831670027648 + 21 +5419.6279641725123 + 31 +0.0 + 0 +DIMENSION + 5 +E93 + 8 +0 + 2 +*D41 + 10 +6374.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 11 +5124.0720016190171 + 21 +1876.387067986979 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +3874.0720016190171 + 23 +732.41766210896446 + 33 +0.0 + 14 +6374.0720016190171 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E94 + 8 +0 + 10 +4007.405334952351 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +5124.0720016190171 + 21 +2161.6845510315902 + 31 +0.0 + 0 +TEXT + 5 +ED4 + 8 +0 + 10 +4624.0720016190171 + 20 +2702.1930384330772 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ + 7 +KANJI + 72 + 1 + 11 +5124.0720016190171 + 21 +2702.1930384330772 + 31 +0.0 + 0 +TEXT + 5 +F80 + 8 +0 + 10 +6507.405334952351 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +7624.0720016190162 + 21 +2161.6845510315902 + 31 +0.0 + 0 +DIMENSION + 5 +F81 + 8 +0 + 2 +*D43 + 10 +8874.0720016190171 + 20 +1663.887067986979 + 30 +0.0 + 11 +7624.0720016190162 + 21 +1876.387067986979 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +6374.0720016190171 + 23 +732.41766210896446 + 33 +0.0 + 14 +8874.0720016190171 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +FAD + 8 +0 + 10 +6224.0720016190171 + 20 +2702.1930384330772 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +7624.0720016190162 + 21 +2702.1930384330772 + 31 +0.0 + 0 +DIMENSION + 5 +114E + 8 +0 + 2 +*D45 + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +10124.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +8874.0720016190171 + 23 +732.41766210896446 + 33 +0.0 + 14 +11374.07200161901 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +INTEGRAL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +INTEGRAL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +114F + 8 +0 + 10 +9590.7386682856832 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +”gŒ` + 7 +KANJI + 72 + 1 + 11 +10124.07200161901 + 21 +2161.6845510315902 + 31 +0.0 + 0 +DIMENSION + 5 +117C + 8 +0 + 2 +*D47 + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +12624.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 0 + 1 +<> + 13 +11374.07200161901 + 23 +732.41766210896446 + 33 +0.0 + 14 +13874.07200161901 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +NONE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +NONE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +117D + 8 +0 + 10 +12124.07200161901 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +‚È‚µ + 7 +KANJI + 72 + 1 + 11 +12624.07200161901 + 21 +2161.6845510315902 + 31 +0.0 + 0 +DIMENSION + 5 +13F4 + 8 +0 + 2 +*D49 + 10 +16108.826121400591 + 20 +1663.887067986979 + 30 +0.0 + 11 +16871.326121400591 + 21 +1663.887067986979 + 31 +0.0 + 70 + 128 + 1 +<> + 13 +14608.826121400591 + 23 +732.41766210896446 + 33 +0.0 + 14 +16108.826121400591 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +DIMENSION + 5 +147B + 8 +0 + 2 +*D50 + 10 +19554.680964136489 + 20 +1663.887067986979 + 30 +0.0 + 11 +20467.180964136489 + 21 +1663.887067986979 + 31 +0.0 + 70 + 128 + 1 +<> + 13 +19054.680964136489 + 23 +732.41766210896446 + 33 +0.0 + 14 +19554.680964136489 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 279 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +TEXT + 5 +151F + 8 +0 + 10 +14219.42234363432 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +ŠOŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +15936.089010300981 + 21 +2161.6845510315902 + 31 +0.0 + 0 +TEXT + 5 +152B + 8 +0 + 10 +18038.395532791132 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +“àŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +19771.72886612446 + 21 +2161.6845510315902 + 31 +0.0 + 0 +TEXT + 5 +156C + 8 +0 + 10 +22164.30081507835 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +À•W¡–@ + 7 +KANJI + 72 + 1 + 11 +23297.634148411678 + 21 +2161.6845510315902 + 31 +0.0 + 0 +DIMENSION + 5 +1682 + 8 +0 + 2 +*D53 + 10 +38079.23269341683 + 20 +22516.996843459321 + 30 +0.0 + 11 +36161.205549448328 + 21 +20899.490081495082 + 31 +0.0 + 70 + 1 + 13 +33902.642865946531 + 23 +19622.518859064141 + 33 +0.0 + 14 +37438.176771879269 + 24 +23158.052764996879 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +168F + 8 +0 + 2 +*D54 + 10 +38005.667932426717 + 20 +23725.543925544331 + 30 +0.0 + 11 +37625.598037538948 + 21 +24406.134202436391 + 31 +0.0 + 70 + 1 + 13 +36377.51660009945 + 23 +24218.712936776701 + 33 +0.0 + 14 +37438.176771879269 + 24 +23158.052764996879 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AE + 8 +0 + 2 +*D55 + 10 +39061.617553885691 + 20 +26056.56410520013 + 30 +0.0 + 11 +36561.617553885691 + 21 +26269.06410520013 + 31 +0.0 + 70 + 1 + 13 +34061.617553885691 + 23 +26963.154083678131 + 33 +0.0 + 14 +39061.617553885691 + 24 +26963.154083678131 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AF + 8 +0 + 2 +*D56 + 10 +39864.171249658742 + 20 +26963.154083678131 + 30 +0.0 + 11 +39651.671249658728 + 21 +27713.154083678139 + 31 +0.0 + 70 + 1 + 13 +39061.617553885691 + 23 +28463.154083678131 + 33 +0.0 + 14 +39061.617553885691 + 24 +26963.154083678131 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +1710 + 8 +1 + 62 + 0 + 10 +33826.091686095053 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI + 0 +TEXT + 5 +1711 + 8 +1 + 62 + 0 + 10 +33472.538295501778 + 20 +20318.356640421549 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI + 0 +TEXT + 5 +1712 + 8 +1 + 62 + 0 + 10 +33826.091686095053 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI + 0 +TEXT + 5 +1840 + 8 +1 + 62 + 0 + 10 +34249.519309308489 + 20 +27759.315555862569 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI + 0 +TEXT + 5 +1841 + 8 +1 + 62 + 0 + 10 +34249.519309308489 + 20 +27759.315555862569 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI + 0 +TEXT + 5 +1842 + 8 +1 + 62 + 0 + 10 +34249.519309308489 + 20 +27259.315555862569 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI + 0 +TEXT + 5 +1843 + 8 +1 + 62 + 0 + 10 +34249.519309308489 + 20 +27259.315555862569 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI + 0 +TEXT + 5 +18CB + 8 +ƒtƒŠ[ƒY‰æ‘w + 10 +29297.880478439241 + 20 +2369.5383377866228 + 30 +0.0 + 40 +500.0 + 1 +ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI + 0 +TEXT + 5 +18CC + 8 +”ñ•\Ž¦‰æ‘w + 10 +29297.880478439241 + 20 +1869.5383377866231 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI + 0 +TEXT + 5 +18CD + 8 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w + 10 +29297.880478439241 + 20 +1369.5383377866231 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI + 0 +TEXT + 5 +18CF + 8 +ƒƒbƒN‚³‚ꂽ‰æ‘w + 10 +29297.880478439241 + 20 +869.53833778662374 + 30 +0.0 + 40 +500.0 + 1 +ƒƒbƒN‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI + 0 +TEXT + 5 +1ABE + 8 +ƒtƒŠ[ƒY‰æ‘w + 10 +18013.265046422741 + 20 +8351.5539229122223 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI + 0 +TEXT + 5 +1ABF + 8 +1 + 10 +15934.060659498469 + 20 +10232.278067765081 + 30 +0.0 + 40 +500.0 + 1 +(ƒ|ƒŠƒ‰ƒCƒ“) + 7 +KANJI + 72 + 1 + 11 +17684.060659498471 + 21 +10232.278067765081 + 31 +0.0 + 0 +POLYLINE + 5 +1AC1 + 8 +1 + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +2156 + 8 +1 + 10 +17355.64886932063 + 20 +9506.9274958169844 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2157 + 8 +1 + 10 +16857.009239960342 + 20 +9506.9274958169844 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2158 + 8 +1 + 10 +16477.092990699311 + 20 +9328.9989639147261 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2159 + 8 +1 + 10 +16239.645558808579 + 20 +8996.8658179876802 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215A + 8 +1 + 10 +16061.559816967459 + 20 +8617.2850797853025 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215B + 8 +1 + 10 +16120.921730914501 + 20 +8202.1185865066072 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215C + 8 +1 + 10 +16346.49700391324 + 20 +7869.9854405795331 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215D + 8 +1 + 10 +16643.306349751008 + 20 +7514.1283767750438 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215E + 8 +1 + 10 +17023.222375114648 + 20 +7348.0618038115208 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +215F + 8 +1 + 10 +17498.117462793511 + 20 +7265.0285781996499 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2160 + 8 +1 + 10 +17913.650636525359 + 20 +7312.4761704749262 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2161 + 8 +1 + 10 +18293.566661888992 + 20 +7478.5427434384774 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2162 + 8 +1 + 10 +18720.97221841025 + 20 +7644.6093164019976 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2163 + 8 +1 + 10 +19041.526553724219 + 20 +7905.5710739161304 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2164 + 8 +1 + 10 +19207.73968887853 + 20 +8273.2899749195494 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2165 + 8 +1 + 10 +19326.463516772601 + 20 +8664.732672060607 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2166 + 8 +1 + 10 +19362.08066514082 + 20 +9079.8991653393314 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2167 + 8 +1 + 10 +19112.760850460669 + 20 +9412.0323112663755 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2168 + 8 +1 + 10 +18768.461749567879 + 20 +9625.5464765052038 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2169 + 8 +1 + 10 +18341.056193046621 + 20 +9756.0274161321577 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +216A + 8 +1 + 10 +17913.650636525359 + 20 +9815.3368456063927 + 30 +0.0 + 42 +0.52056705 + 0 +SEQEND + 5 +216B + 8 +1 + 0 +TEXT + 5 +1AE3 + 8 +0 + 10 +20103.524695249042 + 20 +10232.278067765081 + 30 +0.0 + 40 +500.0 + 1 +ƒŠ[ƒWƒ‡ƒ“ + 7 +KANJI + 0 +INSERT + 5 +1AE7 + 8 +1 + 2 +*U65 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +TEXT + 5 +1B72 + 8 +1 + 10 +16584.060659498471 + 20 +10732.278067765081 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI + 72 + 1 + 11 +17684.060659498471 + 21 +10732.278067765081 + 31 +0.0 + 0 +DIMENSION + 5 +1DFD + 8 +1 + 2 +*D57 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +24827.837537397962 + 21 +2292.399842974457 + 31 +0.0 + 70 + 70 + 13 +24000.0 + 23 +703.36400868305645 + 33 +0.0 + 14 +24978.462537397962 + 24 +1666.7748429744529 + 34 +0.0 + 0 +DIMENSION + 5 +1E0E + 8 +1 + 2 +*D58 + 10 +26446.29486998995 + 20 +1653.6664119135239 + 30 +0.0 + 11 +27433.79486998995 + 21 +1653.6664119135239 + 31 +0.0 + 70 + 128 + 1 +<<>> + 13 +25446.29486998995 + 23 +732.41766210896446 + 33 +0.0 + 14 +26446.29486998995 + 24 +732.41766210896446 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +1E26 + 8 +1 + 10 +25446.29486998995 + 20 +732.41766210896446 + 30 +0.0 + 11 +26446.29486998995 + 21 +732.41766210896446 + 31 +0.0 + 0 +TEXT + 5 +1F2A + 8 +0 + 10 +25832.998858923918 + 20 +2161.6845510315902 + 30 +0.0 + 40 +500.0 + 1 +ã‘‚« + 7 +KANJI + 72 + 1 + 11 +26632.998858923918 + 21 +2161.6845510315902 + 31 +0.0 + 0 +TEXT + 5 +1F2B + 8 +0 + 10 +25516.33219225725 + 20 +2661.6845510315911 + 30 +0.0 + 40 +500.0 + 1 +¡–@’l‚Ì + 7 +KANJI + 72 + 1 + 11 +26632.998858923918 + 21 +2661.6845510315911 + 31 +0.0 + 0 +DIMENSION + 5 +1F54 + 8 +1 + 2 +*D59 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +22870.327402746399 + 21 +1811.026028986983 + 31 +0.0 + 70 + 6 + 13 +21761.907893255539 + 23 +700.0 + 33 +0.0 + 14 +22519.702402746399 + 24 +1660.4010289869841 + 34 +0.0 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test2_r13.dxf b/share/extensions/tests/data/io/test2_r13.dxf new file mode 100644 index 0000000..c873bca --- /dev/null +++ b/share/extensions/tests/data/io/test2_r13.dxf @@ -0,0 +1,38502 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1012 + 9 +$DWGCODEPAGE + 3 +dos932 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +-1.773829838086385 + 20 +-1.103180821155547 + 30 +-0.0000000000112498 + 9 +$EXTMAX + 10 +42052.11217275027 + 20 +29762.89687612323 + 30 +0.0000000000002956 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 1 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$DRAGMODE + 70 + 2 + 9 +$LTSCALE + 40 +100.0 + 9 +$OSMODE + 70 + 3071 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +500.0 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +KANJI + 9 +$CLAYER + 8 +1 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DELOBJ + 70 + 1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937007874016 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMFIT + 70 + 3 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMUNIT + 70 + 2 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$BLIPMODE + 70 + 0 + 9 +$CHAMFERA + 40 +10.0 + 9 +$CHAMFERB + 40 +10.0 + 9 +$CHAMFERC + 40 +20.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2451983.493486933 + 9 +$TDUPDATE + 40 +2451983.695180775 + 9 +$TDINDWG + 40 +0.1337622569 + 9 +$TDUSRTIMER + 40 +0.1337621412 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 3 + 9 +$PDSIZE + 40 +300.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$COORDS + 70 + 1 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$ATTDIA + 70 + 0 + 9 +$ATTREQ + 70 + 1 + 9 +$HANDLING + 70 +-16383 + 9 +$HANDSEED + 5 +2109 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 48 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.000000000000000E+20 + 20 +1.000000000000000E+20 + 30 +1.000000000000000E+20 + 9 +$PEXTMAX + 10 +-1.000000000000000E+20 + 20 +-1.000000000000000E+20 + 30 +-1.000000000000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 0 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$PICKSTYLE + 70 + 3 + 9 +$CMLSTYLE + 2 +STANDARD + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$SAVEIMAGES + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 32768 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 7 + 0 +VPORT + 5 +20BA +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +21025.16917145609 + 22 +14880.89684765104 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +30109.42365528417 + 41 +1.839147286821705 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HIDDEN + 70 + 0 + 3 +------------------------ + 72 + 65 + 73 + 2 + 40 +12.6 + 49 +8.4 + 74 + 0 + 49 +-4.2 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ + 72 + 65 + 73 + 2 + 40 +8.0 + 49 +6.0 + 74 + 0 + 49 +-2.0 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +--¥--¥--¥--¥--¥--¥--¥-- + 72 + 65 + 73 + 4 + 40 +50.5 + 49 +30.0 + 74 + 0 + 49 +-9.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-9.0 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +--¥¥--¥¥--¥¥--¥¥--¥¥-- + 72 + 65 + 73 + 6 + 40 +58.0 + 49 +30.0 + 74 + 0 + 49 +-9.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-5.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-9.0 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 8 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +1 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +29D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DEFPOINTS + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +E63 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +NORMAL + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18C8 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +”ñ•\Ž¦‰æ‘w + 70 + 0 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18C9 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18CA +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18CE +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ƒƒbƒN‚³‚ꂽ‰æ‘w + 70 + 4 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +300.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +300.0 + 3 +txt.shx + 4 + + 0 +STYLE + 5 +37 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +STYLE + 5 +38 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI2 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +MS Gothic.ttf + 4 + +1001 +ACAD +1000 +MS Gothic +1071 + 32817 + 0 +STYLE + 5 +446 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI4 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +@MS Gothic.ttf + 4 + +1001 +ACAD +1000 +@MS Gothic +1071 + 32817 + 0 +STYLE + 5 +67C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI3 + 70 + 4 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +133A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +CONTENTBLOCKICON + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +DIMSTYLE +105 +27 +102 +{ACAD_REACTORS +330 +2C5 +330 +2C7 +330 +329 +330 +373 +330 +37C +330 +755 +330 +801 +330 +83D +330 +866 +330 +89D +330 +8CA +330 +8F7 +330 +92F +330 +97D +330 +9C3 +330 +AAF +330 +AE8 +330 +B1D +330 +B55 +330 +B83 +330 +E65 +330 +E93 +330 +F81 +330 +114E +330 +117C +330 +13F4 +330 +147B +330 +2B7 +330 +2AA +330 +1682 +330 +168F +330 +16AE +330 +16AF +330 +1DFD +330 +1E0E +330 +1F54 +102 +} +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +39 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +STANDARD + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +0.18 + 42 +0.0625 + 43 +0.38 + 44 +0.18 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +0.18 +141 +0.09 +142 +0.0 +143 +25.4 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.09 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 61 + 0 +BLOCK_RECORD + 5 +1F +102 +{ACAD_XDICTIONARY +360 +12CA +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +102 +{ACAD_XDICTIONARY +360 +12CC +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +BLOCK_RECORD + 5 +2B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*U1 + 0 +BLOCK_RECORD + 5 +2AB +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 + 0 +BLOCK_RECORD + 5 +2B8 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 + 0 +BLOCK_RECORD + 5 +2C8 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 + 0 +BLOCK_RECORD + 5 +2D4 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 + 0 +BLOCK_RECORD + 5 +32A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 + 0 +BLOCK_RECORD + 5 +374 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 + 0 +BLOCK_RECORD + 5 +37D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 + 0 +BLOCK_RECORD + 5 +744 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NONAME +1001 +ACAD +1000 +DesignCenter Data +1002 +{ +1070 + 1 +1070 + 4 +1002 +} +1001 +CONTENTBLOCKICON +1071 + 0 +1004 +2800000020000000200000000100080000000000000400000000000000000000000000000000000000000000000080000080000000808000800000008000800080800000C0C0C000C0DCC000F0CAA6000020400000206000002080000020A0000020C0000020E00000400000004020000040400000406000004080000040A0 +1004 +000040C0000040E00000600000006020000060400000606000006080000060A0000060C0000060E00000800000008020000080400000806000008080000080A0000080C0000080E00000A0000000A0200000A0400000A0600000A0800000A0A00000A0C00000A0E00000C0000000C0200000C0400000C0600000C0800000C0 +1004 +A00000C0C00000C0E00000E0000000E0200000E0400000E0600000E0800000E0A00000E0C00000E0E00040000000400020004000400040006000400080004000A0004000C0004000E00040200000402020004020400040206000402080004020A0004020C0004020E000404000004040200040404000404060004040800040 +1004 +40A0004040C0004040E00040600000406020004060400040606000406080004060A0004060C0004060E00040800000408020004080400040806000408080004080A0004080C0004080E00040A0000040A0200040A0400040A0600040A0800040A0A00040A0C00040A0E00040C0000040C0200040C0400040C0600040C08000 +1004 +40C0A00040C0C00040C0E00040E0000040E0200040E0400040E0600040E0800040E0A00040E0C00040E0E00080000000800020008000400080006000800080008000A0008000C0008000E00080200000802020008020400080206000802080008020A0008020C0008020E00080400000804020008040400080406000804080 +1004 +008040A0008040C0008040E00080600000806020008060400080606000806080008060A0008060C0008060E00080800000808020008080400080806000808080008080A0008080C0008080E00080A0000080A0200080A0400080A0600080A0800080A0A00080A0C00080A0E00080C0000080C0200080C0400080C0600080C0 +1004 +800080C0A00080C0C00080C0E00080E0000080E0200080E0400080E0600080E0800080E0A00080E0C00080E0E000C0000000C0002000C0004000C0006000C0008000C000A000C000C000C000E000C0200000C0202000C0204000C0206000C0208000C020A000C020C000C020E000C0400000C0402000C0404000C0406000C0 +1004 +408000C040A000C040C000C040E000C0600000C0602000C0604000C0606000C0608000C060A000C060C000C060E000C0800000C0802000C0804000C0806000C0808000C080A000C080C000C080E000C0A00000C0A02000C0A04000C0A06000C0A08000C0A0A000C0A0C000C0A0E000C0C00000C0C02000C0C04000C0C06000 +1004 +C0C08000C0C0A000F0FBFF00A4A0A000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF000000000000000000000000000000000000000000000000000000000000FF +1004 +00FF0000000000000000000000000000000000000000000000000000000000FF00FF00000000000000000000000000000000000000000000000000000000FF000000FF000000000000000000000000000000000000000000000000000000FF000000FF0000000000000000000000000000000000000000000000000000FF00 +1004 +00000000FF000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000FF00000000000000FF00000000000000FF0000000000000000FF000000000000FF000000000000FF000000000000000000FF00000000000000FF00000000000000FF0000000000FF0000 +1004 +00000000000000FF000000000000FF0000000000000000FF00000000FF0000000000000000000000FF0000000000FF000000000000000000FF000000FF000000000000000000000000FF000000FF00000000000000000000FF0000FF00000000000000000000000000FF0000FF000000000000000000000000FF00FF000000 +1004 +0000000000000000000000FF00FF00000000000000000000000000FF00000000000000000000000000000000FF0000000000000000000000000000FF00000000000000000000000000000000FF00000000000000000000000000FF00FF0000000000000000000000000000FF00FF0000000000000000000000FF0000FF0000 +1004 +0000000000000000000000FF0000FF0000000000000000000000FF000000FF000000000000000000000000FF000000FF000000000000000000FF00000000FF0000000000000000000000FF0000000000FF0000000000000000FF0000000000FF000000000000000000FF000000000000FF00000000000000FF000000000000 +1004 +FF000000000000000000FF00000000000000FF000000000000FF00000000000000FF00000000000000FF0000000000000000FF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000FF0000000000FF00000000000000000000000000000000000000000000 +1004 +00000000FF000000FF000000000000000000000000000000000000000000000000000000FF000000FF00000000000000000000000000000000000000000000000000000000FF00FF0000000000000000000000000000000000000000000000000000000000FF00FF0000000000000000000000000000000000000000000000 +1004 +00000000000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 0 +BLOCK_RECORD + 5 +756 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 + 0 +BLOCK_RECORD + 5 +7CC +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDBLANK + 0 +BLOCK_RECORD + 5 +802 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D12 + 0 +BLOCK_RECORD + 5 +820 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSED + 0 +BLOCK_RECORD + 5 +83E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D14 + 0 +BLOCK_RECORD + 5 +867 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D15 + 0 +BLOCK_RECORD + 5 +87C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOT + 0 +BLOCK_RECORD + 5 +89E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D17 + 0 +BLOCK_RECORD + 5 +8B3 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ARCHTICK + 0 +BLOCK_RECORD + 5 +8CB +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D19 + 0 +BLOCK_RECORD + 5 +8E0 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OBLIQUE + 0 +BLOCK_RECORD + 5 +8F9 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D21 + 0 +BLOCK_RECORD + 5 +90E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN + 0 +BLOCK_RECORD + 5 +931 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D23 + 0 +BLOCK_RECORD + 5 +946 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ORIGIN + 0 +BLOCK_RECORD + 5 +97F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D25 + 0 +BLOCK_RECORD + 5 +994 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ORIGIN2 + 0 +BLOCK_RECORD + 5 +9C5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D27 + 0 +BLOCK_RECORD + 5 +9DA +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN90 + 0 +BLOCK_RECORD + 5 +AB1 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D29 + 0 +BLOCK_RECORD + 5 +AC6 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN30 + 0 +BLOCK_RECORD + 5 +AE9 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D31 + 0 +BLOCK_RECORD + 5 +AFE +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOTSMALL + 0 +BLOCK_RECORD + 5 +B1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D33 + 0 +BLOCK_RECORD + 5 +B34 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOTBLANK + 0 +BLOCK_RECORD + 5 +B57 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D35 + 0 +BLOCK_RECORD + 5 +B6C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_SMALL + 0 +BLOCK_RECORD + 5 +B84 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D37 + 0 +BLOCK_RECORD + 5 +B99 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_BOXBLANK + 0 +BLOCK_RECORD + 5 +E66 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D39 + 0 +BLOCK_RECORD + 5 +E7B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_BOXFILLED + 0 +BLOCK_RECORD + 5 +E95 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D41 + 0 +BLOCK_RECORD + 5 +EAA +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DATUMBLANK + 0 +BLOCK_RECORD + 5 +F82 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D43 + 0 +BLOCK_RECORD + 5 +F97 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DATUMFILLED + 0 +BLOCK_RECORD + 5 +1150 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D45 + 0 +BLOCK_RECORD + 5 +1165 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_INTEGRAL + 0 +BLOCK_RECORD + 5 +117E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D47 + 0 +BLOCK_RECORD + 5 +1193 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_NONE + 0 +BLOCK_RECORD + 5 +13F5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D49 + 0 +BLOCK_RECORD + 5 +147C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D50 + 0 +BLOCK_RECORD + 5 +156E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D51 + 0 +BLOCK_RECORD + 5 +15A5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D52 + 0 +BLOCK_RECORD + 5 +1683 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D53 + 0 +BLOCK_RECORD + 5 +1690 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D54 + 0 +BLOCK_RECORD + 5 +16B0 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D55 + 0 +BLOCK_RECORD + 5 +16BC +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D56 + 0 +BLOCK_RECORD + 5 +1DFE +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D57 + 0 +BLOCK_RECORD + 5 +1E0F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D58 + 0 +BLOCK_RECORD + 5 +1F55 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D59 + 0 +BLOCK_RECORD + 5 +20DC +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*X60 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +30 +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbBlockBegin + 2 +*U1 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U1 + 1 + + 0 +LINE + 5 +2C +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +0.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2D +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2E +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +42000.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +29700.0 + 31 +0.0 + 0 +LINE + 5 +2F +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +42000.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +29700.0 + 31 +0.0 + 0 +ENDBLK + 5 +31 +330 +2B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2B5 +330 +2AB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +171A +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32797.78852034247 + 20 +20727.37320466804 + 30 +0.0 + 11 +32470.00709536237 + 21 +21055.15462964686 + 31 +0.0 + 0 +LINE + 5 +171B +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36333.3224262752 + 20 +24262.90711060077 + 30 +0.0 + 11 +36005.54100128825 + 21 +24590.68853558645 + 31 +0.0 + 0 +LINE + 5 +171C +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32735.17213830715 + 20 +21143.54297729569 + 30 +0.0 + 11 +35917.15265364045 + 21 +24325.52349264132 + 31 +0.0 + 0 +SOLID + 5 +171D +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +32705.70935575765 + 20 +21173.00575984508 + 30 +0.0 + 11 +32764.63492085665 + 21 +21114.08019474631 + 31 +0.0 + 12 +32558.39544301086 + 22 +20966.76628199871 + 32 +0.0 + 13 +32558.39544301086 + 23 +20966.76628199871 + 33 +0.0 + 0 +SOLID + 5 +171E +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +35887.68987109095 + 20 +24354.9862751907 + 30 +0.0 + 11 +35946.61543618994 + 21 +24296.06071009194 + 31 +0.0 + 12 +36093.92934893674 + 22 +24502.3001879383 + 32 +0.0 + 13 +36093.92934893674 + 23 +24502.3001879383 + 33 +0.0 + 0 +MTEXT + 5 +171F +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +34175.90220497137 + 20 +22884.79342597035 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 + 11 +0.707106781185177 + 21 +0.7071067811879182 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1720 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +32841.98269416671 + 20 +20683.17903084396 + 30 +0.0 + 0 +POINT + 5 +1721 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36377.51660009944 + 20 +24218.7129367767 + 30 +0.0 + 0 +POINT + 5 +1722 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36093.92934893674 + 20 +24502.3001879383 + 30 +0.0 + 0 +ENDBLK + 5 +2B6 +330 +2AB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2C2 +330 +2B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +1723 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32797.78852034247 + 20 +20638.98485701989 + 30 +0.0 + 11 +32123.26971235923 + 21 +19964.46604903928 + 31 +0.0 + 0 +LINE + 5 +1724 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33858.4486921223 + 20 +19578.32468524007 + 30 +0.0 + 11 +33183.92988413701 + 21 +18903.8058772574 + 31 +0.0 + 0 +LINE + 5 +1725 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32388.43475530402 + 20 +19876.07770139045 + 30 +0.0 + 11 +33095.5415364892 + 21 +19168.97092020253 + 31 +0.0 + 0 +SOLID + 5 +1726 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +32417.89753785351 + 20 +19905.54048393983 + 30 +0.0 + 11 +32358.97197275452 + 21 +19846.61491884107 + 31 +0.0 + 12 +32211.65806000772 + 22 +20052.85439668743 + 32 +0.0 + 13 +32211.65806000772 + 23 +20052.85439668743 + 33 +0.0 + 0 +SOLID + 5 +1727 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33125.0043190387 + 20 +19198.43370275191 + 30 +0.0 + 11 +33066.0787539397 + 21 +19139.50813765314 + 31 +0.0 + 12 +33272.3182317855 + 22 +18992.19422490555 + 32 +0.0 + 13 +33272.3182317855 + 23 +18992.19422490555 + 33 +0.0 + 0 +MTEXT + 5 +1728 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32892.24833689904 + 20 +19672.78450179834 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.7071067811851766 + 21 +-0.7071067811879185 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1729 +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +32841.9826941667 + 20 +20683.17903084397 + 30 +0.0 + 0 +POINT + 5 +172A +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594654 + 20 +19622.51885906414 + 30 +0.0 + 0 +POINT + 5 +172B +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33272.3182317855 + 20 +18992.19422490555 + 30 +0.0 + 0 +ENDBLK + 5 +2C3 +330 +2B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2D2 +330 +2C8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +172C +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34061.61755388569 + 20 +28525.65408367813 + 30 +0.0 + 11 +34061.61755388569 + 21 +28989.20702038776 + 31 +0.0 + 0 +LINE + 5 +172D +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39061.61755388569 + 20 +28525.65408367813 + 30 +0.0 + 11 +39061.61755388569 + 21 +28989.20702038776 + 31 +0.0 + 0 +LINE + 5 +172E +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34311.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 11 +38811.61755388569 + 21 +28864.20702038776 + 31 +0.0 + 0 +SOLID + 5 +172F +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34311.61755388569 + 20 +28905.87368705443 + 30 +0.0 + 11 +34311.61755388569 + 21 +28822.54035372109 + 31 +0.0 + 12 +34061.61755388569 + 22 +28864.20702038776 + 32 +0.0 + 13 +34061.61755388569 + 23 +28864.20702038776 + 33 +0.0 + 0 +SOLID + 5 +1730 +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +38811.61755388569 + 20 +28905.87368705443 + 30 +0.0 + 11 +38811.61755388569 + 21 +28822.54035372109 + 31 +0.0 + 12 +39061.61755388569 + 22 +28864.20702038776 + 32 +0.0 + 13 +39061.61755388569 + 23 +28864.20702038776 + 33 +0.0 + 0 +MTEXT + 5 +1731 +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36561.61755388569 + 20 +29076.70702038776 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1732 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +1733 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +1734 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 0 +ENDBLK + 5 +2D3 +330 +2C8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2DE +330 +2D4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +1735 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33999.11755388569 + 20 +28463.15408367813 + 30 +0.0 + 11 +33045.20390755901 + 21 +28463.15408367813 + 31 +0.0 + 0 +LINE + 5 +1736 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33999.11755388569 + 20 +26963.15408367813 + 30 +0.0 + 11 +33045.20390755901 + 21 +26963.15408367813 + 31 +0.0 + 0 +LINE + 5 +1737 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33170.20390755901 + 20 +28213.15408367813 + 30 +0.0 + 11 +33170.20390755901 + 21 +27213.15408367813 + 31 +0.0 + 0 +SOLID + 5 +1738 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33128.53724089235 + 20 +28213.15408367813 + 30 +0.0 + 11 +33211.87057422568 + 21 +28213.15408367813 + 31 +0.0 + 12 +33170.20390755901 + 22 +28463.15408367813 + 32 +0.0 + 13 +33170.20390755901 + 23 +28463.15408367813 + 33 +0.0 + 0 +SOLID + 5 +1739 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33128.53724089235 + 20 +27213.15408367813 + 30 +0.0 + 11 +33211.87057422568 + 21 +27213.15408367813 + 31 +0.0 + 12 +33170.20390755901 + 22 +26963.15408367813 + 32 +0.0 + 13 +33170.20390755901 + 23 +26963.15408367813 + 33 +0.0 + 0 +MTEXT + 5 +173A +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32957.70390755901 + 20 +27713.15408367814 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +173B +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +173C +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +173D +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33170.20390755901 + 20 +26963.15408367813 + 30 +0.0 + 0 +ENDBLK + 5 +2DF +330 +2D4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +334 +330 +32A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +ARC + 5 +20C8 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbCircle + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 40 +3643.198465986115 +100 +AcDbArc + 50 +3.932466728467707 + 51 +41.06753327153231 + 0 +SOLID + 5 +20C9 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37578.90583846656 + 20 +19873.80126895147 + 30 +0.0 + 11 +37495.62157004181 + 21 +19870.94205972531 + 31 +0.0 + 12 +37545.84133193265 + 22 +19622.51885906415 + 32 +0.0 + 13 +37545.84133193265 + 23 +19622.51885906415 + 33 +0.0 + 0 +SOLID + 5 +20CA +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +36618.92420206274 + 20 +21987.47673559719 + 30 +0.0 + 11 +36679.83683926468 + 21 +22044.34584033384 + 31 +0.0 + 12 +36478.77320645374 + 22 +22198.64919957136 + 32 +0.0 + 13 +36478.77320645374 + 23 +22198.64919957136 + 33 +0.0 + 0 +MTEXT + 5 +20CB +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37464.84376220628 + 20 +21098.03078219252 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +45‹ + 11 +0.3826834323650894 + 21 +-0.9238795325112869 + 31 +0.0 + 0 +POINT + 5 +20CC +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37421.70235453924 + 20 +20565.44800714964 + 30 +0.0 + 0 +POINT + 5 +20CD +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187928 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +20CE +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 0 +POINT + 5 +20CF +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37726.65216029227 + 20 +19622.51885906415 + 30 +0.0 + 0 +POINT + 5 +20D0 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 0 +ENDBLK + 5 +335 +330 +32A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +37A +330 +374 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +1747 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +18916.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +17291.48750671567 + 31 +0.0 + 0 +LINE + 5 +1748 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +12791.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +12541.48750671567 + 31 +0.0 + 0 +MTEXT + 5 +1749 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +33759.21963608449 + 20 +18228.98750671567 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +\U+22054000 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +174A +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +17041.48750671567 + 31 +0.0 + 0 +SOLID + 5 +174B +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33930.05296941784 + 20 +12791.48750671567 + 30 +0.0 + 11 +34013.38630275116 + 21 +12791.48750671567 + 31 +0.0 + 12 +33971.7196360845 + 22 +13041.48750671567 + 32 +0.0 + 13 +33971.7196360845 + 23 +13041.48750671567 + 33 +0.0 + 0 +SOLID + 5 +174C +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33930.05296941784 + 20 +17291.48750671567 + 30 +0.0 + 11 +34013.38630275116 + 21 +17291.48750671567 + 31 +0.0 + 12 +33971.7196360845 + 22 +17041.48750671567 + 32 +0.0 + 13 +33971.7196360845 + 23 +17041.48750671567 + 33 +0.0 + 0 +POINT + 5 +174D +330 +374 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.7196360845 + 20 +17041.48750671567 + 30 +0.0 + 0 +POINT + 5 +174E +330 +374 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +37B +330 +374 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +384 +330 +37D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +174F +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37235.06246344516 + 20 +17131.03736041948 + 30 +0.0 + 11 +35866.56385842295 + 21 +16254.77451854369 + 31 +0.0 + 0 +MTEXT + 5 +1750 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36541.49406661355 + 20 +16939.26828335956 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +R2000 + 11 +0.8421529877059789 + 21 +0.539238671923568 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +1751 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 11 +35656.02561149646 + 21 +16119.9648505628 + 31 +0.0 + 0 +SOLID + 5 +1752 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +35844.09558042614 + 20 +16289.86422636477 + 30 +0.0 + 11 +35889.03213641976 + 21 +16219.6848107226 + 31 +0.0 + 12 +35656.02561149646 + 22 +16119.9648505628 + 32 +0.0 + 13 +35656.02561149646 + 23 +16119.9648505628 + 33 +0.0 + 0 +POINT + 5 +1753 +330 +37D +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35656.02561149646 + 20 +16119.9648505628 + 30 +0.0 + 0 +POINT + 5 +1754 +330 +37D +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +385 +330 +37D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +745 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NONAME + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NONAME + 1 + + 0 +LINE + 5 +747 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +5012.492533892546 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.619552814738 + 31 +0.0 + 0 +LINE + 5 +748 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +5012.492533892546 + 30 +0.0 + 11 +19339.43845972023 + 21 +5012.492533892547 + 31 +0.0 + 0 +LINE + 5 +749 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +24339.43845972023 + 21 +8260.087798084191 + 31 +0.0 + 0 +LINE + 5 +74A +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.960779162 + 31 +0.0 + 0 +LINE + 5 +74B +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.960779162 + 31 +0.0 + 0 +LINE + 5 +74C +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +5012.492533892547 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.619552814738 + 31 +0.0 + 0 +ENDBLK + 5 +746 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +760 +330 +756 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +LINE + 5 +1755 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +834.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +834.8316700276482 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1756 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1757 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +1084.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +3084.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +SOLID + 5 +1758 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +1084.831670027648 + 20 +4365.021566317238 + 30 +0.0 + 11 +1084.831670027648 + 21 +4281.688232983904 + 31 +0.0 + 12 +834.8316700276482 + 22 +4323.35489965057 + 32 +0.0 + 13 +834.8316700276482 + 23 +4323.35489965057 + 33 +0.0 + 0 +SOLID + 5 +1759 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +3084.831670027648 + 20 +4365.021566317238 + 30 +0.0 + 11 +3084.831670027648 + 21 +4281.688232983904 + 31 +0.0 + 12 +3334.831670027648 + 22 +4323.35489965057 + 32 +0.0 + 13 +3334.831670027648 + 23 +4323.35489965057 + 33 +0.0 + 0 +MTEXT + 5 +175A +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +2084.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +175B +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +834.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175C +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175D +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +761 +330 +756 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7D0 +330 +7CC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDBLANK + 1 + + 0 +LINE + 5 +7CD +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +7CE +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +7CF +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +ENDBLK + 5 +7D1 +330 +7CC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +80C +330 +802 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D12 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D12 + 1 + + 0 +LINE + 5 +175E +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +175F +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +5834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1760 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3584.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +5584.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1761 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSEDBLANK + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1762 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSEDBLANK + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1763 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +4584.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1764 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1765 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1766 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +80D +330 +802 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +825 +330 +820 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSED + 1 + + 0 +LINE + 5 +821 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +822 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +823 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +824 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +826 +330 +820 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +848 +330 +83E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D14 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D14 + 1 + + 0 +LINE + 5 +1767 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +5834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1768 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1769 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6084.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +8084.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +176A +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSED + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +176B +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSED + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +176C +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +7084.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +176D +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176E +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176F +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +849 +330 +83E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +871 +330 +867 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D15 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D15 + 1 + + 0 +LINE + 5 +1770 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1771 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1772 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8584.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +10584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1773 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOT + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1774 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOT + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1775 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +9584.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1776 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1777 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1778 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +872 +330 +867 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +87F +330 +87C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOT + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOT + 1 + + 0 +POLYLINE + 5 +87D +330 +87C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 40 +0.5 + 41 +0.5 + 0 +VERTEX + 5 +20EA +330 +87D +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +-0.25 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +VERTEX + 5 +20EB +330 +87D +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +0.25 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +SEQEND + 5 +20EC +330 +87D +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +LINE + 5 +87E +330 +87C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +880 +330 +87C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8A8 +330 +89E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D17 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D17 + 1 + + 0 +LINE + 5 +1779 +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +177A +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +177B +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +13334.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +177C +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ARCHTICK + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +177D +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ARCHTICK + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +177E +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +12084.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +177F +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1780 +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1781 +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +8A9 +330 +89E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8B5 +330 +8B3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ARCHTICK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ARCHTICK + 1 + + 0 +POLYLINE + 5 +8B4 +330 +8B3 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.15 + 41 +0.15 + 0 +VERTEX + 5 +20ED +330 +8B4 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 0 +VERTEX + 5 +20EE +330 +8B4 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +0.5 + 20 +0.5 + 30 +0.0 + 0 +SEQEND + 5 +20EF +330 +8B4 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +ENDBLK + 5 +8B6 +330 +8B3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8D5 +330 +8CB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D19 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D19 + 1 + + 0 +LINE + 5 +1782 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1783 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +15834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1784 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +15834.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1785 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OBLIQUE + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1786 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OBLIQUE + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1787 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +14584.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1788 +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1789 +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +178A +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +8D6 +330 +8CB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8E2 +330 +8E0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OBLIQUE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OBLIQUE + 1 + + 0 +LINE + 5 +8E1 +330 +8E0 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +ENDBLK + 5 +8E3 +330 +8E0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +903 +330 +8F9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D21 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D21 + 1 + + 0 +LINE + 5 +178B +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +15834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +178C +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +178D +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16084.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +18084.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +178E +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +178F +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1790 +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +17084.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1791 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1792 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1793 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +904 +330 +8F9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +912 +330 +90E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN + 1 + + 0 +LINE + 5 +90F +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +910 +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +-0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +911 +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +913 +330 +90E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +93B +330 +931 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D23 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D23 + 1 + + 0 +LINE + 5 +1794 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1795 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +20834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1796 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18584.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +20584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1797 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1798 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1799 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +19584.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +179A +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179B +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179C +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +93C +330 +931 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +949 +330 +946 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ORIGIN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN + 1 + + 0 +CIRCLE + 5 +947 +330 +946 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +948 +330 +946 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +94A +330 +946 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +989 +330 +97F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D25 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D25 + 1 + + 0 +LINE + 5 +179D +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +20834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +179E +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +179F +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +21084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +23084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17A0 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN2 + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17A1 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN2 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17A2 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +22084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17A3 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A4 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A5 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +98A +330 +97F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +998 +330 +994 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ORIGIN2 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN2 + 1 + + 0 +CIRCLE + 5 +995 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +CIRCLE + 5 +996 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +LINE + 5 +997 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +999 +330 +994 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9CF +330 +9C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D27 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D27 + 1 + + 0 +LINE + 5 +17A6 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17A7 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17A8 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23584.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +25584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17A9 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN90 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17AA +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN90 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17AB +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +24584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17AC +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AD +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AE +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +9D0 +330 +9C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9DE +330 +9DA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN90 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN90 + 1 + + 0 +LINE + 5 +9DB +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +9DC +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +9DD +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +9DF +330 +9DA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +ABB +330 +AB1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D29 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D29 + 1 + + 0 +LINE + 5 +17AF +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B0 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B1 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +26084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +28084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17B2 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17B3 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17B4 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +27084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17B5 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B6 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B7 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +ABC +330 +AB1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +ACA +330 +AC6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN30 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN30 + 1 + + 0 +LINE + 5 +AC7 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.26794919 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +AC8 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.26794919 + 31 +0.0 + 0 +LINE + 5 +AC9 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +ACB +330 +AC6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +AF3 +330 +AE9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D31 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D31 + 1 + + 0 +LINE + 5 +17B8 +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B9 +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +30834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17BA +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +30834.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17BB +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTSMALL + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17BC +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTSMALL + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17BD +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +29584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17BE +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17BF +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C0 +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +AF4 +330 +AE9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B00 +330 +AFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOTSMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTSMALL + 1 + + 0 +POLYLINE + 5 +AFF +330 +AFE +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 40 +0.5 + 41 +0.5 + 0 +VERTEX + 5 +20F0 +330 +AFF +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +-0.0625 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +VERTEX + 5 +20F1 +330 +AFF +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +0.0625 + 20 +0.0 + 30 +0.0 + 42 +1.0 + 0 +SEQEND + 5 +20F2 +330 +AFF +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 + 0 +ENDBLK + 5 +B01 +330 +AFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B29 +330 +B1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D33 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D33 + 1 + + 0 +LINE + 5 +17C1 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +30834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17C2 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17C3 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +31084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +33084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17C4 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTBLANK + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17C5 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTBLANK + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17C6 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17C7 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C8 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C9 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B2A +330 +B1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B37 +330 +B34 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOTBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTBLANK + 1 + + 0 +CIRCLE + 5 +B35 +330 +B34 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +B36 +330 +B34 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +B38 +330 +B34 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B61 +330 +B57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D35 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D35 + 1 + + 0 +LINE + 5 +17CA +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17CB +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +35834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17CC +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +35834.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17CD +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_SMALL + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17CE +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_SMALL + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17CF +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +34584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17D0 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D1 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D2 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B62 +330 +B57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B6E +330 +B6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_SMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_SMALL + 1 + + 0 +CIRCLE + 5 +B6D +330 +B6C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +ENDBLK + 5 +B6F +330 +B6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B8E +330 +B84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D37 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D37 + 1 + + 0 +LINE + 5 +17D3 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +35834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17D4 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17D5 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +38084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17D6 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXBLANK + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17D7 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXBLANK + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17D8 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17D9 +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DA +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DB +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B8F +330 +B84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B9F +330 +B99 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_BOXBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXBLANK + 1 + + 0 +LINE + 5 +B9A +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9B +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9C +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9D +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9E +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +BA0 +330 +B99 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E70 +330 +E66 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D39 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D39 + 1 + + 0 +LINE + 5 +17DC +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17DD +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +40834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +40834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17DE +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38584.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +40584.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17DF +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXFILLED + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17E0 +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXFILLED + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17E1 +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +39584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17E2 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E3 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +40834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E4 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +E71 +330 +E66 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E7E +330 +E7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_BOXFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXFILLED + 1 + + 0 +SOLID + 5 +E7C +330 +E7B +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbTrace + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 12 +-0.5 + 22 +-0.5 + 32 +0.0 + 13 +0.5 + 23 +-0.5 + 33 +0.0 + 0 +LINE + 5 +E7D +330 +E7B +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +E7F +330 +E7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E9F +330 +E95 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D41 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D41 + 1 + + 0 +LINE + 5 +1DBB +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +3874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBC +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6374.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +6374.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBD +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +4124.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +6124.072001619017 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DBE +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMBLANK + 10 +3874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DBF +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMBLANK + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DC0 +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +5124.072001619017 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DC1 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC2 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC3 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +EA0 +330 +E95 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +EAE +330 +EAA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DATUMBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMBLANK + 1 + + 0 +LINE + 5 +EAB +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +EAC +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +-0.5773502700000001 + 31 +0.0 + 0 +LINE + 5 +EAD +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +-0.5773502700000001 + 30 +0.0 + 11 +0.0 + 21 +0.5773502700000001 + 31 +0.0 + 0 +ENDBLK + 5 +EAF +330 +EAA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +F8C +330 +F82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D43 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D43 + 1 + + 0 +LINE + 5 +1DD4 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6374.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +6374.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD5 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +8874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD6 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6624.072001619016 + 20 +1663.887067986979 + 30 +0.0 + 11 +8624.072001619017 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DD7 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMFILLED + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DD8 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMFILLED + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DD9 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +7624.072001619016 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DDA +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DDB +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DDC +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +F8D +330 +F82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +F99 +330 +F97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DATUMFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMFILLED + 1 + + 0 +SOLID + 5 +F98 +330 +F97 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbTrace + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 12 +0.0 + 22 +-0.5773502700000001 + 32 +0.0 + 13 +0.0 + 23 +-0.5773502700000001 + 33 +0.0 + 0 +ENDBLK + 5 +F9A +330 +F97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +115A +330 +1150 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D45 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D45 + 1 + + 0 +LINE + 5 +1DCB +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +8874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCC +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCD +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +11374.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DCE +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_INTEGRAL + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DCF +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_INTEGRAL + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DD0 +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +10124.07200161901 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DD1 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DD2 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DD3 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +115B +330 +1150 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1168 +330 +1165 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_INTEGRAL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_INTEGRAL + 1 + + 0 +ARC + 5 +1166 +330 +1165 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.44488802 + 20 +-0.09133463 + 30 +0.0 + 40 +0.4541666700000001 +100 +AcDbArc + 50 +101.9999999980395 + 51 +167.9999999799193 + 0 +ARC + 5 +1167 +330 +1165 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +-0.44488802 + 20 +0.09133463 + 30 +0.0 + 40 +0.4541666700000001 +100 +AcDbArc + 50 +282.0000000215427 + 51 +348.0000000034225 + 0 +ENDBLK + 5 +1169 +330 +1165 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1188 +330 +117E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D47 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D47 + 1 + + 0 +LINE + 5 +1DC4 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC5 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13874.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +13874.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC6 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +13874.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +MTEXT + 5 +1DC7 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +12624.07200161901 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DC8 +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC9 +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13874.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DCA +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1189 +330 +117E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1194 +330 +1193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_NONE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_NONE + 1 + + 0 +ENDBLK + 5 +1195 +330 +1193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +13FD +330 +13F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D49 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D49 + 1 + + 0 +LINE + 5 +1DDD +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +14608.82612140059 + 20 +794.9176621089645 + 30 +0.0 + 11 +14608.82612140059 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDE +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16108.82612140059 + 20 +794.9176621089645 + 30 +0.0 + 11 +16108.82612140059 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDF +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +14858.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +15858.82612140059 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DE0 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +17383.82612140059 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DE1 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +14608.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DE2 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DE3 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +16871.32612140059 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DE4 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +14608.82612140059 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DE5 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +16108.82612140059 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DE6 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +13FE +330 +13F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1487 +330 +147C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D50 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D50 + 1 + + 0 +LINE + 5 +1DB0 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19054.68096413649 + 20 +794.9176621089645 + 30 +0.0 + 11 +19054.68096413649 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB1 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19554.68096413649 + 20 +794.9176621089645 + 30 +0.0 + 11 +19554.68096413649 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB2 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18804.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +18554.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB3 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19804.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +20879.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB4 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19054.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +19554.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DB5 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +19054.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +INSERT + 5 +1DB6 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +MTEXT + 5 +1DB7 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +20467.18096413649 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DB8 +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19054.68096413649 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DB9 +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19554.68096413649 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DBA +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1488 +330 +147C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1576 +330 +156E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D51 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D51 + 1 + + 0 +LINE + 5 +1F3A +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +21971.23629970006 + 20 +1700.0 + 30 +0.0 + 11 +22602.86068322082 + 21 +1700.0 + 31 +0.0 + 0 +LINE + 5 +1F3B +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +22602.86068322082 + 20 +1700.0 + 30 +0.0 + 11 +22607.86068322081 + 21 +731.2827575619594 + 31 +0.0 + 0 +LINE + 5 +1F3C +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +22607.86068322081 + 20 +731.2827575619594 + 30 +0.0 + 11 +24313.48568322081 + 21 +731.2827575619594 + 31 +0.0 + 0 +MTEXT + 5 +1F3D +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +23463.48568322081 + 20 +881.9077575619594 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1638.24 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F3E +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +21970.61129970006 + 20 +1700.0 + 30 +0.0 + 0 +POINT + 5 +1F3F +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +22612.86068322081 + 20 +731.2827575619594 + 30 +0.0 + 0 +POINT + 5 +1F40 +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +51.46025101292298 + 20 +61.75531173110096 + 30 +0.0 + 0 +ENDBLK + 5 +1577 +330 +156E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +15AB +330 +15A5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D52 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D52 + 1 + + 0 +LINE + 5 +1DF5 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23925.7403567024 + 20 +682.5615222854612 + 30 +0.0 + 11 +23925.7403567024 + 21 +1624.772405628799 + 31 +0.0 + 0 +LINE + 5 +1DF6 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23925.7403567024 + 20 +1624.772405628799 + 30 +0.0 + 11 +25157.97004022932 + 21 +1629.772405628798 + 31 +0.0 + 0 +LINE + 5 +1DF7 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25157.97004022932 + 20 +1629.772405628798 + 30 +0.0 + 11 +25157.97004022932 + 21 +3735.397405628798 + 31 +0.0 + 0 +MTEXT + 5 +1DF8 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +25007.34504022932 + 20 +2685.397405628803 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +26524.29 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DF9 +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23925.7403567024 + 20 +681.9365222854612 + 30 +0.0 + 0 +POINT + 5 +1DFA +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25157.97004022932 + 20 +1634.772405628799 + 30 +0.0 + 0 +POINT + 5 +1DFB +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +-2598.548049632634 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +15AC +330 +15A5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +168D +330 +1683 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D53 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D53 + 1 + + 0 +LINE + 5 +181C +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33946.83703977069 + 20 +19578.32468523999 + 30 +0.0 + 11 +34632.08713513241 + 21 +18893.07458987827 + 31 +0.0 + 0 +LINE + 5 +181D +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37482.37094570343 + 20 +23113.85859117272 + 30 +0.0 + 11 +38167.62104106515 + 21 +22428.608495811 + 31 +0.0 + 0 +LINE + 5 +181E +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34720.47548278073 + 20 +19158.23963282322 + 30 +0.0 + 11 +37902.45599812019 + 21 +22340.22014816269 + 31 +0.0 + 0 +SOLID + 5 +181F +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34691.01270023129 + 20 +19187.70241537266 + 30 +0.0 + 11 +34749.93826533017 + 21 +19128.77685027378 + 31 +0.0 + 12 +34543.6987874841 + 22 +18981.46293752658 + 32 +0.0 + 13 +34543.6987874841 + 23 +18981.46293752658 + 33 +0.0 + 0 +SOLID + 5 +1820 +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37872.99321557076 + 20 +22369.68293071213 + 30 +0.0 + 11 +37931.91878066964 + 21 +22310.75736561325 + 31 +0.0 + 12 +38079.23269341683 + 22 +22516.99684345932 + 32 +0.0 + 13 +38079.23269341683 + 23 +22516.99684345932 + 33 +0.0 + 0 +MTEXT + 5 +1821 +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36161.20554944833 + 20 +20899.49008149508 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 + 11 +0.7071067811865476 + 21 +0.7071067811865475 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1822 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906415 + 30 +0.0 + 0 +POINT + 5 +1823 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187927 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +1824 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38079.23269341683 + 20 +22516.99684345932 + 30 +0.0 + 0 +ENDBLK + 5 +168E +330 +1683 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +169A +330 +1690 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D54 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D54 + 1 + + 0 +LINE + 5 +1825 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36421.71077392361 + 20 +24262.90711060086 + 30 +0.0 + 11 +37033.39610829522 + 21 +24874.59244497247 + 31 +0.0 + 0 +LINE + 5 +1826 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37482.37094570343 + 20 +23202.24693882104 + 30 +0.0 + 11 +38094.05628007504 + 21 +23813.93227319265 + 31 +0.0 + 0 +LINE + 5 +1827 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37121.78445594354 + 20 +24609.42740202752 + 30 +0.0 + 11 +37828.89123713009 + 21 +23902.32062084097 + 31 +0.0 + 0 +SOLID + 5 +1828 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37151.24723849298 + 20 +24638.89018457695 + 30 +0.0 + 11 +37092.3216733941 + 21 +24579.96461947808 + 31 +0.0 + 12 +36945.0077606469 + 22 +24786.20409732415 + 32 +0.0 + 13 +36945.0077606469 + 23 +24786.20409732415 + 33 +0.0 + 0 +SOLID + 5 +1829 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37858.35401967953 + 20 +23931.7834033904 + 30 +0.0 + 11 +37799.42845458065 + 21 +23872.85783829153 + 31 +0.0 + 12 +38005.66793242672 + 22 +23725.54392554433 + 32 +0.0 + 13 +38005.66793242672 + 23 +23725.54392554433 + 33 +0.0 + 0 +MTEXT + 5 +182A +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37625.59803753895 + 20 +24406.13420243639 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.7071067811865476 + 21 +-0.7071067811865475 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +182B +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36377.51660009945 + 20 +24218.7129367767 + 30 +0.0 + 0 +POINT + 5 +182C +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187927 + 20 +23158.05276499688 + 30 +0.0 + 0 +POINT + 5 +182D +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38005.66793242672 + 20 +23725.54392554433 + 30 +0.0 + 0 +ENDBLK + 5 +169B +330 +1690 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +16BA +330 +16B0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D55 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D55 + 1 + + 0 +LINE + 5 +182E +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34061.61755388569 + 20 +26900.65408367813 + 30 +0.0 + 11 +34061.61755388569 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +182F +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39061.61755388569 + 20 +26900.65408367813 + 30 +0.0 + 11 +39061.61755388569 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +1830 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34311.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 11 +38811.61755388569 + 21 +26056.56410520013 + 31 +0.0 + 0 +SOLID + 5 +1831 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34311.61755388569 + 20 +26098.23077186679 + 30 +0.0 + 11 +34311.61755388569 + 21 +26014.89743853346 + 31 +0.0 + 12 +34061.61755388569 + 22 +26056.56410520013 + 32 +0.0 + 13 +34061.61755388569 + 23 +26056.56410520013 + 33 +0.0 + 0 +SOLID + 5 +1832 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +38811.61755388569 + 20 +26098.23077186679 + 30 +0.0 + 11 +38811.61755388569 + 21 +26014.89743853346 + 31 +0.0 + 12 +39061.61755388569 + 22 +26056.56410520013 + 32 +0.0 + 13 +39061.61755388569 + 23 +26056.56410520013 + 33 +0.0 + 0 +MTEXT + 5 +1833 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36561.61755388569 + 20 +26269.06410520013 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1834 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +1835 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +1836 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 0 +ENDBLK + 5 +16BB +330 +16B0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +16C6 +330 +16BC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D56 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D56 + 1 + + 0 +LINE + 5 +1837 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39124.11755388569 + 20 +28463.15408367813 + 30 +0.0 + 11 +39989.17124965874 + 21 +28463.15408367813 + 31 +0.0 + 0 +LINE + 5 +1838 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39124.11755388569 + 20 +26963.15408367813 + 30 +0.0 + 11 +39989.17124965874 + 21 +26963.15408367813 + 31 +0.0 + 0 +LINE + 5 +1839 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39864.17124965874 + 20 +28213.15408367813 + 30 +0.0 + 11 +39864.17124965874 + 21 +27213.15408367813 + 31 +0.0 + 0 +SOLID + 5 +183A +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +39822.50458299207 + 20 +28213.15408367813 + 30 +0.0 + 11 +39905.8379163254 + 21 +28213.15408367813 + 31 +0.0 + 12 +39864.17124965874 + 22 +28463.15408367813 + 32 +0.0 + 13 +39864.17124965874 + 23 +28463.15408367813 + 33 +0.0 + 0 +SOLID + 5 +183B +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +39822.50458299207 + 20 +27213.15408367813 + 30 +0.0 + 11 +39905.8379163254 + 21 +27213.15408367813 + 31 +0.0 + 12 +39864.17124965874 + 22 +26963.15408367813 + 32 +0.0 + 13 +39864.17124965874 + 23 +26963.15408367813 + 33 +0.0 + 0 +MTEXT + 5 +183C +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +39651.67124965873 + 20 +27713.15408367814 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +183D +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +183E +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +183F +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39864.17124965874 + 20 +26963.15408367813 + 30 +0.0 + 0 +ENDBLK + 5 +16C7 +330 +16BC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E04 +330 +1DFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D57 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D57 + 1 + + 0 +LINE + 5 +1E06 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24000.0 + 20 +703.9890086830564 + 30 +0.0 + 11 +24000.0 + 21 +1656.774842974453 + 31 +0.0 + 0 +LINE + 5 +1E07 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24000.0 + 20 +1656.774842974453 + 30 +0.0 + 11 +24978.46253739796 + 21 +1661.774842974453 + 31 +0.0 + 0 +LINE + 5 +1E08 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24978.46253739796 + 20 +1661.774842974453 + 30 +0.0 + 11 +24978.46253739796 + 21 +2917.399842974453 + 31 +0.0 + 0 +MTEXT + 5 +1E09 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +24827.83753739796 + 20 +2292.399842974457 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +24000 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1E0A +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +24000.0 + 20 +703.3640086830565 + 30 +0.0 + 0 +POINT + 5 +1E0B +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +24978.46253739796 + 20 +1666.774842974453 + 30 +0.0 + 0 +POINT + 5 +1E0C +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1E05 +330 +1DFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E1A +330 +1E0F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D58 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D58 + 1 + + 0 +LINE + 5 +1F20 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +25446.29486998995 + 20 +794.9176621089645 + 30 +0.0 + 11 +25446.29486998995 + 21 +1778.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F21 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +26446.29486998995 + 20 +794.9176621089645 + 30 +0.0 + 11 +26446.29486998995 + 21 +1778.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F22 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +25696.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +26196.29486998996 + 21 +1653.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F23 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +28171.29486998995 + 21 +1653.666411913524 + 31 +0.0 + 0 +SOLID + 5 +1F24 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbTrace + 10 +25696.29486998995 + 20 +1695.33307858019 + 30 +0.0 + 11 +25696.29486998995 + 21 +1611.999745246857 + 31 +0.0 + 12 +25446.29486998995 + 22 +1653.666411913524 + 32 +0.0 + 13 +25446.29486998995 + 23 +1653.666411913524 + 33 +0.0 + 0 +SOLID + 5 +1F25 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbTrace + 10 +26196.29486998996 + 20 +1695.33307858019 + 30 +0.0 + 11 +26196.29486998996 + 21 +1611.999745246857 + 31 +0.0 + 12 +26446.29486998995 + 22 +1653.666411913524 + 32 +0.0 + 13 +26446.29486998995 + 23 +1653.666411913524 + 33 +0.0 + 0 +MTEXT + 5 +1F26 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +27433.79486998995 + 20 +1866.166411913523 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +<1000> +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F27 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1F28 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +26446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1F29 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 0 +ENDBLK + 5 +1E1B +330 +1E0F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1F5B +330 +1F55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D59 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D59 + 1 + + 0 +LINE + 5 +1F64 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +21762.53289325554 + 20 +700.0 + 30 +0.0 + 11 +22509.7024027464 + 21 +700.0 + 31 +0.0 + 0 +LINE + 5 +1F65 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +22509.7024027464 + 20 +700.0 + 30 +0.0 + 11 +22514.7024027464 + 21 +1660.401028986984 + 31 +0.0 + 0 +LINE + 5 +1F66 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +22514.7024027464 + 20 +1660.401028986984 + 30 +0.0 + 11 +23220.3274027464 + 21 +1660.401028986984 + 31 +0.0 + 0 +MTEXT + 5 +1F67 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +22870.3274027464 + 20 +1811.026028986983 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +700 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F68 +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +21761.90789325554 + 20 +700.0 + 30 +0.0 + 0 +POINT + 5 +1F69 +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +22519.7024027464 + 20 +1660.401028986984 + 30 +0.0 + 0 +POINT + 5 +1F6A +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1F5C +330 +1F55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +20E7 +330 +20DC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*X60 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*X60 + 1 + + 0 +LINE + 5 +20DD +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +40081.71734709665 + 20 +13879.05486911342 + 30 +0.0 + 11 +40498.45357200498 + 21 +14295.79109402177 + 31 +0.0 + 0 +LINE + 5 +20DE +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39632.70454104319 + 20 +13879.05486911342 + 30 +0.0 + 11 +40498.45357200499 + 21 +14744.80390007522 + 31 +0.0 + 0 +LINE + 5 +20DF +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39183.69173498973 + 20 +13879.05486911342 + 30 +0.0 + 11 +40498.45357200498 + 21 +15193.81670612868 + 31 +0.0 + 0 +LINE + 5 +20E0 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38734.67892893628 + 20 +13879.05486911342 + 30 +0.0 + 11 +40498.45357200498 + 21 +15642.82951218213 + 31 +0.0 + 0 +LINE + 5 +20E1 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38285.66612288281 + 20 +13879.05486911342 + 30 +0.0 + 11 +40285.66612288281 + 21 +15879.05486911342 + 31 +0.0 + 0 +LINE + 5 +20E2 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37836.65331682936 + 20 +13879.05486911342 + 30 +0.0 + 11 +39836.65331682936 + 21 +15879.05486911342 + 31 +0.0 + 0 +LINE + 5 +20E3 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37649.98492586595 + 20 +14141.39928420347 + 30 +0.0 + 11 +39387.6405107759 + 21 +15879.05486911342 + 31 +0.0 + 0 +LINE + 5 +20E4 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37649.98492586595 + 20 +14590.41209025692 + 30 +0.0 + 11 +38938.62770472244 + 21 +15879.05486911342 + 31 +0.0 + 0 +LINE + 5 +20E5 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37649.98492586595 + 20 +15039.42489631038 + 30 +0.0 + 11 +38489.61489866899 + 21 +15879.05486911342 + 31 +0.0 + 0 +LINE + 5 +20E6 +330 +20DC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37649.98492586595 + 20 +15488.43770236384 + 30 +0.0 + 11 +38040.60209261553 + 21 +15879.05486911342 + 31 +0.0 + 0 +ENDBLK + 5 +20E8 +330 +20DC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +POLYLINE + 5 +16E +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +20BE +330 +16E +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +32841.98269416671 + 20 +20683.17903084397 + 30 +0.0 + 0 +VERTEX + 5 +20BF +330 +16E +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +36377.51660009945 + 20 +24218.7129367767 + 30 +0.0 + 0 +VERTEX + 5 +20C0 +330 +16E +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +37438.17677187927 + 20 +23158.05276499688 + 30 +0.0 + 0 +VERTEX + 5 +20C1 +330 +16E +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 0 +SEQEND + 5 +20C2 +330 +16E +100 +AcDbEntity + 8 +1 + 62 + 0 + 0 +INSERT + 5 +170 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbBlockReference + 2 +*U1 + 10 +51.46025101292298 + 20 +61.75531173110096 + 30 +0.0 + 0 +TEXT + 5 +171 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbText + 10 +41.46025101292298 + 20 +51.75531173110096 + 30 +0.0 + 40 +1000.0 + 1 +A3 1/100 + 41 +0.5200000000000001 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +172 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +8032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +DOT + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +173 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +12032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +12032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +174 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(CONTINUOUS) + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +175 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS +100 +AcDbLine + 10 +834.8316700276482 + 20 +11032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +11032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +176 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +CONTINUOUS + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +177 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +DASHDOT + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +178 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DASHDOT +100 +AcDbLine + 10 +834.8316700276482 + 20 +10032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +179 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DIVIDE +100 +AcDbLine + 10 +834.8316700276482 + 20 +9032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +9032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +17A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +9032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +DIVIDE + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +17B +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DOT +100 +AcDbLine + 10 +834.8316700276482 + 20 +8032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +8032.868615568695 + 31 +0.0 + 0 +LINE + 5 +17C +330 +1F +100 +AcDbEntity + 8 +1 + 6 +HIDDEN +100 +AcDbLine + 10 +834.8316700276482 + 20 +7032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +7032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +17D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +7032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +HIDDEN + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +17E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15709.47494670215 + 20 +28715.17555215312 + 30 +0.0 + 11 +15709.47494670215 + 21 +24182.26996797447 + 31 +0.0 + 0 +LINE + 5 +17F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 11 +17116.41234094919 + 21 +24182.26996797447 + 31 +0.0 + 0 +MTEXT + 5 +180 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 41 +4532.9056 + 71 + 1 + 72 + 1 + 1 +‚Qs‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI4 + 11 +-0.0000000000000002 + 21 +-1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +181 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 11 +15709.47494670215 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +182 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15709.47494670215 + 20 +24182.26996797447 + 30 +0.0 + 11 +17116.41234094919 + 21 +24182.26996797447 + 31 +0.0 + 0 +TEXT + 5 +183 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263391 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(White/Black) + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +184 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 1 +100 +AcDbLine + 10 +8432.910636263391 + 20 +11032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +11032.86861556869 + 31 +0.0 + 0 +LINE + 5 +185 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263391 + 20 +12032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +12032.86861556869 + 31 +0.0 + 0 +LINE + 5 +186 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 2 +100 +AcDbLine + 10 +8432.910636263391 + 20 +10032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +187 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 3 +100 +AcDbLine + 10 +8432.910636263391 + 20 +9032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +9032.868615568695 + 31 +0.0 + 0 +LINE + 5 +188 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 4 +100 +AcDbLine + 10 +8432.910636263391 + 20 +8032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +8032.868615568695 + 31 +0.0 + 0 +LINE + 5 +189 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 113 +100 +AcDbLine + 10 +8432.910636263391 + 20 +7032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +7032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +18A +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 2 +100 +AcDbText + 10 +8432.910636263391 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Yellow + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18B +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 113 +100 +AcDbText + 10 +8432.910636263391 + 20 +7032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +ƒpƒŒƒbƒg113 + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18C +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 4 +100 +AcDbText + 10 +8432.910636263391 + 20 +8032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +Cyan + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18D +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 3 +100 +AcDbText + 10 +8432.910636263391 + 20 +9032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +Green + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18E +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 1 +100 +AcDbText + 10 +8432.910636263391 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Red + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +26769.84838325862 + 21 +25791.31768413283 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +190 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +18739.86399912308 + 20 +23517.2060090059 + 30 +0.0 + 11 +18739.86399912308 + 21 +28715.17555215312 + 31 +0.0 + 0 +TEXT + 5 +191 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +192 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.2060090059 + 31 +0.0 + 0 +LINE + 5 +193 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +194 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19269.84838325863 + 21 +23517.2100800719 + 31 +0.0 + 0 +TEXT + 5 +195 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +19178.47782488299 + 21 +23517.20600900591 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +196 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 11 +20269.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +197 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +20769.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +TEXT + 5 +198 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +20269.84838325863 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +20178.47782488299 + 21 +25791.31768413282 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +199 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +19A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +19B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 50 +270.0 + 7 +KANJI4 + 11 +21178.47782488299 + 21 +28715.17555215312 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +19C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +19D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +TEXT + 5 +19E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +22269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +22519.84838325863 + 21 +22867.45981611252 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +19F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1A0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +TEXT + 5 +1A1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +23519.84838325862 + 21 +26116.19078057952 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +1A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24269.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +TEXT + 5 +1A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 50 +270.0 + 7 +KANJI4 + 11 +24519.84838325862 + 21 +28715.17555215313 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +1A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +25269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1A6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +25769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +TEXT + 5 +1A7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +25769.84838325863 + 21 +23517.20600900593 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +1A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1A9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +1AA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 11 +18739.86399912307 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1AF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +25769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +1B2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +1B3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1B4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +27415.68235215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +27415.68235215312 + 31 +0.0 + 0 +LINE + 5 +1B5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +26765.93575215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1B6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +26116.18915215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +26116.18915215312 + 31 +0.0 + 0 +LINE + 5 +1B7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +25466.44255215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1B8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +27415.68235215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +27415.68235215312 + 31 +0.0 + 0 +LINE + 5 +1B9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28065.42895215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1BA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +26765.93575215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +27415.68235215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1BC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +26765.93575215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +26116.18915215313 + 30 +0.0 + 11 +20769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +25466.44255215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +21769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +21769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +19269.84838325863 + 21 +24816.69839479271 + 31 +0.0 + 0 +LINE + 5 +1C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +19769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1C4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325864 + 20 +24166.95423743231 + 30 +0.0 + 11 +19269.84838325864 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +19769.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325864 + 20 +23517.2100800719 + 30 +0.0 + 11 +19269.84838325864 + 21 +23517.2100800719 + 31 +0.0 + 0 +LINE + 5 +1C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +23517.2100800719 + 30 +0.0 + 11 +19769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1C9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +20769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1CA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +20769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1CB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +20269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1CC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +20269.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1CD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +20769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1CE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +20269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1CF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +21769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +21769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +21269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1D2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +21269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1D3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +21769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1D4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +21269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1D5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +22867.4659227115 + 30 +0.0 + 11 +20769.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +1D6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325864 + 20 +22867.4659227115 + 30 +0.0 + 11 +20269.84838325864 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +1D7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1D8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1D9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28065.42895215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1DC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1DD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28065.42895215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1DF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +22769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1E1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1E2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +25466.44255215312 + 30 +0.0 + 11 +23769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1E3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1E4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1E5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1E6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +26765.93575215314 + 30 +0.0 + 11 +25769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +1E7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +27415.68235215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28065.42895215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1E9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +1EA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +1EB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +1EC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +25466.44255215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1ED +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +26116.18915215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1EE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +1EF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +26769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1F0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +22867.46592271151 + 30 +0.0 + 11 +24769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +24769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +24769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1F3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +24769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +23769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1F5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +23769.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1F6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +23769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +22769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1F8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +22769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +22269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +22269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +23269.84838325863 + 21 +24816.69839479271 + 31 +0.0 + 0 +LINE + 5 +1FC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325864 + 20 +24166.95423743231 + 30 +0.0 + 11 +23269.84838325864 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1FD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +22769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +22269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +23269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +200 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +24269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +201 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +24269.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +202 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +24269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +203 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +22769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +204 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +22269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +205 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +24269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +206 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +25769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +207 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +25769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +208 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +25769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +209 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +25269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +20A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +25269.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +20B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +25269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +20C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +26269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +20D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +26769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +20E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +26269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +20F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +26769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +210 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +26269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +211 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +26769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +212 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +26269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +213 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +26769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +214 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +30269.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +215 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +30769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +TEXT + 5 +216 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +30269.84838325864 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 50 +270.0 + 41 +0.9000000000000005 + 7 +KANJI4 + 72 + 5 + 11 +30269.84838325864 + 21 +22867.45981611253 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +217 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +218 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +219 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 50 +270.0 + 7 +KANJI4 + 11 +27769.84838325862 + 21 +28715.17555215314 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +21A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +28263.50320559365 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 4 + 11 +28504.61995686268 + 21 +26116.19078057954 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +21B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +21C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +21D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +29269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +29269.84838325863 + 21 +22867.45981611253 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +21E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +21F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29269.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +220 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +TEXT + 5 +221 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 50 +270.0 + 7 +KANJI4 +100 +AcDbText + 0 +LINE + 5 +222 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +223 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +224 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +225 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +226 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +30769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +227 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +228 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +229 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +22A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +22B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +31769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +22C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +22D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +22E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +22F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +230 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +231 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +232 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +233 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +234 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +235 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +236 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +237 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +238 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +239 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +23A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +23B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +23C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +23D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +27769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +23E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +27769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +23F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +27269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +240 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +27269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +241 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +27769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +242 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +27269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +243 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +28769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +244 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +28769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +245 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +28269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +246 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +28269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +247 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +28769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +248 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +28269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +249 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +29769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +24A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +29769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +24B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +29269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +24C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +29269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +24D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +29769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +24E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +29269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +24F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +31269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +250 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +22867.46592271152 + 30 +0.0 + 11 +30769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +251 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +22867.46592271152 + 30 +0.0 + 11 +29769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +252 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325864 + 20 +22867.46592271152 + 30 +0.0 + 11 +29269.84838325864 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +253 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325864 + 20 +22867.46592271152 + 30 +0.0 + 11 +30269.84838325864 + 21 +22867.46592271152 + 31 +0.0 + 0 +DIMENSION + 5 +2AA +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D2 + 10 +36093.92934893674 + 20 +24502.3001879383 + 30 +0.0 + 11 +34175.90220497137 + 21 +22884.79342597035 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +32841.98269416671 + 23 +20683.17903084397 + 33 +0.0 + 14 +36377.51660009945 + 24 +24218.7129367767 + 34 +0.0 + 50 +45.00000000011105 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +2B7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D3 + 10 +33272.3182317855 + 20 +18992.19422490555 + 30 +0.0 + 11 +32892.24833689904 + 21 +19672.78450179834 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +32841.98269416671 + 23 +20683.17903084397 + 33 +0.0 + 14 +33902.64286594653 + 24 +19622.51885906414 + 34 +0.0 + 50 +134.9999999998889 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +2C4 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33472.53829550178 + 20 +20318.35664042155 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +DIMENSION + 5 +2C5 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D4 + 10 +39061.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 11 +36561.61755388569 + 21 +29076.70702038776 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +28463.15408367813 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +POLYLINE + 5 +2C6 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +20C3 +330 +2C6 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +34061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +VERTEX + 5 +20C4 +330 +2C6 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +39061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +VERTEX + 5 +20C5 +330 +2C6 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +39061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +VERTEX + 5 +20C6 +330 +2C6 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +34061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +SEQEND + 5 +20C7 +330 +2C6 +100 +AcDbEntity + 8 +1 + 62 + 0 + 0 +DIMENSION + 5 +2C7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D5 + 10 +33170.20390755901 + 20 +26963.15408367813 + 30 +0.0 + 11 +32957.70390755901 + 21 +27713.15408367814 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +34061.61755388569 + 24 +26963.15408367813 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +328 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 11 +37726.65216029226 + 21 +19622.51885906414 + 31 +0.0 + 0 +DIMENSION + 5 +329 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D6 + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 11 +37464.84376220628 + 21 +21098.03078219252 + 31 +0.0 + 70 + 34 + 3 +ISO-25 +100 +AcDb2LineAngularDimension + 13 +33902.64286594653 + 23 +19622.51885906414 + 33 +0.0 + 14 +37726.65216029226 + 24 +19622.51885906414 + 34 +0.0 + 15 +37438.17677187927 + 25 +23158.05276499688 + 35 +0.0 + 16 +37421.70235453924 + 26 +20565.44800714964 + 36 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 271 +1070 + 0 +1070 + 271 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 79 +1070 + 2 +1070 + 271 +1070 + 0 +1002 +} + 0 +CIRCLE + 5 +371 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +33971.7196360845 + 20 +15041.48750671567 + 30 +0.0 + 40 +1808.760328193126 + 0 +DIMENSION + 5 +373 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D7 + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 11 +33759.21963608449 + 21 +18228.98750671567 + 31 +0.0 + 70 + 35 + 3 +ISO-25 +100 +AcDbDiametricDimension + 15 +33971.7196360845 + 25 +17041.48750671567 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +DIMENSION + 5 +37C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D8 + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 11 +36541.49406661355 + 21 +16939.26828335956 + 31 +0.0 + 70 + 36 + 3 +ISO-25 +100 +AcDbRadialDimension + 15 +35656.02561149646 + 25 +16119.9648505628 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +ELLIPSE + 5 +3A0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbEllipse + 10 +33971.7196360845 + 20 +15041.48750671567 + 30 +0.0 + 11 +1808.760328193126 + 21 +0.0000000000032901 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 40 +0.5528648458355768 + 41 +0.0 + 42 +6.283185307179586 + 0 +LINE + 5 +3EB +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +10886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3EC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +32162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3EE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +33162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +33162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3EF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +34162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +34162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3F1 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +9886.191051572176 + 30 +0.0 + 11 +40162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F2 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +35162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +35162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +36162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +36162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +37162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +37162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F5 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +38162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +38162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +40162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +39162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +39162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +SPLINE + 5 +3FB +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbSpline +210 +0.0 +220 +0.0 +230 +1.0 + 70 + 8 + 71 + 3 + 72 + 15 + 73 + 11 + 74 + 9 + 42 +0.0000000001 + 43 +0.0000000001 + 44 +0.0000000001 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +1414.213562373095 + 40 +2828.42712474619 + 40 +4242.640687119284 + 40 +5656.85424949238 + 40 +7071.067811865475 + 40 +8485.281374238573 + 40 +9899.494936611667 + 40 +11279.38235200375 + 40 +11279.38235200375 + 40 +11279.38235200375 + 40 +11279.38235200375 + 10 +32162.95930789137 + 20 +10886.19105157217 + 30 +0.0 + 10 +32496.29186790955 + 20 +11386.19109007647 + 30 +0.0 + 10 +33162.9569879459 + 20 +12386.19116708506 + 30 +0.0 + 10 +34162.96858767325 + 20 +10886.19058952059 + 30 +0.0 + 10 +35162.92450870933 + 20 +9386.192784265595 + 30 +0.0 + 10 +36163.08922483765 + 20 +10886.18458285008 + 30 +0.0 + 10 +37162.47443928828 + 20 +12386.21519376713 + 30 +0.0 + 10 +38164.76886535743 + 20 +10886.10095151444 + 30 +0.0 + 10 +39148.1844766345 + 20 +9398.659985702362 + 30 +0.0 + 10 +39827.48280742876 + 20 +10361.51438572329 + 30 +0.0 + 10 +40162.95930789137 + 20 +10837.0271463632 + 30 +0.0 + 11 +32162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +33162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 11 +34162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +35162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 11 +36162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +37162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 11 +38162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +39162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 11 +40162.95930789137 + 21 +10837.0271463632 + 31 +0.0 + 0 +TEXT + 5 +3FC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 40 +500.0 + 1 +ƒXƒvƒ‰ƒCƒ“‹Èü + 7 +KANJI +100 +AcDbText + 0 +LINE + 5 +40C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +40162.95930789137 + 21 +8789.515827027434 + 31 +0.0 + 0 +LINE + 5 +40D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +6789.515827027433 + 30 +0.0 + 11 +40118.791045835 + 21 +6789.515827027426 + 31 +0.0 + 0 +POLYLINE + 5 +40E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +VERTEX + 5 +20D1 +330 +40E +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +32162.95930789137 + 20 +6789.515827027435 + 30 +0.0 + 0 +VERTEX + 5 +20D2 +330 +40E +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +34144.21740571502 + 20 +8789.515827027434 + 30 +0.0 + 0 +VERTEX + 5 +20D3 +330 +40E +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +36162.95930789137 + 20 +6789.515827027435 + 30 +0.0 + 0 +VERTEX + 5 +20D4 +330 +40E +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +38110.78354696862 + 20 +8789.515827027434 + 30 +0.0 + 0 +VERTEX + 5 +20D5 +330 +40E +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +40118.79104583501 + 20 +6789.515827027432 + 30 +0.0 + 0 +SEQEND + 5 +20D6 +330 +40E +100 +AcDbEntity + 8 +0 + 0 +TEXT + 5 +40F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 40 +500.0 + 1 +ƒ|ƒŠƒ‰ƒCƒ“ + 7 +KANJI +100 +AcDbText + 0 +POLYLINE + 5 +411 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 +1001 +ACAD +1000 +ASC_BOUNDS +1002 +{ +1070 + 19 +1005 +434 +1002 +} + 0 +VERTEX + 5 +20D7 +330 +411 +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +37649.98492586595 + 20 +15879.05486911342 + 30 +0.0 + 0 +VERTEX + 5 +20D8 +330 +411 +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +40498.45357200499 + 20 +15879.05486911342 + 30 +0.0 + 0 +VERTEX + 5 +20D9 +330 +411 +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +40498.45357200499 + 20 +13879.05486911342 + 30 +0.0 + 0 +VERTEX + 5 +20DA +330 +411 +100 +AcDbEntity + 8 +0 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +37649.98492586595 + 20 +13879.05486911342 + 30 +0.0 + 0 +SEQEND + 5 +20DB +330 +411 +100 +AcDbEntity + 8 +0 + 0 +INSERT + 5 +434 +330 +1F +100 +AcDbEntity + 8 +0 + 6 +CONTINUOUS +100 +AcDbBlockReference + 2 +*X60 + 10 +0.0 + 20 +0.0 + 30 +0.0 +1001 +ACAD +1000 +HATCH +1002 +{ +1070 + 19 +1000 +ANSI31 +1040 +100.0 +1040 +0.0 +1000 +ASC_BOUNDS +1070 + 1 +1070 + 1 +1070 + 1 +1005 +411 +1000 +ASC_SEEDPOINT +1011 +39291.35995673742 +1021 +15049.92323490473 +1031 +0.0 +1000 +R14_HATCH_DATA +1000 +434 +1011 +1.0 +1021 +0.0 +1031 +0.0 +1011 +0.0 +1021 +1.0 +1031 +0.0 +1011 +0.0 +1021 +0.0 +1031 +1.0 +1040 +0.0 +1010 +0.0 +1020 +0.0 +1030 +1.0 +1000 +ANSI31 +1070 + 0 +1070 + 1 +1071 + 1 +1071 + 7 +1070 + 0 +1070 + 1 +1071 + 4 +1040 +37649.98492586595 +1040 +15879.05486911342 +1040 +37649.98492586595 +1040 +13879.05486911342 +1040 +40498.45357200499 +1040 +13879.05486911342 +1040 +40498.45357200498 +1040 +15879.05486911342 +1071 + 1 +1005 +411 +1070 + 0 +1070 + 1 +1040 +0.0 +1040 +100.0 +1070 + 0 +1070 + 1 +1040 +0.7853981633974483 +1040 +21081.92472009494 +1040 +7900.63361766199 +1040 +-224.5064030267287 +1040 +224.5064030267288 +1070 + 0 +1040 +12.72318334023255 +1071 + 1 +1040 +39291.35995673742 +1040 +15049.92323490473 +1040 +0.0 +1002 +} + 0 +TEXT + 5 +435 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +37649.98492586595 + 20 +16479.05486911342 + 30 +0.0 + 40 +500.0 + 1 +ƒnƒbƒ`ƒ“ƒO + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +436 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +37649.98492586595 + 20 +15879.05486911342 + 30 +0.0 + 40 +500.0 + 1 +ANSI31 + 7 +KANJI +100 +AcDbText + 0 +POINT + 5 +43E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +36750.93264721553 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +43F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +37495.84349439684 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +440 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +38240.75434157815 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +441 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +38985.66518875945 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +442 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +39730.57603594075 + 20 +18178.72189894357 + 30 +0.0 + 0 +TEXT + 5 +443 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +36750.93264721553 + 20 +18486.48910571766 + 30 +0.0 + 40 +500.0 + 1 +“_(â‘Î’PˆÊ300) + 7 +KANJI +100 +AcDbText + 0 +POINT + 5 +444 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +40475.48688312207 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +445 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +41220.39773030337 + 20 +18178.72189894357 + 30 +0.0 + 0 +TEXT + 5 +564 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.831670027631 + 20 +22670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 7 +KANJI2 + 72 + 2 + 11 +6032.801213174838 + 21 +23170.88067496867 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +565 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 7 +KANJI2 + 11 +834.8316700276336 + 21 +21920.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +566 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 11 +6682.541299469253 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +567 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276319 + 20 +22170.88067496866 + 30 +0.0 + 11 +6682.541299469251 + 21 +22170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +568 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276351 + 20 +20670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 1 + 11 +3433.816441601239 + 21 +20920.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +569 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +20670.88067496866 + 30 +0.0 + 11 +6032.797142108851 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +21170.88067496866 + 30 +0.0 + 11 +6032.797142108847 + 21 +21170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276372 + 20 +19670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 7 +KANJI2 + 72 + 2 + 11 +6682.547406068247 + 21 +19920.88067496867 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +56C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +19670.88067496866 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +20170.88067496866 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 7 +KANJI2 + 11 +834.8316700276392 + 21 +18579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +56F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +19170.88067496866 + 30 +0.0 + 11 +6032.797142108851 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +570 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 11 +6032.797142108854 + 21 +18670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +571 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.689538047947 + 21 +17579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +572 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276409 + 20 +18170.88067496866 + 30 +0.0 + 11 +6682.54129946926 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +573 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 11 +6682.54129946926 + 21 +17670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +574 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276436 + 20 +16670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 7 +KANJI2 + 72 + 2 + 11 +6032.801213174851 + 21 +16579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +575 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +16670.88067496866 + 30 +0.0 + 11 +6032.797142108859 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +576 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +17170.88067496866 + 30 +0.0 + 11 +6032.797142108854 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +577 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 11 +7332.293598961658 + 21 +15140.89629083312 + 31 +0.0 + 0 +TEXT + 5 +578 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI2 + 72 + 2 + 11 +7332.293598961658 + 21 +15140.89629083311 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +579 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +7332.293598961658 + 20 +16140.89629083311 + 30 +0.0 + 11 +834.8316700276482 + 21 +16140.89629083311 + 31 +0.0 + 0 +MTEXT + 5 +57A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +834.8316700276477 + 20 +14517.44463265923 + 30 +0.0 + 40 +500.0 + 41 +4532.905584178652 + 71 + 1 + 72 + 1 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI2 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +57B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +14517.44463265923 + 30 +0.0 + 11 +5367.7372542063 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +57C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.737254206298 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +16670.88067496866 + 30 +0.0 + 11 +834.8316700276445 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +57E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +14517.44463265923 + 30 +0.0 + 11 +834.8316700276482 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 11 +834.8316700276482 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +580 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +19670.88067496866 + 30 +0.0 + 11 +834.8316700276372 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +581 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 11 +834.8316700276409 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +582 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 11 +834.8316700276392 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +583 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +20670.88067496866 + 30 +0.0 + 11 +834.8316700276354 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +584 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 11 +834.8316700276319 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +585 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108859 + 20 +16670.88067496867 + 30 +0.0 + 11 +6032.797142108854 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +586 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.052984748452 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +587 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388051 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.308827388049 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +588 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +4083.564670027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +589 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +3433.818070027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +2784.071470027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027645 + 20 +16670.88067496866 + 30 +0.0 + 11 +2134.324870027643 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027645 + 20 +16670.88067496866 + 30 +0.0 + 11 +1484.578270027643 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5367.737254206298 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.7372542063 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +58E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388051 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.308827388051 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +58F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.052984748454 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +590 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108859 + 20 +16670.88067496868 + 30 +0.0 + 11 +6032.797142108859 + 21 +16670.88067496868 + 31 +0.0 + 0 +LINE + 5 +591 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +7332.293598961658 + 20 +15140.89629083312 + 30 +0.0 + 11 +7332.293598961658 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +592 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +4083.564670027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +593 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +3433.818070027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +594 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +2784.071470027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +595 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +1484.578270027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +596 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027638 + 20 +19670.88067496866 + 30 +0.0 + 11 +2134.324870027636 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +597 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +1484.578270027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +598 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +2134.32487002764 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +599 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.07147002764 + 20 +17670.88067496866 + 30 +0.0 + 11 +2784.07147002764 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +1484.578270027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.32487002764 + 20 +18670.88067496866 + 30 +0.0 + 11 +2134.324870027638 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027638 + 20 +18670.88067496866 + 30 +0.0 + 11 +2784.071470027638 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +3433.818070027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +4083.564670027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +3433.818070027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +4083.564670027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +1484.578270027634 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027636 + 20 +20670.88067496866 + 30 +0.0 + 11 +2134.324870027634 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +2784.071470027635 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +1484.578270027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +2134.324870027631 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027631 + 20 +21670.88067496866 + 30 +0.0 + 11 +2784.071470027631 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +3433.818070027635 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027636 + 20 +20670.88067496866 + 30 +0.0 + 11 +4083.564670027636 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +3433.818070027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +4083.564670027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469256 + 20 +19670.88067496867 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +19670.88067496867 + 30 +0.0 + 11 +6032.797142108851 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388044 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.308827388042 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748449 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.052984748447 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388047 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.308827388047 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388047 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.308827388046 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5B1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748452 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.052984748452 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748452 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.05298474845 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +17670.88067496868 + 30 +0.0 + 11 +6032.797142108854 + 21 +17670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5B4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +17670.88067496867 + 30 +0.0 + 11 +6032.797142108854 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474845 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.052984748449 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388046 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.308827388044 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388046 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.308827388046 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474845 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.05298474845 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388044 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.308827388044 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748449 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.052984748449 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +18670.88067496867 + 30 +0.0 + 11 +6032.797142108851 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +18670.88067496868 + 30 +0.0 + 11 +6032.797142108854 + 21 +18670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +19670.88067496868 + 30 +0.0 + 11 +6032.797142108851 + 21 +19670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.54129946926 + 20 +17670.88067496868 + 30 +0.0 + 11 +6682.54129946926 + 21 +17670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.54129946926 + 20 +17670.88067496867 + 30 +0.0 + 11 +6682.54129946926 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469256 + 20 +19670.88067496868 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388042 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.308827388042 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388042 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.30882738804 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748445 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.052984748445 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748445 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.052984748443 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +20670.88067496868 + 30 +0.0 + 11 +6032.797142108851 + 21 +20670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +20670.88067496867 + 30 +0.0 + 11 +6032.797142108847 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388039 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.308827388037 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748443 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.052984748442 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388039 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.308827388039 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748443 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.052984748443 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108847 + 20 +21670.88067496867 + 30 +0.0 + 11 +6032.797142108846 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108847 + 20 +21670.88067496868 + 30 +0.0 + 11 +6032.797142108847 + 21 +21670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5CD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469253 + 20 +21670.88067496867 + 30 +0.0 + 11 +6682.541299469251 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469253 + 20 +21670.88067496868 + 30 +0.0 + 11 +6682.541299469253 + 21 +21670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5CF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 11 +4733.308827388029 + 21 +28670.88067496866 + 31 +0.0 + 0 +TEXT + 5 +5D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +5D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +29170.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5D2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26670.88067496866 + 30 +0.0 + 11 +6682.541299469241 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 7 +KANJI2 + 72 + 2 + 11 +6682.547406068232 + 21 +26670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5D5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +25670.88067496866 + 30 +0.0 + 11 +6032.797142108838 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26170.88067496866 + 30 +0.0 + 11 +6032.797142108837 + 21 +26170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276241 + 20 +25672.14971050166 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 4 + 11 +3433.816441601227 + 21 +25905.65224857272 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +5D8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 7 +KANJI2 + 11 +834.8316700276264 + 21 +25170.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +5D9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 11 +6032.79714210884 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276246 + 20 +25170.88067496866 + 30 +0.0 + 11 +6032.797142108838 + 21 +25170.88067496866 + 31 +0.0 + 0 +TEXT + 5 +5DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +27670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 41 +0.9 + 7 +KANJI2 + 72 + 5 + 11 +6682.547406068232 + 21 +27670.88067496868 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5DC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27670.88067496866 + 30 +0.0 + 11 +6682.541299469241 + 21 +27670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +24170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +23170.88067496866 + 30 +0.0 + 11 +6032.797142108844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +22670.88067496866 + 30 +0.0 + 11 +6032.797142108846 + 21 +22670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5E2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.689538047932 + 21 +24170.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +5E3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 11 +834.8316700276281 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +22670.88067496866 + 30 +0.0 + 11 +834.8316700276299 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 11 +834.8316700276246 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +25670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +28170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027627 + 20 +23670.88067496866 + 30 +0.0 + 11 +2784.071470027627 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027629 + 20 +23670.88067496866 + 30 +0.0 + 11 +2134.324870027627 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +1484.578270027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5ED +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.57827002763 + 20 +22670.88067496866 + 30 +0.0 + 11 +1484.57827002763 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027631 + 20 +22670.88067496866 + 30 +0.0 + 11 +2134.324870027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +2784.071470027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +1484.578270027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +2134.324870027623 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027624 + 20 +24670.88067496866 + 30 +0.0 + 11 +2784.071470027624 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +4083.564670027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +3433.818070027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +3433.818070027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +4083.564670027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +3433.818070027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +4083.564670027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +26670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +26670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +25670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +25670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +600 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +601 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +602 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +603 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108844 + 20 +23670.88067496867 + 30 +0.0 + 11 +6032.79714210884 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +604 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474844 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.052984748438 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +605 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388035 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.308827388032 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +606 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388037 + 20 +22670.88067496867 + 30 +0.0 + 11 +4733.308827388037 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +607 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388037 + 20 +22670.88067496866 + 30 +0.0 + 11 +4733.308827388035 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +608 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748442 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.052984748442 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +609 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748442 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.05298474844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388035 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.308827388035 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474844 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.05298474844 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108846 + 20 +22670.88067496868 + 30 +0.0 + 11 +6032.797142108846 + 21 +22670.88067496868 + 31 +0.0 + 0 +LINE + 5 +60D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108846 + 20 +22670.88067496867 + 30 +0.0 + 11 +6032.797142108844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108844 + 20 +23670.88067496868 + 30 +0.0 + 11 +6032.797142108844 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +60F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388031 + 20 +24670.88067496866 + 30 +0.0 + 11 +4733.308827388029 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +610 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748435 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +611 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388031 + 20 +24670.88067496867 + 30 +0.0 + 11 +4733.308827388031 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +612 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748435 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.052984748435 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +613 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.79714210884 + 20 +24670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +614 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.79714210884 + 20 +24670.88067496868 + 30 +0.0 + 11 +6032.79714210884 + 21 +24670.88067496868 + 31 +0.0 + 0 +LINE + 5 +615 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469247 + 20 +23670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +616 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469247 + 20 +23670.88067496868 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +617 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.797142108837 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +618 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +26670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +619 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.052984748432 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +25670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +25670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +61C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.052984748432 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +26670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +620 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +621 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.797142108837 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +622 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +623 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469241 + 20 +26670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +624 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469242 + 20 +26670.88067496868 + 30 +0.0 + 11 +6682.541299469242 + 21 +26670.88067496868 + 31 +0.0 + 0 +LINE + 5 +625 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469241 + 20 +27670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +626 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469242 + 20 +27670.88067496868 + 30 +0.0 + 11 +6682.541299469242 + 21 +27670.88067496868 + 31 +0.0 + 0 +LINE + 5 +627 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +28670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +628 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +28670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +629 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +28670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +62D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +28670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +29170.88067496866 + 31 +0.0 + 0 +TEXT + 5 +62E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +62F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI + 11 +8432.910636263379 + 21 +21920.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +630 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22170.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +631 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +21670.88067496869 + 31 +0.0 + 0 +LINE + 5 +632 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +20670.8806749687 + 31 +0.0 + 0 +LINE + 5 +633 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21170.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.8806749687 + 31 +0.0 + 0 +TEXT + 5 +634 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 40 +500.0000000000003 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 1 + 11 +11549.57730293004 + 21 +20920.8806749687 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +635 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +19670.88067496871 + 31 +0.0 + 0 +LINE + 5 +636 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20170.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +TEXT + 5 +637 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI + 72 + 2 + 11 +15266.24396959671 + 21 +19920.88067496871 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +638 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +18737.54734163539 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI + 11 +8432.910636263379 + 21 +18670.88067496872 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +639 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19170.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +63A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18670.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +18670.88067496872 + 31 +0.0 + 0 +TEXT + 5 +63B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +17604.21400830207 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +63C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18170.88067496873 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +63D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 11 +15266.24396959671 + 21 +17670.88067496873 + 31 +0.0 + 0 +TEXT + 5 +63E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263384 + 20 +16670.88067496875 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +16604.21400830208 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +63F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +16670.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +16670.88067496874 + 31 +0.0 + 0 +LINE + 5 +640 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17170.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +641 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +16670.88067496875 + 30 +0.0 + 11 +8432.910636263379 + 21 +17170.88067496874 + 31 +0.0 + 0 +LINE + 5 +642 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +8432.910636263384 + 20 +13184.11129932598 + 30 +0.0 + 11 +12965.81622044203 + 21 +13184.11129932597 + 31 +0.0 + 0 +LINE + 5 +643 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +MTEXT + 5 +644 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 40 +500.0 + 41 +4532.905584178652 + 71 + 1 + 72 + 1 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +645 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +15140.89629083319 + 31 +0.0 + 0 +TEXT + 5 +646 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI + 72 + 2 + 11 +14166.24396959671 + 21 +15140.89629083319 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +647 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +16140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +648 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 11 +8432.910636263384 + 21 +13184.11129932598 + 31 +0.0 + 0 +LINE + 5 +649 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 11 +8432.910636263384 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +64A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +12965.81622044203 + 20 +13184.11129932597 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +LINE + 5 +64D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14166.24396959671 + 20 +15140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +64E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 11 +8432.910636263379 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +64F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 11 +8432.910636263379 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +650 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18670.88067496872 + 30 +0.0 + 11 +8432.910636263379 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +651 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 11 +8432.910636263379 + 21 +21170.8806749687 + 31 +0.0 + 0 +LINE + 5 +652 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 11 +8432.910636263379 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +653 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +16670.88067496874 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +654 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +655 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +17670.88067496873 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +656 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +18670.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +657 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +20670.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.8806749687 + 31 +0.0 + 0 +LINE + 5 +658 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +21670.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +659 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26670.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +26670.88067496866 + 31 +0.0 + 0 +LINE + 5 +65A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +65B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263381 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI + 72 + 2 + 11 +15232.91063626337 + 21 +26670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +65C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +65D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +65E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26170.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +65F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +24670.88067496868 + 31 +0.0 + 0 +LINE + 5 +660 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25170.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.88067496868 + 31 +0.0 + 0 +TEXT + 5 +661 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI + 11 +8432.910636263379 + 21 +25170.88067496868 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +662 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.9272727272727273 + 7 +KANJI + 72 + 5 + 11 +15232.91063626337 + 21 +27670.88067496866 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +663 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +27670.88067496866 + 31 +0.0 + 0 +LINE + 5 +664 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +665 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 11 +14666.24396959671 + 21 +22670.88067496868 + 31 +0.0 + 0 +LINE + 5 +666 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23170.88067496869 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +667 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 11 +15266.24396959671 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +668 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24170.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.88067496869 + 31 +0.0 + 0 +TEXT + 5 +669 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +24170.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +66A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI +100 +AcDbText + 0 +LINE + 5 +66B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 11 +8432.910636263379 + 21 +24170.88067496868 + 31 +0.0 + 0 +LINE + 5 +66C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 11 +8432.910636263379 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +66D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 11 +8432.910636263379 + 21 +25170.88067496867 + 31 +0.0 + 0 +LINE + 5 +66E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +66F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +670 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 11 +8432.910636263379 + 21 +28170.88067496866 + 31 +0.0 + 0 +LINE + 5 +671 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +29170.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +672 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +673 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +674 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +13432.91063626337 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +675 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +23670.88067496868 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.88067496869 + 31 +0.0 + 0 +LINE + 5 +676 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +22670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +677 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +24670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.88067496868 + 31 +0.0 + 0 +LINE + 5 +678 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15232.91063626337 + 20 +26670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +679 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15232.91063626337 + 20 +27670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.20600900591 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 + 0 +LINE + 5 +67E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.20600900591 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 + 0 +LINE + 5 +680 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.2060090059 + 30 +0.0 + 11 +18739.86399912308 + 21 +23517.2060090059 + 31 +0.0 + 0 +TEXT + 5 +681 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +25683.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI3 + 72 + 2 + 11 +25683.30873463529 + 21 +12102.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +685 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +21683.30873463532 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI3 + 11 +21683.30873463532 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +TEXT + 5 +686 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +22683.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI3 + 72 + 2 + 11 +22683.30873463531 + 21 +11468.7721504546 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +689 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +23683.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 1 + 11 +23683.3087346353 + 21 +16577.10548378792 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +68E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +24683.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI3 + 11 +24683.3087346353 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +697 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +26683.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI3 + 72 + 1 + 11 +26683.30873463528 + 21 +16277.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +69E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +30683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.6677577741407528 + 7 +KANJI3 + 72 + 2 + 11 +30683.30873463527 + 21 +10902.10548378792 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +69F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +27683.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI3 + 11 +27683.30873463528 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +6A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28433.30873463526 + 21 +12068.77215045459 + 31 +0.0 + 0 +TEXT + 5 +6A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +28683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 2 + 11 +28683.30873463527 + 21 +12068.77215045459 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +29683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI3 + 72 + 2 + 11 +29683.30873463527 + 21 +11502.10548378792 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +31683.30873463526 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI3 + 72 + 2 + 11 +31683.30873463526 + 21 +13418.77215045459 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +19683.30873463535 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI3 + 72 + 2 + 11 +19683.30873463535 + 21 +12068.7721504546 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +TEXT + 5 +6BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +20683.30873463533 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI3 + 72 + 1 + 11 +20683.30873463533 + 21 +16277.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +6BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +18903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +TEXT + 5 +6C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +18403.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 7 +KANJI3 +100 +AcDbText + 0 +LINE + 5 +6C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +17903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +MTEXT + 5 +6C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +15946.53935899258 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 41 +6072.728764697807 + 71 + 1 + 72 + 3 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI3 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +6C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17479.87269232592 + 20 +21085.43881712126 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6C4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +15946.53935899258 + 20 +21085.43881712126 + 30 +0.0 + 11 +15946.53935899257 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17479.87269232592 + 20 +21085.43881712126 + 30 +0.0 + 11 +15946.53935899258 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15946.53935899257 + 20 +15002.24551827521 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6CC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17903.3243504998 + 20 +16485.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +LINE + 5 +6CD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +28433.30873463526 + 20 +12068.77215045459 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6CF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +28433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +27433.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6D3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +27933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +25433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D9 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +25433.30873463527 + 20 +12102.10548378793 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25433.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6F0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27433.30873463527 + 20 +12102.10548378793 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29433.30873463526 + 21 +11502.10548378793 + 31 +0.0 + 0 +LINE + 5 +6F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +29433.30873463526 + 20 +11502.10548378793 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +29433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26433.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6FE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +11468.7721504546 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24433.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +700 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24933.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +701 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +11468.7721504546 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +702 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +703 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +704 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23433.30873463528 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +705 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23933.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +706 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +23433.30873463528 + 20 +12068.77215045459 + 30 +0.0 + 11 +23933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +707 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +23433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +708 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +709 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22433.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +70A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +11468.7721504546 + 30 +0.0 + 11 +22933.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +70B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +70F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21433.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +710 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +21433.30873463529 + 20 +12068.77215045459 + 30 +0.0 + 11 +21933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +711 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +21433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +712 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20433.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +713 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +714 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +11468.7721504546 + 30 +0.0 + 11 +20933.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +715 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +716 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +717 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19433.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19433.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +718 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19933.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19933.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +719 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19433.3087346353 + 20 +12068.77215045459 + 30 +0.0 + 11 +19933.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +71A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19433.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19933.30873463531 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +720 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31433.30873463526 + 21 +13418.7721504546 + 31 +0.0 + 0 +LINE + 5 +721 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +722 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +31433.30873463526 + 20 +13418.7721504546 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +723 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +31433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +726 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30516.60873463526 + 20 +21085.43881712126 + 30 +0.0 + 11 +30516.60873463526 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +727 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30850.00873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +729 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30516.60873463526 + 20 +10902.10548378792 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +72A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30516.60873463526 + 20 +21085.43881712126 + 30 +0.0 + 11 +30850.00873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +730 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +29231.97245541628 + 21 +10114.99828738483 + 31 +0.0 + 0 +LINE + 5 +731 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +27731.97245541628 + 21 +7516.922076031523 + 31 +0.0 + 0 +LINE + 5 +732 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +29231.97245541628 + 21 +10114.99828738483 + 31 +0.0 + 0 +LINE + 5 +735 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +29231.97245541628 + 21 +6867.403023193194 + 31 +0.0 + 0 +LINE + 5 +736 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +30731.97245541628 + 21 +9465.479234546508 + 31 +0.0 + 0 +LINE + 5 +737 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +29231.97245541628 + 21 +6867.403023193194 + 31 +0.0 + 0 +TEXT + 5 +73B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +27375.98522036158 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒOƒ‹[ƒv}Œ` + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +73C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23443.86458478673 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒuƒƒbƒN}Œ` + 7 +KANJI +100 +AcDbText + 0 +INSERT + 5 +74D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 2 +NONAME + 10 +12199.75897743096 + 20 +4508.97892854021 + 30 +0.0 + 41 +0.6 + 42 +0.6 + 43 +0.6 + 0 +LINE + 5 +74E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +40162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +40162.95930789137 + 21 +6789.515827027426 + 31 +0.0 + 0 +LINE + 5 +74F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +38110.78354696862 + 20 +8789.515827027434 + 30 +0.0 + 11 +38110.78354696862 + 21 +6789.515827027428 + 31 +0.0 + 0 +LINE + 5 +750 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +36162.95930789138 + 20 +6789.515827027429 + 30 +0.0 + 11 +36162.95930789138 + 21 +8789.515827027434 + 31 +0.0 + 0 +LINE + 5 +752 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +34144.21740571502 + 20 +8789.515827027434 + 30 +0.0 + 11 +34144.21740571502 + 21 +6789.515827027432 + 31 +0.0 + 0 +LINE + 5 +753 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +32162.95930789137 + 21 +6789.515827027435 + 31 +0.0 + 0 +DIMENSION + 5 +755 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D10 + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +2084.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +834.8316700276482 + 23 +3391.885493772555 + 33 +0.0 + 14 +3334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 + +1070 + 173 +1070 + 1 +1070 + 7 +1000 + +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +801 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D12 + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +4584.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +3334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +5834.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSEDBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSEDBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +83A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +684.8316700276475 + 20 +5515.901028694454 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +2084.831670027647 + 21 +5515.901028694454 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +83B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +1568.165003360981 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +–îˆó + 7 +KANJI + 72 + 1 + 11 +2084.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +83C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +3768.165003360982 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +‹ó–îˆó + 7 +KANJI + 72 + 1 + 11 +4584.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +83D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D14 + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +7084.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +5834.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +8334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +865 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6251.498336694315 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +•Â–îˆó + 7 +KANJI + 72 + 1 + 11 +7084.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +866 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D15 + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +9584.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +8334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +10834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOT +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOT +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +893 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +9051.498336694313 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +•ŠÛ + 7 +KANJI + 72 + 1 + 11 +9584.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +89C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +11534.83167002764 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +(‘¾) + 7 +KANJI + 72 + 1 + 11 +12084.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +89D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D17 + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +12084.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +10834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +13334.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ARCHTICK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ARCHTICK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8C9 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +13468.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +14584.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +8CA +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D19 + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +14584.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +13334.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +15834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OBLIQUE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OBLIQUE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F6 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +10968.16500336098 + 20 +5452.894222873409 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +12084.83167002764 + 21 +5452.894222873409 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +8F7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D21 + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +17084.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +15834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +18334.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +16251.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŠJ–îˆó + 7 +KANJI + 72 + 1 + 11 +17084.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +92F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D23 + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +19584.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +18334.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +20834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +930 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +18868.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ1 + 7 +KANJI + 72 + 1 + 11 +19584.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +97D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D25 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +22084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +20834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +23334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN2 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN2 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +97E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +21284.83167002765 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ2 + 7 +KANJI + 72 + 1 + 11 +22084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +9C3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D27 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +24584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +23334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +25834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN90 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN90 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +9C4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23468.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +’¼Šp–îˆó + 7 +KANJI + 72 + 1 + 11 +24584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +AAF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D29 + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +27084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +25834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +28334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN30 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN30 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +AB0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25809.83167002764 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +30‹–îˆó + 7 +KANJI + 72 + 1 + 11 +27084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +AE7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +28751.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +¬•ŠÛ + 7 +KANJI + 72 + 1 + 11 +29584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +AE8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D31 + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +29584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +28334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +30834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTSMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTSMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +B1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D33 + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +32084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +30834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +33334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B1E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +31251.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +32084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +B55 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D35 + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +34584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +33334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +35834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +SMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +SMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B56 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +33451.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +¬‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +34584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +B82 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +36551.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +37084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +B83 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D37 + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +37084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +35834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +38334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E64 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +39051.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +39584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +E65 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D39 + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +39584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +38334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +40834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E92 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +38184.83167002765 + 20 +5419.627964172512 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +39584.83167002765 + 21 +5419.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +E93 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D41 + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +5124.072001619017 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +3874.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +6374.072001619017 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E94 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +4007.405334952351 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +5124.072001619017 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +ED4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +4624.072001619017 + 20 +2702.193038433077 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ + 7 +KANJI + 72 + 1 + 11 +5124.072001619017 + 21 +2702.193038433077 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +F80 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6507.405334952351 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +7624.072001619016 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +F81 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D43 + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +7624.072001619016 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +6374.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +8874.072001619017 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +FAD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6224.072001619017 + 20 +2702.193038433077 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +7624.072001619016 + 21 +2702.193038433077 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +114E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D45 + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +10124.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +8874.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +11374.07200161901 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +INTEGRAL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +INTEGRAL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +114F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +9590.738668285684 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +”gŒ` + 7 +KANJI + 72 + 1 + 11 +10124.07200161901 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +117C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D47 + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +12624.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +11374.07200161901 + 23 +732.4176621089645 + 33 +0.0 + 14 +13874.07200161901 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +NONE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +NONE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +117D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +12124.07200161901 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +‚È‚µ + 7 +KANJI + 72 + 1 + 11 +12624.07200161901 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +13F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D49 + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +16871.32612140059 + 21 +1663.887067986979 + 31 +0.0 + 70 + 160 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +14608.82612140059 + 23 +732.4176621089645 + 33 +0.0 + 14 +16108.82612140059 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +DIMENSION + 5 +147B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D50 + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +20467.18096413649 + 21 +1663.887067986979 + 31 +0.0 + 70 + 160 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +19054.68096413649 + 23 +732.4176621089645 + 33 +0.0 + 14 +19554.68096413649 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 279 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +TEXT + 5 +151F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +14219.42234363432 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ŠOŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +15936.08901030098 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +152B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +18038.39553279113 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +“àŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +19771.72886612446 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +156C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +22164.30081507835 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +À•W¡–@ + 7 +KANJI + 72 + 1 + 11 +23297.63414841168 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1682 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D53 + 10 +38079.23269341683 + 20 +22516.99684345932 + 30 +0.0 + 11 +36161.20554944833 + 21 +20899.49008149508 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +33902.64286594653 + 23 +19622.51885906414 + 33 +0.0 + 14 +37438.17677187927 + 24 +23158.05276499688 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +168F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D54 + 10 +38005.66793242672 + 20 +23725.54392554433 + 30 +0.0 + 11 +37625.59803753895 + 21 +24406.13420243639 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +36377.51660009945 + 23 +24218.7129367767 + 33 +0.0 + 14 +37438.17677187927 + 24 +23158.05276499688 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D55 + 10 +39061.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 11 +36561.61755388569 + 21 +26269.06410520013 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +26963.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +26963.15408367813 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D56 + 10 +39864.17124965874 + 20 +26963.15408367813 + 30 +0.0 + 11 +39651.67124965873 + 21 +27713.15408367814 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +39061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +26963.15408367813 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +1710 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33826.09168609505 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1711 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33472.53829550178 + 20 +20318.35664042155 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1712 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33826.09168609505 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1840 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27759.31555586257 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1841 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27759.31555586257 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1842 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27259.31555586257 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1843 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27259.31555586257 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CB +330 +1F +100 +AcDbEntity + 8 +ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +2369.538337786623 + 30 +0.0 + 40 +500.0 + 1 +ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CC +330 +1F +100 +AcDbEntity + 8 +”ñ•\Ž¦‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +1869.538337786623 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CD +330 +1F +100 +AcDbEntity + 8 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +1369.538337786623 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CF +330 +1F +100 +AcDbEntity + 8 +ƒƒbƒN‚³‚ꂽ‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +869.5383377866237 + 30 +0.0 + 40 +500.0 + 1 +ƒƒbƒN‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1ABE +330 +1F +100 +AcDbEntity + 8 +ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +18013.26504642274 + 20 +8351.553922912222 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1ABF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +15934.06065949847 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +(ƒ|ƒŠƒ‰ƒCƒ“) + 7 +KANJI + 72 + 1 + 11 +17684.06065949847 + 21 +10232.27806776508 + 31 +0.0 +100 +AcDbText + 0 +POLYLINE + 5 +1AC1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDb2dPolyline + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 1 + 0 +VERTEX + 5 +20F3 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +17355.64886932063 + 20 +9506.927495816984 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F4 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16857.00923996034 + 20 +9506.927495816984 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F5 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16477.09299069931 + 20 +9328.998963914726 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F6 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16239.64555880858 + 20 +8996.86581798768 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F7 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16061.55981696746 + 20 +8617.285079785302 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F8 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16120.9217309145 + 20 +8202.118586506607 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20F9 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16346.49700391324 + 20 +7869.985440579533 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FA +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +16643.30634975101 + 20 +7514.128376775044 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FB +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +17023.22237511465 + 20 +7348.061803811521 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FC +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +17498.11746279351 + 20 +7265.02857819965 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FD +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +17913.65063652536 + 20 +7312.476170474926 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FE +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +18293.56666188899 + 20 +7478.542743438477 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +20FF +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +18720.97221841025 + 20 +7644.609316401998 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2100 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +19041.52655372422 + 20 +7905.57107391613 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2101 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +19207.73968887853 + 20 +8273.289974919549 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2102 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +19326.4635167726 + 20 +8664.732672060607 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2103 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +19362.08066514082 + 20 +9079.899165339332 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2104 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +19112.76085046067 + 20 +9412.032311266376 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2105 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +18768.46174956788 + 20 +9625.546476505203 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2106 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +18341.05619304662 + 20 +9756.027416132157 + 30 +0.0 + 42 +0.52056705 + 0 +VERTEX + 5 +2107 +330 +1AC1 +100 +AcDbEntity + 8 +1 +100 +AcDbVertex +100 +AcDb2dVertex + 10 +17913.65063652536 + 20 +9815.336845606392 + 30 +0.0 + 42 +0.52056705 + 0 +SEQEND + 5 +2108 +330 +1AC1 +100 +AcDbEntity + 8 +1 + 0 +TEXT + 5 +1AE3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +20103.52469524904 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒŠ[ƒWƒ‡ƒ“ + 7 +KANJI +100 +AcDbText + 0 +REGION + 5 +1AE7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbModelerGeometry + 70 + 1 + 1 +noi io n o + 1 +=0;& {rn {n {rn {rn | + 1 +3*2/ {rn {rn {m {o | + 1 +,7:33 {rn {rn {rn {l {n | + 1 +9><: {rn {rn {k {m {rn {j 90-(>-; ;0*=3: 0*+ | + 1 +300/ {rn {rn {i {l | + 1 +/3>1:r,*-9><: {rn mnkjfqjilkkillkig gjffqkjlglohimoifi o o o n n o o o V V V V | + 1 +<0:;8: {rn {h {g {rn {f n {k {rn | + 1 +<0:;8: {rn {no {i {rn {nn n {k {rn | + 1 +<0:;8: {rn {i {nm {rn {nl o {k {rn | + 1 +:;8: {rn {nk {nj {i {ni o | + 1 +<0:;8: {rn {nh {h {rn {ng o {k {rn | + 1 +:;8: {rn {nf {nk {h {mo o | + 1 +<0:;8: {rn {g {mn {rn {mm n {k {rn | + 1 +:;8: {rn {ml {nj {g {mk o | + 1 +):-+:' {rn {nn {mj | + 1 +):-+:' {rn {f {mi | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig fkijqkhfmlkjkijogj o roqjoooooooooooooomm roqgiiomjkolhgkklgi o V V | + 1 +<0:;8: {rn {mh {no {rn {mg n {k {rn | + 1 +:;8: {rn {nf {mf {no {mk o | + 1 +):-+:' {rn {nn {lo | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o n o o V V | + 1 +<0:;8: {rn {nm {ln {rn {lm n {k {rn | + 1 +:;8: {rn {ml {ll {nm {lk o | + 1 +):-+:' {rn {mm {lj | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o roqjoooooooooooooomm oqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mmfjfqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +/061+ {rn mmlfhqoilkkillkig gkfnqmooijjmgfonin o | + 1 +<0:;8: {rn {li {nh {rn {lh n {k {rn | + 1 +:;8: {rn {lg {mf {nh {lf o | + 1 +):-+:' {rn {mg {ko | + 1 +/061+ {rn mnglkqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +<0:;8: {rn {mn {kn {rn {km o {k {rn | + 1 +:;8: {rn {ll {kl {mn {ni o | + 1 +):-+:' {rn {lm {kk | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o rn o o V V | + 1 +/061+ {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o | + 1 +<0:;8: {rn {kj {mh {rn {ki o {k {rn | + 1 +:;8: {rn {kh {lg {mh {mo o | + 1 +):-+:' {rn {lh {kg | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig hjniqfmmohiolnjmm o oqjoooooooooooooomm oqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mnkjfqjilkkillkig nonnkqffgmghlgkglh o | + 1 +<0:;8: {rn {ln {kj {rn {kf n {k {rn | + 1 +:;8: {rn {jo {kl {ln {jn o | + 1 +):-+:' {rn {lm {jm | + 1 +/061+ {rn mnglkqjilkkillkig hjniqfmmohiolnjmm o | + 1 +<0:;8: {rn {kn {li {rn {jl n {k {rn | + 1 +:;8: {rn {kh {jk {li {jn o | + 1 +):-+:' {rn {lh {jj | + 1 +/061+ {rn mnogkqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +:;8: {rn {jo {ji {kn {lk o | + 1 +):-+:' {rn {km {jh | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o oqjoooooooooooooomm roqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mnkjfqjilkkillkig igihqkolomlnflnflg o | + 1 +:;8: {rn {ji {jk {kj {lf o | + 1 +):-+:' {rn {jl {jg | + 1 +/061+ {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +):-+:' {rn {kf {jf | + 1 +/061+ {rn mnogkqjilkkillkig hjniqfmmohiolnjmm o | + 1 +/061+ {rn mojmmqoilkkillkig gkfnqmooijjmgfonin o | + 1 +/061+ {rn nffjfqjilkkillkig hjniqfmmohiolnjmm o | + 0 +TEXT + 5 +1B72 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +16584.06065949847 + 20 +10732.27806776508 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI + 72 + 1 + 11 +17684.06065949847 + 21 +10732.27806776508 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1DFD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D57 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +24827.83753739796 + 21 +2292.399842974457 + 31 +0.0 + 70 + 102 + 3 +ISO-25 +100 +AcDbOrdinateDimension + 13 +24000.0 + 23 +703.3640086830565 + 33 +0.0 + 14 +24978.46253739796 + 24 +1666.774842974453 + 34 +0.0 + 0 +DIMENSION + 5 +1E0E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D58 + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +27433.79486998995 + 21 +1653.666411913524 + 31 +0.0 + 70 + 160 + 1 +<<>> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +25446.29486998995 + 23 +732.4176621089645 + 33 +0.0 + 14 +26446.29486998995 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +1E26 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 11 +26446.29486998995 + 21 +732.4176621089645 + 31 +0.0 + 0 +TEXT + 5 +1F2A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25832.99885892392 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ã‘‚« + 7 +KANJI + 72 + 1 + 11 +26632.99885892392 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +1F2B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25516.33219225725 + 20 +2661.684551031591 + 30 +0.0 + 40 +500.0 + 1 +¡–@’l‚Ì + 7 +KANJI + 72 + 1 + 11 +26632.99885892392 + 21 +2661.684551031591 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1F54 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D59 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +22870.3274027464 + 21 +1811.026028986983 + 31 +0.0 + 70 + 38 + 3 +ISO-25 +100 +AcDbOrdinateDimension + 13 +21761.90789325554 + 23 +700.0 + 33 +0.0 + 14 +22519.7024027464 + 24 +1660.401028986984 + 34 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACADDIM +350 +3A2 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +12CA +330 +1F +100 +AcDbDictionary + 3 +ACAD_LAYOUTSELFREF +350 +20BC +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 1 + 0 +DICTIONARY + 5 +12CC +330 +1B +100 +AcDbDictionary + 3 +ACAD_LAYOUTSELFREF +350 +20BB +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 1 + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +*A1 +350 +739 + 3 +*A2 +350 +1AE4 + 3 +*A3 +350 +1AE5 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +1A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +17 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +DICTIONARY + 5 +19 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +1001 +ACAD +1000 +TREAT_AS_HARD +1070 + 0 + 0 +XRECORD + 5 +3A2 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbXrecord + 90 + 990106 + 3 + + 60 + 0 + 61 + 0 + 62 + 1 + 63 + 3 + 64 + 0 + 65 + 0 + 66 + 0 + 67 + 3 + 68 + 1 + 69 + 0 + 70 + 0 + 71 + 0 + 72 + 0 + 40 +843.2087290138007 +170 + 0 + 0 +XRECORD + 5 +20BC +102 +{ACAD_REACTORS +330 +12CA +102 +} +330 +12CA +100 +AcDbXrecord +340 +1F + 0 +XRECORD + 5 +20BB +102 +{ACAD_REACTORS +330 +12CC +102 +} +330 +12CC +100 +AcDbXrecord +340 +1B + 0 +GROUP + 5 +739 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 +340 +736 +340 +735 +340 +731 +340 +732 +340 +737 +340 +730 + 0 +GROUP + 5 +1AE4 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 + 0 +GROUP + 5 +1AE5 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 + 0 +MLINESTYLE + 5 +18 +102 +{ACAD_REACTORS +330 +17 +102 +} +330 +17 +100 +AcDbMlineStyle + 2 +STANDARD + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 2 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test2_r14.dxf b/share/extensions/tests/data/io/test2_r14.dxf new file mode 100644 index 0000000..df5dbf1 --- /dev/null +++ b/share/extensions/tests/data/io/test2_r14.dxf @@ -0,0 +1,38018 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$ACADMAINTVER + 70 + 9 + 9 +$DWGCODEPAGE + 3 +ANSI_932 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +-1.773829838086385 + 20 +-1.103180821155547 + 30 +-0.0000000000112498 + 9 +$EXTMAX + 10 +42052.11217275027 + 20 +29762.89687612323 + 30 +0.0000000000002956 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +420.0 + 20 +297.0 + 9 +$ORTHOMODE + 70 + 1 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 1 + 9 +$DRAGMODE + 70 + 2 + 9 +$LTSCALE + 40 +100.0 + 9 +$OSMODE + 70 + 3071 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +500.0 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +KANJI + 9 +$CLAYER + 8 +1 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DELOBJ + 70 + 1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937007874016 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMFIT + 70 + 3 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMUNIT + 70 + 2 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$BLIPMODE + 70 + 0 + 9 +$CHAMFERA + 40 +10.0 + 9 +$CHAMFERB + 40 +10.0 + 9 +$CHAMFERC + 40 +20.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2451983.493486933 + 9 +$TDUPDATE + 40 +2451983.695053854 + 9 +$TDINDWG + 40 +0.1336353356 + 9 +$TDUSRTIMER + 40 +0.1336352199 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 3 + 9 +$PDSIZE + 40 +300.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$COORDS + 70 + 1 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$ATTDIA + 70 + 0 + 9 +$ATTREQ + 70 + 1 + 9 +$HANDLING + 70 +-16383 + 9 +$HANDSEED + 5 +20BA + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 48 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.000000000000000E+20 + 20 +1.000000000000000E+20 + 30 +1.000000000000000E+20 + 9 +$PEXTMAX + 10 +-1.000000000000000E+20 + 20 +-1.000000000000000E+20 + 30 +-1.000000000000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +420.0 + 20 +297.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 0 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$PICKSTYLE + 70 + 3 + 9 +$CMLSTYLE + 2 +STANDARD + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LONG_TRANSACTION + 2 +AcDbLongTransaction + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LWPOLYLINE + 2 +AcDbPolyline + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +HATCH + 2 +AcDbHatch + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 1 + 0 +CLASS + 1 +XRECORD + 2 +AcDbXrecord + 3 +AutoCAD 2000 + 90 + 0 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 6 + 0 +VPORT + 5 +208C +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +21025.16917145609 + 22 +14880.89684765104 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +30109.42365528417 + 41 +1.839147286821705 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HIDDEN + 70 + 0 + 3 +------------------------ + 72 + 65 + 73 + 2 + 40 +12.6 + 49 +8.4 + 74 + 0 + 49 +-4.2 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ + 72 + 65 + 73 + 2 + 40 +8.0 + 49 +6.0 + 74 + 0 + 49 +-2.0 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +--¥--¥--¥--¥--¥--¥--¥-- + 72 + 65 + 73 + 4 + 40 +50.5 + 49 +30.0 + 74 + 0 + 49 +-9.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-9.0 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +--¥¥--¥¥--¥¥--¥¥--¥¥-- + 72 + 65 + 73 + 6 + 40 +58.0 + 49 +30.0 + 74 + 0 + 49 +-9.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-5.0 + 74 + 0 + 49 +2.5 + 74 + 0 + 49 +-9.0 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 8 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +36 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +1 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +29D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +DEFPOINTS + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +E63 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +NORMAL + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18C8 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +”ñ•\Ž¦‰æ‘w + 70 + 0 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18C9 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + 7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18CA +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w + 70 + 1 + 62 + -7 + 6 +CONTINUOUS + 0 +LAYER + 5 +18CE +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +ƒƒbƒN‚³‚ꂽ‰æ‘w + 70 + 4 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +300.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +300.0 + 3 +txt.shx + 4 + + 0 +STYLE + 5 +37 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +STYLE + 5 +38 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI2 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +MS Gothic.ttf + 4 + +1001 +ACAD +1000 +MS Gothic +1071 + 32817 + 0 +STYLE + 5 +446 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI4 + 70 + 0 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +@MS Gothic.ttf + 4 + +1001 +ACAD +1000 +@MS Gothic +1071 + 32817 + 0 +STYLE + 5 +67C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +KANJI3 + 70 + 4 + 40 +500.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +500.0 + 3 +TXT.shx + 4 +BIGFONT.shx + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +133A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +CONTENTBLOCKICON + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +DIMSTYLE +105 +27 +102 +{ACAD_REACTORS +330 +2C5 +330 +2C7 +330 +329 +330 +373 +330 +37C +330 +755 +330 +801 +330 +83D +330 +866 +330 +89D +330 +8CA +330 +8F7 +330 +92F +330 +97D +330 +9C3 +330 +AAF +330 +AE8 +330 +B1D +330 +B55 +330 +B83 +330 +E65 +330 +E93 +330 +F81 +330 +114E +330 +117C +330 +13F4 +330 +147B +330 +2B7 +330 +2AA +330 +1682 +330 +168F +330 +16AE +330 +16AF +330 +1DFD +330 +1E0E +330 +1F54 +102 +} +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +DIMSTYLE +105 +39 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +STANDARD + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +0.18 + 42 +0.0625 + 43 +0.38 + 44 +0.18 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +0.18 +141 +0.09 +142 +0.0 +143 +25.4 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.09 + 71 + 0 + 72 + 0 + 73 + 1 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 60 + 0 +BLOCK_RECORD + 5 +1F +102 +{ACAD_XDICTIONARY +360 +12CA +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +102 +{ACAD_XDICTIONARY +360 +12CC +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +BLOCK_RECORD + 5 +2B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*U1 + 0 +BLOCK_RECORD + 5 +2AB +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D2 + 0 +BLOCK_RECORD + 5 +2B8 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D3 + 0 +BLOCK_RECORD + 5 +2C8 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D4 + 0 +BLOCK_RECORD + 5 +2D4 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D5 + 0 +BLOCK_RECORD + 5 +32A +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D6 + 0 +BLOCK_RECORD + 5 +374 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D7 + 0 +BLOCK_RECORD + 5 +37D +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D8 + 0 +BLOCK_RECORD + 5 +744 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +NONAME +1001 +ACAD +1000 +DesignCenter Data +1002 +{ +1070 + 1 +1070 + 4 +1002 +} +1001 +CONTENTBLOCKICON +1071 + 0 +1004 +2800000020000000200000000100080000000000000400000000000000000000000000000000000000000000000080000080000000808000800000008000800080800000C0C0C000C0DCC000F0CAA6000020400000206000002080000020A0000020C0000020E00000400000004020000040400000406000004080000040A0 +1004 +000040C0000040E00000600000006020000060400000606000006080000060A0000060C0000060E00000800000008020000080400000806000008080000080A0000080C0000080E00000A0000000A0200000A0400000A0600000A0800000A0A00000A0C00000A0E00000C0000000C0200000C0400000C0600000C0800000C0 +1004 +A00000C0C00000C0E00000E0000000E0200000E0400000E0600000E0800000E0A00000E0C00000E0E00040000000400020004000400040006000400080004000A0004000C0004000E00040200000402020004020400040206000402080004020A0004020C0004020E000404000004040200040404000404060004040800040 +1004 +40A0004040C0004040E00040600000406020004060400040606000406080004060A0004060C0004060E00040800000408020004080400040806000408080004080A0004080C0004080E00040A0000040A0200040A0400040A0600040A0800040A0A00040A0C00040A0E00040C0000040C0200040C0400040C0600040C08000 +1004 +40C0A00040C0C00040C0E00040E0000040E0200040E0400040E0600040E0800040E0A00040E0C00040E0E00080000000800020008000400080006000800080008000A0008000C0008000E00080200000802020008020400080206000802080008020A0008020C0008020E00080400000804020008040400080406000804080 +1004 +008040A0008040C0008040E00080600000806020008060400080606000806080008060A0008060C0008060E00080800000808020008080400080806000808080008080A0008080C0008080E00080A0000080A0200080A0400080A0600080A0800080A0A00080A0C00080A0E00080C0000080C0200080C0400080C0600080C0 +1004 +800080C0A00080C0C00080C0E00080E0000080E0200080E0400080E0600080E0800080E0A00080E0C00080E0E000C0000000C0002000C0004000C0006000C0008000C000A000C000C000C000E000C0200000C0202000C0204000C0206000C0208000C020A000C020C000C020E000C0400000C0402000C0404000C0406000C0 +1004 +408000C040A000C040C000C040E000C0600000C0602000C0604000C0606000C0608000C060A000C060C000C060E000C0800000C0802000C0804000C0806000C0808000C080A000C080C000C080E000C0A00000C0A02000C0A04000C0A06000C0A08000C0A0A000C0A0C000C0A0E000C0C00000C0C02000C0C04000C0C06000 +1004 +C0C08000C0C0A000F0FBFF00A4A0A000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF000000000000000000000000000000000000000000000000000000000000FF +1004 +00FF0000000000000000000000000000000000000000000000000000000000FF00FF00000000000000000000000000000000000000000000000000000000FF000000FF000000000000000000000000000000000000000000000000000000FF000000FF0000000000000000000000000000000000000000000000000000FF00 +1004 +00000000FF000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000FF00000000000000FF00000000000000FF0000000000000000FF000000000000FF000000000000FF000000000000000000FF00000000000000FF00000000000000FF0000000000FF0000 +1004 +00000000000000FF000000000000FF0000000000000000FF00000000FF0000000000000000000000FF0000000000FF000000000000000000FF000000FF000000000000000000000000FF000000FF00000000000000000000FF0000FF00000000000000000000000000FF0000FF000000000000000000000000FF00FF000000 +1004 +0000000000000000000000FF00FF00000000000000000000000000FF00000000000000000000000000000000FF0000000000000000000000000000FF00000000000000000000000000000000FF00000000000000000000000000FF00FF0000000000000000000000000000FF00FF0000000000000000000000FF0000FF0000 +1004 +0000000000000000000000FF0000FF0000000000000000000000FF000000FF000000000000000000000000FF000000FF000000000000000000FF00000000FF0000000000000000000000FF0000000000FF0000000000000000FF0000000000FF000000000000000000FF000000000000FF00000000000000FF000000000000 +1004 +FF000000000000000000FF00000000000000FF000000000000FF00000000000000FF00000000000000FF0000000000000000FF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000FF0000000000FF00000000000000000000000000000000000000000000 +1004 +00000000FF000000FF000000000000000000000000000000000000000000000000000000FF000000FF00000000000000000000000000000000000000000000000000000000FF00FF0000000000000000000000000000000000000000000000000000000000FF00FF0000000000000000000000000000000000000000000000 +1004 +00000000000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 0 +BLOCK_RECORD + 5 +756 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D10 + 0 +BLOCK_RECORD + 5 +7CC +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSEDBLANK + 0 +BLOCK_RECORD + 5 +802 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D12 + 0 +BLOCK_RECORD + 5 +820 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_CLOSED + 0 +BLOCK_RECORD + 5 +83E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D14 + 0 +BLOCK_RECORD + 5 +867 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D15 + 0 +BLOCK_RECORD + 5 +87C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOT + 0 +BLOCK_RECORD + 5 +89E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D17 + 0 +BLOCK_RECORD + 5 +8B3 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ARCHTICK + 0 +BLOCK_RECORD + 5 +8CB +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D19 + 0 +BLOCK_RECORD + 5 +8E0 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OBLIQUE + 0 +BLOCK_RECORD + 5 +8F9 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D21 + 0 +BLOCK_RECORD + 5 +90E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN + 0 +BLOCK_RECORD + 5 +931 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D23 + 0 +BLOCK_RECORD + 5 +946 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ORIGIN + 0 +BLOCK_RECORD + 5 +97F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D25 + 0 +BLOCK_RECORD + 5 +994 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_ORIGIN2 + 0 +BLOCK_RECORD + 5 +9C5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D27 + 0 +BLOCK_RECORD + 5 +9DA +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN90 + 0 +BLOCK_RECORD + 5 +AB1 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D29 + 0 +BLOCK_RECORD + 5 +AC6 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_OPEN30 + 0 +BLOCK_RECORD + 5 +AE9 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D31 + 0 +BLOCK_RECORD + 5 +AFE +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOTSMALL + 0 +BLOCK_RECORD + 5 +B1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D33 + 0 +BLOCK_RECORD + 5 +B34 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DOTBLANK + 0 +BLOCK_RECORD + 5 +B57 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D35 + 0 +BLOCK_RECORD + 5 +B6C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_SMALL + 0 +BLOCK_RECORD + 5 +B84 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D37 + 0 +BLOCK_RECORD + 5 +B99 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_BOXBLANK + 0 +BLOCK_RECORD + 5 +E66 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D39 + 0 +BLOCK_RECORD + 5 +E7B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_BOXFILLED + 0 +BLOCK_RECORD + 5 +E95 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D41 + 0 +BLOCK_RECORD + 5 +EAA +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DATUMBLANK + 0 +BLOCK_RECORD + 5 +F82 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D43 + 0 +BLOCK_RECORD + 5 +F97 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_DATUMFILLED + 0 +BLOCK_RECORD + 5 +1150 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D45 + 0 +BLOCK_RECORD + 5 +1165 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_INTEGRAL + 0 +BLOCK_RECORD + 5 +117E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D47 + 0 +BLOCK_RECORD + 5 +1193 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +_NONE + 0 +BLOCK_RECORD + 5 +13F5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D49 + 0 +BLOCK_RECORD + 5 +147C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D50 + 0 +BLOCK_RECORD + 5 +156E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D51 + 0 +BLOCK_RECORD + 5 +15A5 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D52 + 0 +BLOCK_RECORD + 5 +1683 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D53 + 0 +BLOCK_RECORD + 5 +1690 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D54 + 0 +BLOCK_RECORD + 5 +16B0 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D55 + 0 +BLOCK_RECORD + 5 +16BC +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D56 + 0 +BLOCK_RECORD + 5 +1DFE +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D57 + 0 +BLOCK_RECORD + 5 +1E0F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D58 + 0 +BLOCK_RECORD + 5 +1F55 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*D59 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +30 +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbBlockBegin + 2 +*U1 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*U1 + 1 + + 0 +LINE + 5 +2C +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +0.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2D +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +2E +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +42000.0 + 20 +0.0 + 30 +0.0 + 11 +42000.0 + 21 +29700.0 + 31 +0.0 + 0 +LINE + 5 +2F +330 +2B +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbLine + 10 +42000.0 + 20 +29700.0 + 30 +0.0 + 11 +0.0 + 21 +29700.0 + 31 +0.0 + 0 +ENDBLK + 5 +31 +330 +2B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2B5 +330 +2AB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D2 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D2 + 1 + + 0 +LINE + 5 +171A +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32797.78852034247 + 20 +20727.37320466804 + 30 +0.0 + 11 +32470.00709536237 + 21 +21055.15462964686 + 31 +0.0 + 0 +LINE + 5 +171B +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36333.3224262752 + 20 +24262.90711060077 + 30 +0.0 + 11 +36005.54100128825 + 21 +24590.68853558645 + 31 +0.0 + 0 +LINE + 5 +171C +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32735.17213830715 + 20 +21143.54297729569 + 30 +0.0 + 11 +35917.15265364045 + 21 +24325.52349264132 + 31 +0.0 + 0 +SOLID + 5 +171D +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +32705.70935575765 + 20 +21173.00575984508 + 30 +0.0 + 11 +32764.63492085665 + 21 +21114.08019474631 + 31 +0.0 + 12 +32558.39544301086 + 22 +20966.76628199871 + 32 +0.0 + 13 +32558.39544301086 + 23 +20966.76628199871 + 33 +0.0 + 0 +SOLID + 5 +171E +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +35887.68987109095 + 20 +24354.9862751907 + 30 +0.0 + 11 +35946.61543618994 + 21 +24296.06071009194 + 31 +0.0 + 12 +36093.92934893674 + 22 +24502.3001879383 + 32 +0.0 + 13 +36093.92934893674 + 23 +24502.3001879383 + 33 +0.0 + 0 +MTEXT + 5 +171F +330 +2AB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +34175.90220497137 + 20 +22884.79342597035 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 + 11 +0.707106781185177 + 21 +0.7071067811879182 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1720 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +32841.98269416671 + 20 +20683.17903084396 + 30 +0.0 + 0 +POINT + 5 +1721 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36377.51660009944 + 20 +24218.7129367767 + 30 +0.0 + 0 +POINT + 5 +1722 +330 +2AB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36093.92934893674 + 20 +24502.3001879383 + 30 +0.0 + 0 +ENDBLK + 5 +2B6 +330 +2AB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2C2 +330 +2B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D3 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D3 + 1 + + 0 +LINE + 5 +1723 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32797.78852034247 + 20 +20638.98485701989 + 30 +0.0 + 11 +32123.26971235923 + 21 +19964.46604903928 + 31 +0.0 + 0 +LINE + 5 +1724 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33858.4486921223 + 20 +19578.32468524007 + 30 +0.0 + 11 +33183.92988413701 + 21 +18903.8058772574 + 31 +0.0 + 0 +LINE + 5 +1725 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +32388.43475530402 + 20 +19876.07770139045 + 30 +0.0 + 11 +33095.5415364892 + 21 +19168.97092020253 + 31 +0.0 + 0 +SOLID + 5 +1726 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +32417.89753785351 + 20 +19905.54048393983 + 30 +0.0 + 11 +32358.97197275452 + 21 +19846.61491884107 + 31 +0.0 + 12 +32211.65806000772 + 22 +20052.85439668743 + 32 +0.0 + 13 +32211.65806000772 + 23 +20052.85439668743 + 33 +0.0 + 0 +SOLID + 5 +1727 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33125.0043190387 + 20 +19198.43370275191 + 30 +0.0 + 11 +33066.0787539397 + 21 +19139.50813765314 + 31 +0.0 + 12 +33272.3182317855 + 22 +18992.19422490555 + 32 +0.0 + 13 +33272.3182317855 + 23 +18992.19422490555 + 33 +0.0 + 0 +MTEXT + 5 +1728 +330 +2B8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32892.24833689904 + 20 +19672.78450179834 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.7071067811851766 + 21 +-0.7071067811879185 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1729 +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +32841.9826941667 + 20 +20683.17903084397 + 30 +0.0 + 0 +POINT + 5 +172A +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594654 + 20 +19622.51885906414 + 30 +0.0 + 0 +POINT + 5 +172B +330 +2B8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33272.3182317855 + 20 +18992.19422490555 + 30 +0.0 + 0 +ENDBLK + 5 +2C3 +330 +2B8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2D2 +330 +2C8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D4 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D4 + 1 + + 0 +LINE + 5 +172C +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34061.61755388569 + 20 +28525.65408367813 + 30 +0.0 + 11 +34061.61755388569 + 21 +28989.20702038776 + 31 +0.0 + 0 +LINE + 5 +172D +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39061.61755388569 + 20 +28525.65408367813 + 30 +0.0 + 11 +39061.61755388569 + 21 +28989.20702038776 + 31 +0.0 + 0 +LINE + 5 +172E +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34311.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 11 +38811.61755388569 + 21 +28864.20702038776 + 31 +0.0 + 0 +SOLID + 5 +172F +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34311.61755388569 + 20 +28905.87368705443 + 30 +0.0 + 11 +34311.61755388569 + 21 +28822.54035372109 + 31 +0.0 + 12 +34061.61755388569 + 22 +28864.20702038776 + 32 +0.0 + 13 +34061.61755388569 + 23 +28864.20702038776 + 33 +0.0 + 0 +SOLID + 5 +1730 +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +38811.61755388569 + 20 +28905.87368705443 + 30 +0.0 + 11 +38811.61755388569 + 21 +28822.54035372109 + 31 +0.0 + 12 +39061.61755388569 + 22 +28864.20702038776 + 32 +0.0 + 13 +39061.61755388569 + 23 +28864.20702038776 + 33 +0.0 + 0 +MTEXT + 5 +1731 +330 +2C8 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36561.61755388569 + 20 +29076.70702038776 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1732 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +1733 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +1734 +330 +2C8 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 0 +ENDBLK + 5 +2D3 +330 +2C8 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +2DE +330 +2D4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D5 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D5 + 1 + + 0 +LINE + 5 +1735 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33999.11755388569 + 20 +28463.15408367813 + 30 +0.0 + 11 +33045.20390755901 + 21 +28463.15408367813 + 31 +0.0 + 0 +LINE + 5 +1736 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33999.11755388569 + 20 +26963.15408367813 + 30 +0.0 + 11 +33045.20390755901 + 21 +26963.15408367813 + 31 +0.0 + 0 +LINE + 5 +1737 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33170.20390755901 + 20 +28213.15408367813 + 30 +0.0 + 11 +33170.20390755901 + 21 +27213.15408367813 + 31 +0.0 + 0 +SOLID + 5 +1738 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33128.53724089235 + 20 +28213.15408367813 + 30 +0.0 + 11 +33211.87057422568 + 21 +28213.15408367813 + 31 +0.0 + 12 +33170.20390755901 + 22 +28463.15408367813 + 32 +0.0 + 13 +33170.20390755901 + 23 +28463.15408367813 + 33 +0.0 + 0 +SOLID + 5 +1739 +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33128.53724089235 + 20 +27213.15408367813 + 30 +0.0 + 11 +33211.87057422568 + 21 +27213.15408367813 + 31 +0.0 + 12 +33170.20390755901 + 22 +26963.15408367813 + 32 +0.0 + 13 +33170.20390755901 + 23 +26963.15408367813 + 33 +0.0 + 0 +MTEXT + 5 +173A +330 +2D4 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32957.70390755901 + 20 +27713.15408367814 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +173B +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +173C +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +173D +330 +2D4 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33170.20390755901 + 20 +26963.15408367813 + 30 +0.0 + 0 +ENDBLK + 5 +2DF +330 +2D4 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +334 +330 +32A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D6 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D6 + 1 + + 0 +ARC + 5 +20B0 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbCircle + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 40 +3643.198465986115 +100 +AcDbArc + 50 +3.932466728467707 + 51 +41.06753327153231 + 0 +SOLID + 5 +20B1 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37578.90583846656 + 20 +19873.80126895147 + 30 +0.0 + 11 +37495.62157004181 + 21 +19870.94205972531 + 31 +0.0 + 12 +37545.84133193265 + 22 +19622.51885906415 + 32 +0.0 + 13 +37545.84133193265 + 23 +19622.51885906415 + 33 +0.0 + 0 +SOLID + 5 +20B2 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +36618.92420206274 + 20 +21987.47673559719 + 30 +0.0 + 11 +36679.83683926468 + 21 +22044.34584033384 + 31 +0.0 + 12 +36478.77320645374 + 22 +22198.64919957136 + 32 +0.0 + 13 +36478.77320645374 + 23 +22198.64919957136 + 33 +0.0 + 0 +MTEXT + 5 +20B3 +330 +32A +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37464.84376220628 + 20 +21098.03078219252 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +45‹ + 11 +0.3826834323650894 + 21 +-0.9238795325112869 + 31 +0.0 + 0 +POINT + 5 +20B4 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37421.70235453924 + 20 +20565.44800714964 + 30 +0.0 + 0 +POINT + 5 +20B5 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187928 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +20B6 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 0 +POINT + 5 +20B7 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37726.65216029227 + 20 +19622.51885906415 + 30 +0.0 + 0 +POINT + 5 +20B8 +330 +32A +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 0 +ENDBLK + 5 +335 +330 +32A +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +37A +330 +374 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D7 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D7 + 1 + + 0 +LINE + 5 +1747 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +18916.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +17291.48750671567 + 31 +0.0 + 0 +LINE + 5 +1748 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +12791.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +12541.48750671567 + 31 +0.0 + 0 +MTEXT + 5 +1749 +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +33759.21963608449 + 20 +18228.98750671567 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +\U+22054000 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +174A +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 11 +33971.7196360845 + 21 +17041.48750671567 + 31 +0.0 + 0 +SOLID + 5 +174B +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33930.05296941784 + 20 +12791.48750671567 + 30 +0.0 + 11 +34013.38630275116 + 21 +12791.48750671567 + 31 +0.0 + 12 +33971.7196360845 + 22 +13041.48750671567 + 32 +0.0 + 13 +33971.7196360845 + 23 +13041.48750671567 + 33 +0.0 + 0 +SOLID + 5 +174C +330 +374 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +33930.05296941784 + 20 +17291.48750671567 + 30 +0.0 + 11 +34013.38630275116 + 21 +17291.48750671567 + 31 +0.0 + 12 +33971.7196360845 + 22 +17041.48750671567 + 32 +0.0 + 13 +33971.7196360845 + 23 +17041.48750671567 + 33 +0.0 + 0 +POINT + 5 +174D +330 +374 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.7196360845 + 20 +17041.48750671567 + 30 +0.0 + 0 +POINT + 5 +174E +330 +374 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +37B +330 +374 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +384 +330 +37D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D8 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D8 + 1 + + 0 +LINE + 5 +174F +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37235.06246344516 + 20 +17131.03736041948 + 30 +0.0 + 11 +35866.56385842295 + 21 +16254.77451854369 + 31 +0.0 + 0 +MTEXT + 5 +1750 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36541.49406661355 + 20 +16939.26828335956 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +R2000 + 11 +0.8421529877059789 + 21 +0.539238671923568 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +1751 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 11 +35656.02561149646 + 21 +16119.9648505628 + 31 +0.0 + 0 +SOLID + 5 +1752 +330 +37D +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +35844.09558042614 + 20 +16289.86422636477 + 30 +0.0 + 11 +35889.03213641976 + 21 +16219.6848107226 + 31 +0.0 + 12 +35656.02561149646 + 22 +16119.9648505628 + 32 +0.0 + 13 +35656.02561149646 + 23 +16119.9648505628 + 33 +0.0 + 0 +POINT + 5 +1753 +330 +37D +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35656.02561149646 + 20 +16119.9648505628 + 30 +0.0 + 0 +POINT + 5 +1754 +330 +37D +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 0 +ENDBLK + 5 +385 +330 +37D +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +745 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +NONAME + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +NONAME + 1 + + 0 +LINE + 5 +747 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +5012.492533892546 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.619552814738 + 31 +0.0 + 0 +LINE + 5 +748 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +5012.492533892546 + 30 +0.0 + 11 +19339.43845972023 + 21 +5012.492533892547 + 31 +0.0 + 0 +LINE + 5 +749 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +24339.43845972023 + 21 +8260.087798084191 + 31 +0.0 + 0 +LINE + 5 +74A +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.960779162 + 31 +0.0 + 0 +LINE + 5 +74B +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24339.43845972023 + 20 +8260.087798084191 + 30 +0.0 + 11 +21839.43845972023 + 21 +3929.960779162 + 31 +0.0 + 0 +LINE + 5 +74C +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19339.43845972023 + 20 +5012.492533892547 + 30 +0.0 + 11 +21839.43845972023 + 21 +9342.619552814738 + 31 +0.0 + 0 +ENDBLK + 5 +746 +330 +744 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +760 +330 +756 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D10 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D10 + 1 + + 0 +LINE + 5 +1755 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +834.8316700276482 + 20 +3454.385493772555 + 30 +0.0 + 11 +834.8316700276482 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1756 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1757 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +1084.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +3084.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +SOLID + 5 +1758 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +1084.831670027648 + 20 +4365.021566317238 + 30 +0.0 + 11 +1084.831670027648 + 21 +4281.688232983904 + 31 +0.0 + 12 +834.8316700276482 + 22 +4323.35489965057 + 32 +0.0 + 13 +834.8316700276482 + 23 +4323.35489965057 + 33 +0.0 + 0 +SOLID + 5 +1759 +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +3084.831670027648 + 20 +4365.021566317238 + 30 +0.0 + 11 +3084.831670027648 + 21 +4281.688232983904 + 31 +0.0 + 12 +3334.831670027648 + 22 +4323.35489965057 + 32 +0.0 + 13 +3334.831670027648 + 23 +4323.35489965057 + 33 +0.0 + 0 +MTEXT + 5 +175A +330 +756 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +2084.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +175B +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +834.8316700276482 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175C +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +175D +330 +756 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +761 +330 +756 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +7D0 +330 +7CC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSEDBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSEDBLANK + 1 + + 0 +LINE + 5 +7CD +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +7CE +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +7CF +330 +7CC +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +ENDBLK + 5 +7D1 +330 +7CC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +80C +330 +802 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D12 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D12 + 1 + + 0 +LINE + 5 +175E +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +3334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +175F +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +5834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1760 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3584.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +5584.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1761 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSEDBLANK + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1762 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSEDBLANK + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1763 +330 +802 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +4584.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1764 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1765 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1766 +330 +802 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +80D +330 +802 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +825 +330 +820 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_CLOSED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_CLOSED + 1 + + 0 +LINE + 5 +821 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +822 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +823 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +-1.0 + 21 +-0.1666666666666666 + 31 +0.0 + 0 +LINE + 5 +824 +330 +820 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +826 +330 +820 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +848 +330 +83E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D14 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D14 + 1 + + 0 +LINE + 5 +1767 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +5834.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +5834.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1768 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1769 +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6084.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +8084.831670027648 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +176A +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSED + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +176B +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_CLOSED + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +176C +330 +83E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +7084.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +176D +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +5834.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176E +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +176F +330 +83E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +849 +330 +83E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +871 +330 +867 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D15 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D15 + 1 + + 0 +LINE + 5 +1770 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8334.831670027648 + 20 +3454.385493772555 + 30 +0.0 + 11 +8334.831670027648 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1771 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1772 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8584.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +10584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1773 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOT + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1774 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOT + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1775 +330 +867 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +9584.831670027648 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1776 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8334.831670027648 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1777 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1778 +330 +867 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +872 +330 +867 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +87F +330 +87C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOT + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOT + 1 + + 0 +LWPOLYLINE + 5 +87D +330 +87C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbPolyline + 90 + 2 + 70 + 1 + 43 +0.5 + 10 +-0.25 + 20 +0.0 + 42 +1.0 + 10 +0.25 + 20 +0.0 + 42 +1.0 + 0 +LINE + 5 +87E +330 +87C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +880 +330 +87C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8A8 +330 +89E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D17 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D17 + 1 + + 0 +LINE + 5 +1779 +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +10834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +177A +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +177B +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +13334.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +177C +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ARCHTICK + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +177D +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ARCHTICK + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +177E +330 +89E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +12084.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +177F +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +10834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1780 +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1781 +330 +89E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +8A9 +330 +89E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8B5 +330 +8B3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ARCHTICK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ARCHTICK + 1 + + 0 +LWPOLYLINE + 5 +8B4 +330 +8B3 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbPolyline + 90 + 2 + 70 + 0 + 43 +0.15 + 10 +-0.5 + 20 +-0.5 + 10 +0.5 + 20 +0.5 + 0 +ENDBLK + 5 +8B6 +330 +8B3 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8D5 +330 +8CB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D19 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D19 + 1 + + 0 +LINE + 5 +1782 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +13334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1783 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +15834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1784 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +15834.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1785 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OBLIQUE + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1786 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OBLIQUE + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1787 +330 +8CB +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +14584.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1788 +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1789 +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +178A +330 +8CB +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +8D6 +330 +8CB +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +8E2 +330 +8E0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OBLIQUE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OBLIQUE + 1 + + 0 +LINE + 5 +8E1 +330 +8E0 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +ENDBLK + 5 +8E3 +330 +8E0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +903 +330 +8F9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D21 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D21 + 1 + + 0 +LINE + 5 +178B +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +15834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +15834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +178C +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +178D +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16084.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +18084.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +178E +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +178F +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1790 +330 +8F9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +17084.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1791 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +15834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1792 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +1793 +330 +8F9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +904 +330 +8F9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +912 +330 +90E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN + 1 + + 0 +LINE + 5 +90F +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +910 +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +-0.1666666666666666 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +911 +330 +90E +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +913 +330 +90E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +93B +330 +931 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D23 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D23 + 1 + + 0 +LINE + 5 +1794 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18334.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +18334.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1795 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +20834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +1796 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18584.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +20584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +1797 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1798 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1799 +330 +931 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +19584.83167002764 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +179A +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +18334.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179B +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +179C +330 +931 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +93C +330 +931 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +949 +330 +946 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ORIGIN + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN + 1 + + 0 +CIRCLE + 5 +947 +330 +946 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +948 +330 +946 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +94A +330 +946 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +989 +330 +97F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D25 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D25 + 1 + + 0 +LINE + 5 +179D +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +20834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +20834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +179E +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +179F +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +21084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +23084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17A0 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN2 + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17A1 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_ORIGIN2 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17A2 +330 +97F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +22084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17A3 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +20834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A4 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17A5 +330 +97F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +98A +330 +97F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +998 +330 +994 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_ORIGIN2 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_ORIGIN2 + 1 + + 0 +CIRCLE + 5 +995 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +CIRCLE + 5 +996 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +LINE + 5 +997 +330 +994 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +999 +330 +994 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9CF +330 +9C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D27 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D27 + 1 + + 0 +LINE + 5 +17A6 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +23334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17A7 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17A8 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23584.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +25584.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17A9 +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN90 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17AA +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN90 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17AB +330 +9C5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +24584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17AC +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AD +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17AE +330 +9C5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +9D0 +330 +9C5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +9DE +330 +9DA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN90 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN90 + 1 + + 0 +LINE + 5 +9DB +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +9DC +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +9DD +330 +9DA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +9DF +330 +9DA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +ABB +330 +AB1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D29 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D29 + 1 + + 0 +LINE + 5 +17AF +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +25834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B0 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B1 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +26084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +28084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17B2 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17B3 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17B4 +330 +AB1 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +27084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17B5 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B6 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17B7 +330 +AB1 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +ABC +330 +AB1 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +ACA +330 +AC6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_OPEN30 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_OPEN30 + 1 + + 0 +LINE + 5 +AC7 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.26794919 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +AC8 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +-0.26794919 + 31 +0.0 + 0 +LINE + 5 +AC9 +330 +AC6 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +ACB +330 +AC6 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +AF3 +330 +AE9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D31 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D31 + 1 + + 0 +LINE + 5 +17B8 +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +28334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17B9 +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +30834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17BA +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +30834.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17BB +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTSMALL + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17BC +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTSMALL + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17BD +330 +AE9 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +29584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17BE +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +28334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17BF +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C0 +330 +AE9 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +AF4 +330 +AE9 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B00 +330 +AFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOTSMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTSMALL + 1 + + 0 +LWPOLYLINE + 5 +AFF +330 +AFE +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbPolyline + 90 + 2 + 70 + 1 + 43 +0.5 + 10 +-0.0625 + 20 +0.0 + 42 +1.0 + 10 +0.0625 + 20 +0.0 + 42 +1.0 + 0 +ENDBLK + 5 +B01 +330 +AFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B29 +330 +B1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D33 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D33 + 1 + + 0 +LINE + 5 +17C1 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +30834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +30834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17C2 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17C3 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +31084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +33084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17C4 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTBLANK + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17C5 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DOTBLANK + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17C6 +330 +B1F +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +32084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17C7 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +30834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C8 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17C9 +330 +B1F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B2A +330 +B1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B37 +330 +B34 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DOTBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DOTBLANK + 1 + + 0 +CIRCLE + 5 +B35 +330 +B34 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.5 + 0 +LINE + 5 +B36 +330 +B34 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +B38 +330 +B34 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B61 +330 +B57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D35 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D35 + 1 + + 0 +LINE + 5 +17CA +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +33334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17CB +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +35834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17CC +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +35834.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17CD +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_SMALL + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17CE +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_SMALL + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17CF +330 +B57 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +34584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17D0 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D1 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17D2 +330 +B57 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B62 +330 +B57 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B6E +330 +B6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_SMALL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_SMALL + 1 + + 0 +CIRCLE + 5 +B6D +330 +B6C +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +0.25 + 0 +ENDBLK + 5 +B6F +330 +B6C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B8E +330 +B84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D37 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D37 + 1 + + 0 +LINE + 5 +17D3 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +35834.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +35834.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17D4 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17D5 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36084.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +38084.83167002764 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17D6 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXBLANK + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17D7 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXBLANK + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17D8 +330 +B84 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37084.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17D9 +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +35834.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DA +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17DB +330 +B84 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +B8F +330 +B84 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +B9F +330 +B99 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_BOXBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXBLANK + 1 + + 0 +LINE + 5 +B9A +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9B +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.5 + 20 +-0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9C +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +0.5 + 31 +0.0 + 0 +LINE + 5 +B9D +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +-0.5 + 21 +-0.5 + 31 +0.0 + 0 +LINE + 5 +B9E +330 +B99 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +BA0 +330 +B99 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E70 +330 +E66 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D39 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D39 + 1 + + 0 +LINE + 5 +17DC +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38334.83167002765 + 20 +3454.385493772555 + 30 +0.0 + 11 +38334.83167002765 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17DD +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +40834.83167002764 + 20 +3454.385493772555 + 30 +0.0 + 11 +40834.83167002764 + 21 +4448.35489965057 + 31 +0.0 + 0 +LINE + 5 +17DE +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +38584.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +40584.83167002765 + 21 +4323.35489965057 + 31 +0.0 + 0 +INSERT + 5 +17DF +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXFILLED + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +17E0 +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_BOXFILLED + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +17E1 +330 +E66 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +39584.83167002765 + 20 +4535.85489965057 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +17E2 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38334.83167002765 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E3 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +40834.83167002764 + 20 +3391.885493772555 + 30 +0.0 + 0 +POINT + 5 +17E4 +330 +E66 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 0 +ENDBLK + 5 +E71 +330 +E66 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E7E +330 +E7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_BOXFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_BOXFILLED + 1 + + 0 +SOLID + 5 +E7C +330 +E7B +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbTrace + 10 +-0.5 + 20 +0.5 + 30 +0.0 + 11 +0.5 + 21 +0.5 + 31 +0.0 + 12 +-0.5 + 22 +-0.5 + 32 +0.0 + 13 +0.5 + 23 +-0.5 + 33 +0.0 + 0 +LINE + 5 +E7D +330 +E7B +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-0.5 + 20 +0.0 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +E7F +330 +E7B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +E9F +330 +E95 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D41 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D41 + 1 + + 0 +LINE + 5 +1DBB +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +3874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +3874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBC +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6374.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +6374.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DBD +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +4124.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +6124.072001619017 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DBE +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMBLANK + 10 +3874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DBF +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMBLANK + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DC0 +330 +E95 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +5124.072001619017 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DC1 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +3874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC2 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC3 +330 +E95 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +EA0 +330 +E95 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +EAE +330 +EAA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DATUMBLANK + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMBLANK + 1 + + 0 +LINE + 5 +EAB +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +EAC +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +-1.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +-0.5773502700000001 + 31 +0.0 + 0 +LINE + 5 +EAD +330 +EAA +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbLine + 10 +0.0 + 20 +-0.5773502700000001 + 30 +0.0 + 11 +0.0 + 21 +0.5773502700000001 + 31 +0.0 + 0 +ENDBLK + 5 +EAF +330 +EAA +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +F8C +330 +F82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D43 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D43 + 1 + + 0 +LINE + 5 +1DD4 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6374.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +6374.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD5 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +8874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DD6 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +6624.072001619016 + 20 +1663.887067986979 + 30 +0.0 + 11 +8624.072001619017 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DD7 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMFILLED + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DD8 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_DATUMFILLED + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DD9 +330 +F82 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +7624.072001619016 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DDA +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +6374.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DDB +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DDC +330 +F82 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +F8D +330 +F82 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +F99 +330 +F97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_DATUMFILLED + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_DATUMFILLED + 1 + + 0 +SOLID + 5 +F98 +330 +F97 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbTrace + 10 +0.0 + 20 +0.5773502700000001 + 30 +0.0 + 11 +-1.0 + 21 +0.0 + 31 +0.0 + 12 +0.0 + 22 +-0.5773502700000001 + 32 +0.0 + 13 +0.0 + 23 +-0.5773502700000001 + 33 +0.0 + 0 +ENDBLK + 5 +F9A +330 +F97 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +115A +330 +1150 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D45 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D45 + 1 + + 0 +LINE + 5 +1DCB +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +794.9176621089645 + 30 +0.0 + 11 +8874.072001619017 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCC +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DCD +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +11374.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DCE +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_INTEGRAL + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DCF +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_INTEGRAL + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DD0 +330 +1150 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +10124.07200161901 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DD1 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +8874.072001619017 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DD2 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DD3 +330 +1150 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +115B +330 +1150 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1168 +330 +1165 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_INTEGRAL + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_INTEGRAL + 1 + + 0 +ARC + 5 +1166 +330 +1165 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +0.44488802 + 20 +-0.09133463 + 30 +0.0 + 40 +0.4541666700000001 +100 +AcDbArc + 50 +101.9999999980395 + 51 +167.9999999799193 + 0 +ARC + 5 +1167 +330 +1165 +100 +AcDbEntity + 8 +0 + 6 +BYBLOCK + 62 + 0 +100 +AcDbCircle + 10 +-0.44488802 + 20 +0.09133463 + 30 +0.0 + 40 +0.4541666700000001 +100 +AcDbArc + 50 +282.0000000215427 + 51 +348.0000000034225 + 0 +ENDBLK + 5 +1169 +330 +1165 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1188 +330 +117E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D47 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D47 + 1 + + 0 +LINE + 5 +1DC4 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +11374.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC5 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +13874.07200161901 + 20 +794.9176621089645 + 30 +0.0 + 11 +13874.07200161901 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DC6 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +13874.07200161901 + 21 +1663.887067986979 + 31 +0.0 + 0 +MTEXT + 5 +1DC7 +330 +117E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +12624.07200161901 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +2500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DC8 +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +11374.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DC9 +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13874.07200161901 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DCA +330 +117E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1189 +330 +117E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1194 +330 +1193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +_NONE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +_NONE + 1 + + 0 +ENDBLK + 5 +1195 +330 +1193 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +13FD +330 +13F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D49 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D49 + 1 + + 0 +LINE + 5 +1DDD +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +14608.82612140059 + 20 +794.9176621089645 + 30 +0.0 + 11 +14608.82612140059 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDE +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16108.82612140059 + 20 +794.9176621089645 + 30 +0.0 + 11 +16108.82612140059 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DDF +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +14858.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +15858.82612140059 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DE0 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +17383.82612140059 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DE1 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +14608.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +INSERT + 5 +1DE2 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +MTEXT + 5 +1DE3 +330 +13F5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +16871.32612140059 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DE4 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +14608.82612140059 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DE5 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +16108.82612140059 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DE6 +330 +13F5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +13FE +330 +13F5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1487 +330 +147C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D50 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D50 + 1 + + 0 +LINE + 5 +1DB0 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19054.68096413649 + 20 +794.9176621089645 + 30 +0.0 + 11 +19054.68096413649 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB1 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19554.68096413649 + 20 +794.9176621089645 + 30 +0.0 + 11 +19554.68096413649 + 21 +1788.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB2 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +18804.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +18554.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB3 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19804.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +20879.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +LINE + 5 +1DB4 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +19054.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +19554.68096413649 + 21 +1663.887067986979 + 31 +0.0 + 0 +INSERT + 5 +1DB5 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +19054.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 0 +INSERT + 5 +1DB6 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbBlockReference + 2 +_OPEN30 + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 41 +250.0 + 42 +250.0 + 43 +250.0 + 50 +180.0 + 0 +MTEXT + 5 +1DB7 +330 +147C +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +20467.18096413649 + 20 +1876.387067986979 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +500 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DB8 +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19054.68096413649 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DB9 +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19554.68096413649 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1DBA +330 +147C +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 0 +ENDBLK + 5 +1488 +330 +147C +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1576 +330 +156E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D51 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D51 + 1 + + 0 +LINE + 5 +1F3A +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +21971.23629970006 + 20 +1700.0 + 30 +0.0 + 11 +22602.86068322082 + 21 +1700.0 + 31 +0.0 + 0 +LINE + 5 +1F3B +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +22602.86068322082 + 20 +1700.0 + 30 +0.0 + 11 +22607.86068322081 + 21 +731.2827575619594 + 31 +0.0 + 0 +LINE + 5 +1F3C +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +22607.86068322081 + 20 +731.2827575619594 + 30 +0.0 + 11 +24313.48568322081 + 21 +731.2827575619594 + 31 +0.0 + 0 +MTEXT + 5 +1F3D +330 +156E +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +23463.48568322081 + 20 +881.9077575619594 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1638.24 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F3E +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +21970.61129970006 + 20 +1700.0 + 30 +0.0 + 0 +POINT + 5 +1F3F +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +22612.86068322081 + 20 +731.2827575619594 + 30 +0.0 + 0 +POINT + 5 +1F40 +330 +156E +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +51.46025101292298 + 20 +61.75531173110096 + 30 +0.0 + 0 +ENDBLK + 5 +1577 +330 +156E +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +15AB +330 +15A5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D52 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D52 + 1 + + 0 +LINE + 5 +1DF5 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23925.7403567024 + 20 +682.5615222854612 + 30 +0.0 + 11 +23925.7403567024 + 21 +1624.772405628799 + 31 +0.0 + 0 +LINE + 5 +1DF6 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +23925.7403567024 + 20 +1624.772405628799 + 30 +0.0 + 11 +25157.97004022932 + 21 +1629.772405628798 + 31 +0.0 + 0 +LINE + 5 +1DF7 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +25157.97004022932 + 20 +1629.772405628798 + 30 +0.0 + 11 +25157.97004022932 + 21 +3735.397405628798 + 31 +0.0 + 0 +MTEXT + 5 +1DF8 +330 +15A5 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +25007.34504022932 + 20 +2685.397405628803 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +26524.29 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1DF9 +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +23925.7403567024 + 20 +681.9365222854612 + 30 +0.0 + 0 +POINT + 5 +1DFA +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25157.97004022932 + 20 +1634.772405628799 + 30 +0.0 + 0 +POINT + 5 +1DFB +330 +15A5 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +-2598.548049632634 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +15AC +330 +15A5 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +168D +330 +1683 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D53 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D53 + 1 + + 0 +LINE + 5 +181C +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +33946.83703977069 + 20 +19578.32468523999 + 30 +0.0 + 11 +34632.08713513241 + 21 +18893.07458987827 + 31 +0.0 + 0 +LINE + 5 +181D +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37482.37094570343 + 20 +23113.85859117272 + 30 +0.0 + 11 +38167.62104106515 + 21 +22428.608495811 + 31 +0.0 + 0 +LINE + 5 +181E +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34720.47548278073 + 20 +19158.23963282322 + 30 +0.0 + 11 +37902.45599812019 + 21 +22340.22014816269 + 31 +0.0 + 0 +SOLID + 5 +181F +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34691.01270023129 + 20 +19187.70241537266 + 30 +0.0 + 11 +34749.93826533017 + 21 +19128.77685027378 + 31 +0.0 + 12 +34543.6987874841 + 22 +18981.46293752658 + 32 +0.0 + 13 +34543.6987874841 + 23 +18981.46293752658 + 33 +0.0 + 0 +SOLID + 5 +1820 +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37872.99321557076 + 20 +22369.68293071213 + 30 +0.0 + 11 +37931.91878066964 + 21 +22310.75736561325 + 31 +0.0 + 12 +38079.23269341683 + 22 +22516.99684345932 + 32 +0.0 + 13 +38079.23269341683 + 23 +22516.99684345932 + 33 +0.0 + 0 +MTEXT + 5 +1821 +330 +1683 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36161.20554944833 + 20 +20899.49008149508 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 + 11 +0.7071067811865476 + 21 +0.7071067811865475 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1822 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +33902.64286594653 + 20 +19622.51885906415 + 30 +0.0 + 0 +POINT + 5 +1823 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187927 + 20 +23158.05276499689 + 30 +0.0 + 0 +POINT + 5 +1824 +330 +1683 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38079.23269341683 + 20 +22516.99684345932 + 30 +0.0 + 0 +ENDBLK + 5 +168E +330 +1683 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +169A +330 +1690 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D54 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D54 + 1 + + 0 +LINE + 5 +1825 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +36421.71077392361 + 20 +24262.90711060086 + 30 +0.0 + 11 +37033.39610829522 + 21 +24874.59244497247 + 31 +0.0 + 0 +LINE + 5 +1826 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37482.37094570343 + 20 +23202.24693882104 + 30 +0.0 + 11 +38094.05628007504 + 21 +23813.93227319265 + 31 +0.0 + 0 +LINE + 5 +1827 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +37121.78445594354 + 20 +24609.42740202752 + 30 +0.0 + 11 +37828.89123713009 + 21 +23902.32062084097 + 31 +0.0 + 0 +SOLID + 5 +1828 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37151.24723849298 + 20 +24638.89018457695 + 30 +0.0 + 11 +37092.3216733941 + 21 +24579.96461947808 + 31 +0.0 + 12 +36945.0077606469 + 22 +24786.20409732415 + 32 +0.0 + 13 +36945.0077606469 + 23 +24786.20409732415 + 33 +0.0 + 0 +SOLID + 5 +1829 +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +37858.35401967953 + 20 +23931.7834033904 + 30 +0.0 + 11 +37799.42845458065 + 21 +23872.85783829153 + 31 +0.0 + 12 +38005.66793242672 + 22 +23725.54392554433 + 32 +0.0 + 13 +38005.66793242672 + 23 +23725.54392554433 + 33 +0.0 + 0 +MTEXT + 5 +182A +330 +1690 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +37625.59803753895 + 20 +24406.13420243639 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.7071067811865476 + 21 +-0.7071067811865475 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +182B +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +36377.51660009945 + 20 +24218.7129367767 + 30 +0.0 + 0 +POINT + 5 +182C +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +37438.17677187927 + 20 +23158.05276499688 + 30 +0.0 + 0 +POINT + 5 +182D +330 +1690 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +38005.66793242672 + 20 +23725.54392554433 + 30 +0.0 + 0 +ENDBLK + 5 +169B +330 +1690 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +16BA +330 +16B0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D55 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D55 + 1 + + 0 +LINE + 5 +182E +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34061.61755388569 + 20 +26900.65408367813 + 30 +0.0 + 11 +34061.61755388569 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +182F +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39061.61755388569 + 20 +26900.65408367813 + 30 +0.0 + 11 +39061.61755388569 + 21 +25931.56410520013 + 31 +0.0 + 0 +LINE + 5 +1830 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +34311.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 11 +38811.61755388569 + 21 +26056.56410520013 + 31 +0.0 + 0 +SOLID + 5 +1831 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +34311.61755388569 + 20 +26098.23077186679 + 30 +0.0 + 11 +34311.61755388569 + 21 +26014.89743853346 + 31 +0.0 + 12 +34061.61755388569 + 22 +26056.56410520013 + 32 +0.0 + 13 +34061.61755388569 + 23 +26056.56410520013 + 33 +0.0 + 0 +SOLID + 5 +1832 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +38811.61755388569 + 20 +26098.23077186679 + 30 +0.0 + 11 +38811.61755388569 + 21 +26014.89743853346 + 31 +0.0 + 12 +39061.61755388569 + 22 +26056.56410520013 + 32 +0.0 + 13 +39061.61755388569 + 23 +26056.56410520013 + 33 +0.0 + 0 +MTEXT + 5 +1833 +330 +16B0 +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +36561.61755388569 + 20 +26269.06410520013 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +5000 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1834 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +34061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +1835 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +1836 +330 +16B0 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 0 +ENDBLK + 5 +16BB +330 +16B0 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +16C6 +330 +16BC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D56 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D56 + 1 + + 0 +LINE + 5 +1837 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39124.11755388569 + 20 +28463.15408367813 + 30 +0.0 + 11 +39989.17124965874 + 21 +28463.15408367813 + 31 +0.0 + 0 +LINE + 5 +1838 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39124.11755388569 + 20 +26963.15408367813 + 30 +0.0 + 11 +39989.17124965874 + 21 +26963.15408367813 + 31 +0.0 + 0 +LINE + 5 +1839 +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbLine + 10 +39864.17124965874 + 20 +28213.15408367813 + 30 +0.0 + 11 +39864.17124965874 + 21 +27213.15408367813 + 31 +0.0 + 0 +SOLID + 5 +183A +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +39822.50458299207 + 20 +28213.15408367813 + 30 +0.0 + 11 +39905.8379163254 + 21 +28213.15408367813 + 31 +0.0 + 12 +39864.17124965874 + 22 +28463.15408367813 + 32 +0.0 + 13 +39864.17124965874 + 23 +28463.15408367813 + 33 +0.0 + 0 +SOLID + 5 +183B +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbTrace + 10 +39822.50458299207 + 20 +27213.15408367813 + 30 +0.0 + 11 +39905.8379163254 + 21 +27213.15408367813 + 31 +0.0 + 12 +39864.17124965874 + 22 +26963.15408367813 + 32 +0.0 + 13 +39864.17124965874 + 23 +26963.15408367813 + 33 +0.0 + 0 +MTEXT + 5 +183C +330 +16BC +100 +AcDbEntity + 8 +0 + 62 + 0 +100 +AcDbMText + 10 +39651.67124965873 + 20 +27713.15408367814 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +1500 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +183D +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +28463.15408367813 + 30 +0.0 + 0 +POINT + 5 +183E +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39061.61755388569 + 20 +26963.15408367813 + 30 +0.0 + 0 +POINT + 5 +183F +330 +16BC +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +39864.17124965874 + 20 +26963.15408367813 + 30 +0.0 + 0 +ENDBLK + 5 +16C7 +330 +16BC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E04 +330 +1DFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D57 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D57 + 1 + + 0 +LINE + 5 +1E06 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24000.0 + 20 +703.9890086830564 + 30 +0.0 + 11 +24000.0 + 21 +1656.774842974453 + 31 +0.0 + 0 +LINE + 5 +1E07 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24000.0 + 20 +1656.774842974453 + 30 +0.0 + 11 +24978.46253739796 + 21 +1661.774842974453 + 31 +0.0 + 0 +LINE + 5 +1E08 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +24978.46253739796 + 20 +1661.774842974453 + 30 +0.0 + 11 +24978.46253739796 + 21 +2917.399842974453 + 31 +0.0 + 0 +MTEXT + 5 +1E09 +330 +1DFE +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +24827.83753739796 + 20 +2292.399842974457 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +24000 + 11 +0.0000000000000001 + 21 +1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1E0A +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +24000.0 + 20 +703.3640086830565 + 30 +0.0 + 0 +POINT + 5 +1E0B +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +24978.46253739796 + 20 +1666.774842974453 + 30 +0.0 + 0 +POINT + 5 +1E0C +330 +1DFE +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1E05 +330 +1DFE +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1E1A +330 +1E0F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D58 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D58 + 1 + + 0 +LINE + 5 +1F20 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +25446.29486998995 + 20 +794.9176621089645 + 30 +0.0 + 11 +25446.29486998995 + 21 +1778.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F21 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +26446.29486998995 + 20 +794.9176621089645 + 30 +0.0 + 11 +26446.29486998995 + 21 +1778.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F22 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +25696.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +26196.29486998996 + 21 +1653.666411913524 + 31 +0.0 + 0 +LINE + 5 +1F23 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +28171.29486998995 + 21 +1653.666411913524 + 31 +0.0 + 0 +SOLID + 5 +1F24 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbTrace + 10 +25696.29486998995 + 20 +1695.33307858019 + 30 +0.0 + 11 +25696.29486998995 + 21 +1611.999745246857 + 31 +0.0 + 12 +25446.29486998995 + 22 +1653.666411913524 + 32 +0.0 + 13 +25446.29486998995 + 23 +1653.666411913524 + 33 +0.0 + 0 +SOLID + 5 +1F25 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbTrace + 10 +26196.29486998996 + 20 +1695.33307858019 + 30 +0.0 + 11 +26196.29486998996 + 21 +1611.999745246857 + 31 +0.0 + 12 +26446.29486998995 + 22 +1653.666411913524 + 32 +0.0 + 13 +26446.29486998995 + 23 +1653.666411913524 + 33 +0.0 + 0 +MTEXT + 5 +1F26 +330 +1E0F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +27433.79486998995 + 20 +1866.166411913523 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +<1000> +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F27 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +25446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1F28 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +26446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 0 +POINT + 5 +1F29 +330 +1E0F +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 0 +ENDBLK + 5 +1E1B +330 +1E0F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1F5B +330 +1F55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*D59 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*D59 + 1 + + 0 +LINE + 5 +1F64 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +21762.53289325554 + 20 +700.0 + 30 +0.0 + 11 +22509.7024027464 + 21 +700.0 + 31 +0.0 + 0 +LINE + 5 +1F65 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +22509.7024027464 + 20 +700.0 + 30 +0.0 + 11 +22514.7024027464 + 21 +1660.401028986984 + 31 +0.0 + 0 +LINE + 5 +1F66 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbLine + 10 +22514.7024027464 + 20 +1660.401028986984 + 30 +0.0 + 11 +23220.3274027464 + 21 +1660.401028986984 + 31 +0.0 + 0 +MTEXT + 5 +1F67 +330 +1F55 +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbMText + 10 +22870.3274027464 + 20 +1811.026028986983 + 30 +0.0 + 40 +300.0 + 41 +0.0 + 71 + 5 + 72 + 1 + 1 +700 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +POINT + 5 +1F68 +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +21761.90789325554 + 20 +700.0 + 30 +0.0 + 0 +POINT + 5 +1F69 +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +22519.7024027464 + 20 +1660.401028986984 + 30 +0.0 + 0 +POINT + 5 +1F6A +330 +1F55 +100 +AcDbEntity + 8 +DEFPOINTS + 62 + 0 +100 +AcDbPoint + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +ENDBLK + 5 +1F5C +330 +1F55 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +16E +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0.0 + 10 +32841.98269416671 + 20 +20683.17903084397 + 10 +36377.51660009945 + 20 +24218.7129367767 + 10 +37438.17677187927 + 20 +23158.05276499688 + 10 +33902.64286594653 + 20 +19622.51885906414 + 0 +INSERT + 5 +170 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbBlockReference + 2 +*U1 + 10 +51.46025101292298 + 20 +61.75531173110096 + 30 +0.0 + 0 +TEXT + 5 +171 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS + 62 + 7 +100 +AcDbText + 10 +51.46025101292298 + 20 +61.75531173110096 + 30 +0.0 + 40 +1000.0 + 1 +A3 1/100 + 41 +0.5200000000000001 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +172 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +8032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +DOT + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +173 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +12032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +12032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +174 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(CONTINUOUS) + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +175 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +CONTINUOUS +100 +AcDbLine + 10 +834.8316700276482 + 20 +11032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +11032.86861556869 + 31 +0.0 + 0 +TEXT + 5 +176 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +CONTINUOUS + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +177 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +DASHDOT + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +178 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DASHDOT +100 +AcDbLine + 10 +834.8316700276482 + 20 +10032.86861556869 + 30 +0.0 + 11 +7734.450330124251 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +179 +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DIVIDE +100 +AcDbLine + 10 +834.8316700276482 + 20 +9032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +9032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +17A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +9032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +DIVIDE + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +17B +330 +1F +100 +AcDbEntity + 8 +1 + 6 +DOT +100 +AcDbLine + 10 +834.8316700276482 + 20 +8032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +8032.868615568695 + 31 +0.0 + 0 +LINE + 5 +17C +330 +1F +100 +AcDbEntity + 8 +1 + 6 +HIDDEN +100 +AcDbLine + 10 +834.8316700276482 + 20 +7032.868615568695 + 30 +0.0 + 11 +7734.450330124251 + 21 +7032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +17D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +7032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +HIDDEN + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +17E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15709.47494670215 + 20 +28715.17555215312 + 30 +0.0 + 11 +15709.47494670215 + 21 +24182.26996797447 + 31 +0.0 + 0 +LINE + 5 +17F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 11 +17116.41234094919 + 21 +24182.26996797447 + 31 +0.0 + 0 +MTEXT + 5 +180 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 41 +4532.9056 + 71 + 1 + 72 + 5 + 1 +‚Qs‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI4 + 11 +-0.0000000000000002 + 21 +-1.0 + 31 +0.0 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +181 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17116.41234094919 + 20 +28715.17555215312 + 30 +0.0 + 11 +15709.47494670215 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +182 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15709.47494670215 + 20 +24182.26996797447 + 30 +0.0 + 11 +17116.41234094919 + 21 +24182.26996797447 + 31 +0.0 + 0 +TEXT + 5 +183 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263391 + 20 +12032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +ByLayer(White/Black) + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +184 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 1 +100 +AcDbLine + 10 +8432.910636263391 + 20 +11032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +11032.86861556869 + 31 +0.0 + 0 +LINE + 5 +185 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263391 + 20 +12032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +12032.86861556869 + 31 +0.0 + 0 +LINE + 5 +186 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 2 +100 +AcDbLine + 10 +8432.910636263391 + 20 +10032.86861556869 + 30 +0.0 + 11 +15332.52929635998 + 21 +10032.86861556869 + 31 +0.0 + 0 +LINE + 5 +187 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 3 +100 +AcDbLine + 10 +8432.910636263391 + 20 +9032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +9032.868615568695 + 31 +0.0 + 0 +LINE + 5 +188 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 4 +100 +AcDbLine + 10 +8432.910636263391 + 20 +8032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +8032.868615568695 + 31 +0.0 + 0 +LINE + 5 +189 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 113 +100 +AcDbLine + 10 +8432.910636263391 + 20 +7032.868615568695 + 30 +0.0 + 11 +15332.52929635998 + 21 +7032.868615568695 + 31 +0.0 + 0 +TEXT + 5 +18A +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 2 +100 +AcDbText + 10 +8432.910636263391 + 20 +10032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Yellow + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18B +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 113 +100 +AcDbText + 10 +8432.910636263391 + 20 +7032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +ƒpƒŒƒbƒg113 + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18C +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 4 +100 +AcDbText + 10 +8432.910636263391 + 20 +8032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +Cyan + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18D +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 3 +100 +AcDbText + 10 +8432.910636263391 + 20 +9032.868615568695 + 30 +0.0 + 40 +500.0 + 1 +Green + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18E +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 1 +100 +AcDbText + 10 +8432.910636263391 + 20 +11032.86861556869 + 30 +0.0 + 40 +500.0 + 1 +Red + 7 +KANJI2 +100 +AcDbText + 0 +TEXT + 5 +18F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +26769.84838325862 + 21 +25791.31768413283 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +190 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +18739.86399912308 + 20 +23517.2060090059 + 30 +0.0 + 11 +18739.86399912308 + 21 +28715.17555215312 + 31 +0.0 + 0 +TEXT + 5 +191 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +192 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.2060090059 + 31 +0.0 + 0 +LINE + 5 +193 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +194 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19269.84838325863 + 21 +23517.2100800719 + 31 +0.0 + 0 +TEXT + 5 +195 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +19178.47782488299 + 21 +23517.20600900591 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +196 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 11 +20269.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +197 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +20769.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +TEXT + 5 +198 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +20269.84838325863 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +20178.47782488299 + 21 +25791.31768413282 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +199 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +19A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21769.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +19B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 50 +270.0 + 7 +KANJI4 + 11 +21178.47782488299 + 21 +28715.17555215312 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +19C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +19D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +TEXT + 5 +19E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +22269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +22519.84838325863 + 21 +22867.45981611252 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +19F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1A0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +TEXT + 5 +1A1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 1 + 11 +23519.84838325862 + 21 +26116.19078057952 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +1A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24769.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24269.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +TEXT + 5 +1A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 50 +270.0 + 7 +KANJI4 + 11 +24519.84838325862 + 21 +28715.17555215313 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +1A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +25269.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1A6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +25769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +TEXT + 5 +1A7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +25769.84838325863 + 21 +23517.20600900593 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +1A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1A9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +1AA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17739.86399912307 + 20 +28715.17555215312 + 30 +0.0 + 11 +18739.86399912307 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28715.17555215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28715.17555215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +28715.17555215312 + 31 +0.0 + 0 +LINE + 5 +1AE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1AF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28715.17555215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +28715.17555215313 + 31 +0.0 + 0 +LINE + 5 +1B1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +25769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +1B2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +1B3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1B4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +27415.68235215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +27415.68235215312 + 31 +0.0 + 0 +LINE + 5 +1B5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +26765.93575215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1B6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +26116.18915215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +26116.18915215312 + 31 +0.0 + 0 +LINE + 5 +1B7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325862 + 20 +25466.44255215312 + 30 +0.0 + 11 +19769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1B8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +27415.68235215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +27415.68235215312 + 31 +0.0 + 0 +LINE + 5 +1B9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +28065.42895215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1BA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +26765.93575215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +27415.68235215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1BC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +28065.42895215312 + 31 +0.0 + 0 +LINE + 5 +1BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +26765.93575215312 + 30 +0.0 + 11 +21769.84838325862 + 21 +26765.93575215312 + 31 +0.0 + 0 +LINE + 5 +1BE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +26116.18915215313 + 30 +0.0 + 11 +20769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +25466.44255215312 + 30 +0.0 + 11 +20769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +21769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +21769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +19269.84838325863 + 21 +24816.69839479271 + 31 +0.0 + 0 +LINE + 5 +1C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +19769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1C4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325864 + 20 +24166.95423743231 + 30 +0.0 + 11 +19269.84838325864 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +19769.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325864 + 20 +23517.2100800719 + 30 +0.0 + 11 +19269.84838325864 + 21 +23517.2100800719 + 31 +0.0 + 0 +LINE + 5 +1C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19269.84838325863 + 20 +23517.2100800719 + 30 +0.0 + 11 +19769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1C9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +20769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1CA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +20769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1CB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +20269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1CC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +20269.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1CD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +20769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1CE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +20269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1CF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +21769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +21769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +21269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1D2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +21269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1D3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +21769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1D4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +21269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1D5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325863 + 20 +22867.4659227115 + 30 +0.0 + 11 +20769.84838325863 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +1D6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20269.84838325864 + 20 +22867.4659227115 + 30 +0.0 + 11 +20269.84838325864 + 21 +22867.4659227115 + 31 +0.0 + 0 +LINE + 5 +1D7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1D8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1D9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325862 + 20 +28065.42895215313 + 30 +0.0 + 11 +24769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1DC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1DD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1DE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +28065.42895215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1DF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +27415.68235215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +28065.42895215312 + 30 +0.0 + 11 +22769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1E1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +26765.93575215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +26765.93575215313 + 31 +0.0 + 0 +LINE + 5 +1E2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +25466.44255215312 + 30 +0.0 + 11 +23769.84838325862 + 21 +25466.44255215312 + 31 +0.0 + 0 +LINE + 5 +1E3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +23769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1E4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +26116.18915215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1E5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +22769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1E6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +26765.93575215314 + 30 +0.0 + 11 +25769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +1E7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +27415.68235215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +27415.68235215313 + 31 +0.0 + 0 +LINE + 5 +1E8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +28065.42895215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +28065.42895215313 + 31 +0.0 + 0 +LINE + 5 +1E9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +1EA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +1EB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +1EC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +25466.44255215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1ED +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +26116.18915215313 + 30 +0.0 + 11 +25769.84838325862 + 21 +26116.18915215313 + 31 +0.0 + 0 +LINE + 5 +1EE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +26769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +1EF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325862 + 20 +25466.44255215313 + 30 +0.0 + 11 +26769.84838325862 + 21 +25466.44255215313 + 31 +0.0 + 0 +LINE + 5 +1F0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +22867.46592271151 + 30 +0.0 + 11 +24769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +1F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +24769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +24769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1F3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +24769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +23769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +1F5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +23769.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1F6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +23769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +22769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1F8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +22769.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1F9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +22269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +1FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +22269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +1FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325863 + 20 +24816.69839479271 + 30 +0.0 + 11 +23269.84838325863 + 21 +24816.69839479271 + 31 +0.0 + 0 +LINE + 5 +1FC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325864 + 20 +24166.95423743231 + 30 +0.0 + 11 +23269.84838325864 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +1FD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +22769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +22269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +1FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +23269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +200 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +24269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +201 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325863 + 20 +24166.95423743231 + 30 +0.0 + 11 +24269.84838325863 + 21 +24166.95423743231 + 31 +0.0 + 0 +LINE + 5 +202 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +24269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +203 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +22769.84838325863 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +204 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +22269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +205 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +24269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +206 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +25769.84838325863 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +207 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +25769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +208 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +25769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +209 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24816.69839479272 + 30 +0.0 + 11 +25269.84838325863 + 21 +24816.69839479272 + 31 +0.0 + 0 +LINE + 5 +20A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +25269.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +20B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +25269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +20C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +26269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +20D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +26769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +20E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +24166.95423743232 + 30 +0.0 + 11 +26269.84838325864 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +20F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +24166.95423743232 + 30 +0.0 + 11 +26769.84838325863 + 21 +24166.95423743232 + 31 +0.0 + 0 +LINE + 5 +210 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +23517.21008007191 + 30 +0.0 + 11 +26269.84838325864 + 21 +23517.21008007191 + 31 +0.0 + 0 +LINE + 5 +211 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325863 + 20 +23517.21008007191 + 30 +0.0 + 11 +26769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +212 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +26269.84838325864 + 21 +22867.46592271151 + 31 +0.0 + 0 +LINE + 5 +213 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26269.84838325864 + 20 +22867.46592271151 + 30 +0.0 + 11 +26769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +214 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +30269.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +215 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +30769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +TEXT + 5 +216 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +30269.84838325864 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 50 +270.0 + 41 +0.9000000000000005 + 7 +KANJI4 + 72 + 5 + 11 +30269.84838325864 + 21 +22867.45981611253 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +217 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +218 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +219 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 50 +270.0 + 7 +KANJI4 + 11 +27769.84838325862 + 21 +28715.17555215314 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +21A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +28263.50320559365 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 50 +270.0 + 7 +KANJI4 + 72 + 4 + 11 +28504.61995686268 + 21 +26116.19078057954 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +21B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +21C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +TEXT + 5 +21D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +29269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 50 +270.0 + 7 +KANJI4 + 72 + 2 + 11 +29269.84838325863 + 21 +22867.45981611253 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +21E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +21F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29269.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +220 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31769.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +TEXT + 5 +221 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 50 +270.0 + 7 +KANJI4 +100 +AcDbText + 0 +LINE + 5 +222 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +223 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +224 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +225 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +226 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +28715.17555215314 + 30 +0.0 + 11 +30769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +227 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28715.17555215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +28715.17555215314 + 31 +0.0 + 0 +LINE + 5 +228 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +229 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +22A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +22B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +31769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +22C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +22D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +31769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +22E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +22F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +230 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +231 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +232 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +233 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +234 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +235 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +27769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +236 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +237 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +28769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +238 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +27415.68235215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +27415.68235215314 + 31 +0.0 + 0 +LINE + 5 +239 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +28065.42895215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +28065.42895215314 + 31 +0.0 + 0 +LINE + 5 +23A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +26765.93575215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +26765.93575215314 + 31 +0.0 + 0 +LINE + 5 +23B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +26116.18915215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +26116.18915215314 + 31 +0.0 + 0 +LINE + 5 +23C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +25466.44255215314 + 30 +0.0 + 11 +29769.84838325862 + 21 +25466.44255215314 + 31 +0.0 + 0 +LINE + 5 +23D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +27769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +23E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +27769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +23F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +27269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +240 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +27269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +241 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +27769.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +242 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +27269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +243 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +28769.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +244 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +28769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +245 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +28269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +246 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +28269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +247 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +28769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +248 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28269.84838325864 + 20 +23517.21008007192 + 30 +0.0 + 11 +28269.84838325864 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +249 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +29769.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +24A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325862 + 20 +24816.69839479273 + 30 +0.0 + 11 +29769.84838325862 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +24B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +29269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +24C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +24166.95423743233 + 30 +0.0 + 11 +29269.84838325863 + 21 +24166.95423743233 + 31 +0.0 + 0 +LINE + 5 +24D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +29769.84838325863 + 21 +23517.21008007193 + 31 +0.0 + 0 +LINE + 5 +24E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +23517.21008007192 + 30 +0.0 + 11 +29269.84838325863 + 21 +23517.21008007192 + 31 +0.0 + 0 +LINE + 5 +24F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31269.84838325863 + 20 +24816.69839479273 + 30 +0.0 + 11 +31269.84838325863 + 21 +24816.69839479273 + 31 +0.0 + 0 +LINE + 5 +250 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325863 + 20 +22867.46592271152 + 30 +0.0 + 11 +30769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +251 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325863 + 20 +22867.46592271152 + 30 +0.0 + 11 +29769.84838325863 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +252 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29269.84838325864 + 20 +22867.46592271152 + 30 +0.0 + 11 +29269.84838325864 + 21 +22867.46592271152 + 31 +0.0 + 0 +LINE + 5 +253 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30269.84838325864 + 20 +22867.46592271152 + 30 +0.0 + 11 +30269.84838325864 + 21 +22867.46592271152 + 31 +0.0 + 0 +DIMENSION + 5 +2AA +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D2 + 10 +36093.92934893674 + 20 +24502.3001879383 + 30 +0.0 + 11 +34175.90220497137 + 21 +22884.79342597035 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +32841.98269416671 + 23 +20683.17903084397 + 33 +0.0 + 14 +36377.51660009945 + 24 +24218.7129367767 + 34 +0.0 + 50 +45.00000000011105 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +2B7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D3 + 10 +33272.3182317855 + 20 +18992.19422490555 + 30 +0.0 + 11 +32892.24833689904 + 21 +19672.78450179834 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +32841.98269416671 + 23 +20683.17903084397 + 33 +0.0 + 14 +33902.64286594653 + 24 +19622.51885906414 + 34 +0.0 + 50 +134.9999999998889 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +2C4 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33472.53829550178 + 20 +20318.35664042155 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +DIMENSION + 5 +2C5 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D4 + 10 +39061.61755388569 + 20 +28864.20702038776 + 30 +0.0 + 11 +36561.61755388569 + 21 +29076.70702038776 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +28463.15408367813 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LWPOLYLINE + 5 +2C6 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0.0 + 10 +34061.61755388569 + 20 +28463.15408367813 + 10 +39061.61755388569 + 20 +28463.15408367813 + 10 +39061.61755388569 + 20 +26963.15408367813 + 10 +34061.61755388569 + 20 +26963.15408367813 + 0 +DIMENSION + 5 +2C7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D5 + 10 +33170.20390755901 + 20 +26963.15408367813 + 30 +0.0 + 11 +32957.70390755901 + 21 +27713.15408367814 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +34061.61755388569 + 24 +26963.15408367813 + 34 +0.0 + 50 +90.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +328 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 11 +37726.65216029226 + 21 +19622.51885906414 + 31 +0.0 + 0 +DIMENSION + 5 +329 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D6 + 10 +33902.64286594653 + 20 +19622.51885906414 + 30 +0.0 + 11 +37464.84376220628 + 21 +21098.03078219252 + 31 +0.0 + 70 + 34 + 3 +ISO-25 +100 +AcDb2LineAngularDimension + 13 +33902.64286594653 + 23 +19622.51885906414 + 33 +0.0 + 14 +37726.65216029226 + 24 +19622.51885906414 + 34 +0.0 + 15 +37438.17677187927 + 25 +23158.05276499688 + 35 +0.0 + 16 +37421.70235453924 + 26 +20565.44800714964 + 36 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 271 +1070 + 0 +1070 + 271 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 79 +1070 + 2 +1070 + 271 +1070 + 0 +1002 +} + 0 +CIRCLE + 5 +371 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbCircle + 10 +33971.7196360845 + 20 +15041.48750671567 + 30 +0.0 + 40 +1808.760328193126 + 0 +DIMENSION + 5 +373 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D7 + 10 +33971.7196360845 + 20 +13041.48750671567 + 30 +0.0 + 11 +33759.21963608449 + 21 +18228.98750671567 + 31 +0.0 + 70 + 35 + 3 +ISO-25 +100 +AcDbDiametricDimension + 15 +33971.7196360845 + 25 +17041.48750671567 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +DIMENSION + 5 +37C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D8 + 10 +33971.71963608451 + 20 +15041.48750671567 + 30 +0.0 + 11 +36541.49406661355 + 21 +16939.26828335956 + 31 +0.0 + 70 + 36 + 3 +ISO-25 +100 +AcDbRadialDimension + 15 +35656.02561149646 + 25 +16119.9648505628 + 35 +0.0 + 40 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 288 +1070 + 1 +1002 +} + 0 +ELLIPSE + 5 +3A0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbEllipse + 10 +33971.7196360845 + 20 +15041.48750671567 + 30 +0.0 + 11 +1808.760328193126 + 21 +0.0000000000032901 + 31 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 40 +0.5528648458355768 + 41 +0.0 + 42 +6.283185307179586 + 0 +LINE + 5 +3EB +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +10886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3EC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +32162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3EE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +33162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +33162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3EF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +34162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +34162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 0 +LINE + 5 +3F1 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +9886.191051572176 + 30 +0.0 + 11 +40162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F2 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +35162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +35162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +36162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +36162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +37162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +37162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F5 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +38162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +38162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +40162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +40162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +LINE + 5 +3F8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +39162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 11 +39162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 0 +SPLINE + 5 +3FB +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbSpline +210 +0.0 +220 +0.0 +230 +1.0 + 70 + 8 + 71 + 3 + 72 + 15 + 73 + 11 + 74 + 9 + 42 +0.0000000001 + 43 +0.0000000001 + 44 +0.0000000001 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +0.0 + 40 +1414.213562373095 + 40 +2828.42712474619 + 40 +4242.640687119284 + 40 +5656.85424949238 + 40 +7071.067811865475 + 40 +8485.281374238573 + 40 +9899.494936611667 + 40 +11279.38235200375 + 40 +11279.38235200375 + 40 +11279.38235200375 + 40 +11279.38235200375 + 10 +32162.95930789137 + 20 +10886.19105157217 + 30 +0.0 + 10 +32496.29186790955 + 20 +11386.19109007647 + 30 +0.0 + 10 +33162.9569879459 + 20 +12386.19116708506 + 30 +0.0 + 10 +34162.96858767325 + 20 +10886.19058952059 + 30 +0.0 + 10 +35162.92450870933 + 20 +9386.192784265595 + 30 +0.0 + 10 +36163.08922483765 + 20 +10886.18458285008 + 30 +0.0 + 10 +37162.47443928828 + 20 +12386.21519376713 + 30 +0.0 + 10 +38164.76886535743 + 20 +10886.10095151444 + 30 +0.0 + 10 +39148.1844766345 + 20 +9398.659985702362 + 30 +0.0 + 10 +39827.48280742876 + 20 +10361.51438572329 + 30 +0.0 + 10 +40162.95930789137 + 20 +10837.0271463632 + 30 +0.0 + 11 +32162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +33162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 11 +34162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +35162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 11 +36162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +37162.95930789137 + 21 +11886.19105157217 + 31 +0.0 + 11 +38162.95930789137 + 21 +10886.19105157217 + 31 +0.0 + 11 +39162.95930789137 + 21 +9886.191051572176 + 31 +0.0 + 11 +40162.95930789137 + 21 +10837.0271463632 + 31 +0.0 + 0 +TEXT + 5 +3FC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +32162.95930789137 + 20 +11886.19105157217 + 30 +0.0 + 40 +500.0 + 1 +ƒXƒvƒ‰ƒCƒ“‹Èü + 7 +KANJI +100 +AcDbText + 0 +LINE + 5 +40C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +40162.95930789137 + 21 +8789.515827027434 + 31 +0.0 + 0 +LINE + 5 +40D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +6789.515827027433 + 30 +0.0 + 11 +40118.791045835 + 21 +6789.515827027426 + 31 +0.0 + 0 +LWPOLYLINE + 5 +40E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 + 5 + 70 + 0 + 43 +0.0 + 10 +32162.95930789137 + 20 +6789.515827027435 + 10 +34144.21740571502 + 20 +8789.515827027434 + 10 +36162.95930789137 + 20 +6789.515827027435 + 10 +38110.78354696862 + 20 +8789.515827027434 + 10 +40118.79104583501 + 20 +6789.515827027432 + 0 +TEXT + 5 +40F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 40 +500.0 + 1 +ƒ|ƒŠƒ‰ƒCƒ“ + 7 +KANJI +100 +AcDbText + 0 +LWPOLYLINE + 5 +411 +102 +{ACAD_REACTORS +330 +434 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0.0 + 10 +37649.98492586595 + 20 +15879.05486911342 + 10 +40498.45357200499 + 20 +15879.05486911342 + 10 +40498.45357200499 + 20 +13879.05486911342 + 10 +37649.98492586595 + 20 +13879.05486911342 + 0 +HATCH + 5 +434 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbHatch + 10 +0.0 + 20 +0.0 + 30 +0.0 +210 +0.0 +220 +0.0 +230 +1.0 + 2 +ANSI31 + 70 + 0 + 71 + 1 + 91 + 1 + 92 + 7 + 72 + 0 + 73 + 1 + 93 + 4 + 10 +37649.98492586595 + 20 +15879.05486911342 + 10 +37649.98492586595 + 20 +13879.05486911342 + 10 +40498.45357200499 + 20 +13879.05486911342 + 10 +40498.45357200498 + 20 +15879.05486911342 + 97 + 1 +330 +411 + 75 + 0 + 76 + 1 + 52 +0.0 + 41 +100.0 + 77 + 0 + 78 + 1 + 53 +45.0 + 43 +21081.92472009494 + 44 +7900.63361766199 + 45 +-224.5064030267287 + 46 +224.5064030267288 + 79 + 0 + 47 +12.72318334023255 + 98 + 1 + 10 +39291.35995673742 + 20 +15049.92323490473 + 0 +TEXT + 5 +435 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +37649.98492586595 + 20 +16479.05486911342 + 30 +0.0 + 40 +500.0 + 1 +ƒnƒbƒ`ƒ“ƒO + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +436 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +37649.98492586595 + 20 +15879.05486911342 + 30 +0.0 + 40 +500.0 + 1 +ANSI31 + 7 +KANJI +100 +AcDbText + 0 +POINT + 5 +43E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +36750.93264721553 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +43F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +37495.84349439684 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +440 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +38240.75434157815 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +441 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +38985.66518875945 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +442 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +39730.57603594075 + 20 +18178.72189894357 + 30 +0.0 + 0 +TEXT + 5 +443 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +36750.93264721553 + 20 +18486.48910571766 + 30 +0.0 + 40 +500.0 + 1 +“_(â‘Î’PˆÊ300) + 7 +KANJI +100 +AcDbText + 0 +POINT + 5 +444 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +40475.48688312207 + 20 +18178.72189894357 + 30 +0.0 + 0 +POINT + 5 +445 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbPoint + 10 +41220.39773030337 + 20 +18178.72189894357 + 30 +0.0 + 0 +TEXT + 5 +564 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.831670027631 + 20 +22670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰Eã + 7 +KANJI2 + 72 + 2 + 11 +6032.801213174838 + 21 +23170.88067496867 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +565 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶’†‰› + 7 +KANJI2 + 11 +834.8316700276336 + 21 +21920.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +566 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 11 +6682.541299469253 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +567 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276319 + 20 +22170.88067496866 + 30 +0.0 + 11 +6682.541299469251 + 21 +22170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +568 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276351 + 20 +20670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 1 + 11 +3433.816441601239 + 21 +20920.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +569 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +20670.88067496866 + 30 +0.0 + 11 +6032.797142108851 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +21170.88067496866 + 30 +0.0 + 11 +6032.797142108847 + 21 +21170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276372 + 20 +19670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E’†‰› + 7 +KANJI2 + 72 + 2 + 11 +6682.547406068247 + 21 +19920.88067496867 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +56C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +19670.88067496866 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +56D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +20170.88067496866 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +56E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶‰º + 7 +KANJI2 + 11 +834.8316700276392 + 21 +18579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +56F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +19170.88067496866 + 30 +0.0 + 11 +6032.797142108851 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +570 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 11 +6032.797142108854 + 21 +18670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +571 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰º’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.689538047947 + 21 +17579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +572 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276409 + 20 +18170.88067496866 + 30 +0.0 + 11 +6682.54129946926 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +573 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 11 +6682.54129946926 + 21 +17670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +574 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276436 + 20 +16670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰E‰º + 7 +KANJI2 + 72 + 2 + 11 +6032.801213174851 + 21 +16579.51011659303 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +575 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +16670.88067496866 + 30 +0.0 + 11 +6032.797142108859 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +576 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +17170.88067496866 + 30 +0.0 + 11 +6032.797142108854 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +577 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 11 +7332.293598961658 + 21 +15140.89629083312 + 31 +0.0 + 0 +TEXT + 5 +578 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI2 + 72 + 2 + 11 +7332.293598961658 + 21 +15140.89629083311 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +579 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +7332.293598961658 + 20 +16140.89629083311 + 30 +0.0 + 11 +834.8316700276482 + 21 +16140.89629083311 + 31 +0.0 + 0 +MTEXT + 5 +57A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +834.8316700276477 + 20 +14517.44463265923 + 30 +0.0 + 40 +500.0 + 41 +4532.905584178652 + 71 + 1 + 72 + 5 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI2 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +57B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +14517.44463265923 + 30 +0.0 + 11 +5367.7372542063 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +57C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.737254206298 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276445 + 20 +16670.88067496866 + 30 +0.0 + 11 +834.8316700276445 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +57E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +14517.44463265923 + 30 +0.0 + 11 +834.8316700276482 + 21 +13110.50723841219 + 31 +0.0 + 0 +LINE + 5 +57F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276482 + 20 +15140.89629083311 + 30 +0.0 + 11 +834.8316700276482 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +580 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276372 + 20 +19670.88067496866 + 30 +0.0 + 11 +834.8316700276372 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +581 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276427 + 20 +17670.88067496866 + 30 +0.0 + 11 +834.8316700276409 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +582 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276392 + 20 +18670.88067496866 + 30 +0.0 + 11 +834.8316700276392 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +583 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276354 + 20 +20670.88067496866 + 30 +0.0 + 11 +834.8316700276354 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +584 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276336 + 20 +21670.88067496866 + 30 +0.0 + 11 +834.8316700276319 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +585 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108859 + 20 +16670.88067496867 + 30 +0.0 + 11 +6032.797142108854 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +586 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.052984748452 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +587 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388051 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.308827388049 + 21 +17170.88067496867 + 31 +0.0 + 0 +LINE + 5 +588 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +4083.564670027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +589 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +3433.818070027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027644 + 20 +16670.88067496866 + 30 +0.0 + 11 +2784.071470027644 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027645 + 20 +16670.88067496866 + 30 +0.0 + 11 +2134.324870027643 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027645 + 20 +16670.88067496866 + 30 +0.0 + 11 +1484.578270027643 + 21 +17170.88067496866 + 31 +0.0 + 0 +LINE + 5 +58D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5367.737254206298 + 20 +13110.50723841219 + 30 +0.0 + 11 +5367.7372542063 + 21 +14517.44463265923 + 31 +0.0 + 0 +LINE + 5 +58E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388051 + 20 +16670.88067496867 + 30 +0.0 + 11 +4733.308827388051 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +58F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748454 + 20 +16670.88067496867 + 30 +0.0 + 11 +5383.052984748454 + 21 +16670.88067496867 + 31 +0.0 + 0 +LINE + 5 +590 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108859 + 20 +16670.88067496868 + 30 +0.0 + 11 +6032.797142108859 + 21 +16670.88067496868 + 31 +0.0 + 0 +LINE + 5 +591 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +7332.293598961658 + 20 +15140.89629083312 + 30 +0.0 + 11 +7332.293598961658 + 21 +16140.89629083311 + 31 +0.0 + 0 +LINE + 5 +592 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +4083.564670027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +593 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +3433.818070027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +594 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +2784.071470027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +595 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027637 + 20 +19670.88067496866 + 30 +0.0 + 11 +1484.578270027637 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +596 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027638 + 20 +19670.88067496866 + 30 +0.0 + 11 +2134.324870027636 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +597 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +1484.578270027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +598 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +2134.32487002764 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +599 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.07147002764 + 20 +17670.88067496866 + 30 +0.0 + 11 +2784.07147002764 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +1484.578270027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.32487002764 + 20 +18670.88067496866 + 30 +0.0 + 11 +2134.324870027638 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027638 + 20 +18670.88067496866 + 30 +0.0 + 11 +2784.071470027638 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +3433.818070027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027641 + 20 +17670.88067496866 + 30 +0.0 + 11 +4083.564670027641 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +59F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +3433.818070027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027639 + 20 +18670.88067496866 + 30 +0.0 + 11 +4083.564670027639 + 21 +19170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +1484.578270027634 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027636 + 20 +20670.88067496866 + 30 +0.0 + 11 +2134.324870027634 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +2784.071470027635 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +1484.578270027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +2134.324870027631 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027631 + 20 +21670.88067496866 + 30 +0.0 + 11 +2784.071470027631 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027635 + 20 +20670.88067496866 + 30 +0.0 + 11 +3433.818070027635 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027636 + 20 +20670.88067496866 + 30 +0.0 + 11 +4083.564670027636 + 21 +21170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5A9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +3433.818070027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027632 + 20 +21670.88067496866 + 30 +0.0 + 11 +4083.564670027632 + 21 +22170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469256 + 20 +19670.88067496867 + 30 +0.0 + 11 +6682.541299469256 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +19670.88067496867 + 30 +0.0 + 11 +6032.797142108851 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388044 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.308827388042 + 21 +20170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5AE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748449 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.052984748447 + 21 +20170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5AF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388047 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.308827388047 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388047 + 20 +17670.88067496867 + 30 +0.0 + 11 +4733.308827388046 + 21 +18170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5B1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748452 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.052984748452 + 21 +17670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748452 + 20 +17670.88067496867 + 30 +0.0 + 11 +5383.05298474845 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +17670.88067496868 + 30 +0.0 + 11 +6032.797142108854 + 21 +17670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5B4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +17670.88067496867 + 30 +0.0 + 11 +6032.797142108854 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474845 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.052984748449 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388046 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.308827388044 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388046 + 20 +18670.88067496867 + 30 +0.0 + 11 +4733.308827388046 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474845 + 20 +18670.88067496867 + 30 +0.0 + 11 +5383.05298474845 + 21 +18670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5B9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388044 + 20 +19670.88067496867 + 30 +0.0 + 11 +4733.308827388044 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748449 + 20 +19670.88067496867 + 30 +0.0 + 11 +5383.052984748449 + 21 +19670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +18670.88067496867 + 30 +0.0 + 11 +6032.797142108851 + 21 +19170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5BC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108854 + 20 +18670.88067496868 + 30 +0.0 + 11 +6032.797142108854 + 21 +18670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +19670.88067496868 + 30 +0.0 + 11 +6032.797142108851 + 21 +19670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.54129946926 + 20 +17670.88067496868 + 30 +0.0 + 11 +6682.54129946926 + 21 +17670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.54129946926 + 20 +17670.88067496867 + 30 +0.0 + 11 +6682.54129946926 + 21 +18170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469256 + 20 +19670.88067496868 + 30 +0.0 + 11 +6682.541299469256 + 21 +19670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388042 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.308827388042 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388042 + 20 +20670.88067496867 + 30 +0.0 + 11 +4733.30882738804 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748445 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.052984748445 + 21 +20670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748445 + 20 +20670.88067496867 + 30 +0.0 + 11 +5383.052984748443 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +20670.88067496868 + 30 +0.0 + 11 +6032.797142108851 + 21 +20670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108851 + 20 +20670.88067496867 + 30 +0.0 + 11 +6032.797142108847 + 21 +21170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388039 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.308827388037 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748443 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.052984748442 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5C9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388039 + 20 +21670.88067496867 + 30 +0.0 + 11 +4733.308827388039 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748443 + 20 +21670.88067496867 + 30 +0.0 + 11 +5383.052984748443 + 21 +21670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108847 + 20 +21670.88067496867 + 30 +0.0 + 11 +6032.797142108846 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108847 + 20 +21670.88067496868 + 30 +0.0 + 11 +6032.797142108847 + 21 +21670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5CD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469253 + 20 +21670.88067496867 + 30 +0.0 + 11 +6682.541299469251 + 21 +22170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5CE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469253 + 20 +21670.88067496868 + 30 +0.0 + 11 +6682.541299469253 + 21 +21670.88067496868 + 31 +0.0 + 0 +LINE + 5 +5CF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 11 +4733.308827388029 + 21 +28670.88067496866 + 31 +0.0 + 0 +TEXT + 5 +5D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN + 7 +KANJI2 +100 +AcDbText + 0 +LINE + 5 +5D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +29170.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5D2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26670.88067496866 + 30 +0.0 + 11 +6682.541299469241 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + 7 +KANJI2 + 72 + 2 + 11 +6682.547406068232 + 21 +26670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5D5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +25670.88067496866 + 30 +0.0 + 11 +6032.797142108838 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5D6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26170.88067496866 + 30 +0.0 + 11 +6032.797142108837 + 21 +26170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5D7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276241 + 20 +25672.14971050166 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN’†‰› + 7 +KANJI2 + 72 + 4 + 11 +3433.816441601227 + 21 +25905.65224857272 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +5D8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒN¶ã + 7 +KANJI2 + 11 +834.8316700276264 + 21 +25170.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +5D9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 11 +6032.79714210884 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276246 + 20 +25170.88067496866 + 30 +0.0 + 11 +6032.797142108838 + 21 +25170.88067496866 + 31 +0.0 + 0 +TEXT + 5 +5DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276226 + 20 +27670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + 41 +0.9 + 7 +KANJI2 + 72 + 5 + 11 +6682.547406068232 + 21 +27670.88067496868 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +5DC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27670.88067496866 + 30 +0.0 + 11 +6682.541299469241 + 21 +27670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +24170.88067496866 + 30 +0.0 + 11 +6682.541299469242 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5DF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +23170.88067496866 + 30 +0.0 + 11 +6032.797142108844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +5E1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +22670.88067496866 + 30 +0.0 + 11 +6032.797142108846 + 21 +22670.88067496867 + 31 +0.0 + 0 +TEXT + 5 +5E2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +‚l‚rƒSƒVƒbƒNã’†S + 7 +KANJI2 + 72 + 1 + 11 +3758.689538047932 + 21 +24170.88067496866 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +5E3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276281 + 20 +23670.88067496866 + 30 +0.0 + 11 +834.8316700276281 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276299 + 20 +22670.88067496866 + 30 +0.0 + 11 +834.8316700276299 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276264 + 20 +24670.88067496866 + 30 +0.0 + 11 +834.8316700276246 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +26670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +25670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +27670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +28170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5E9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +834.8316700276226 + 20 +28670.88067496866 + 30 +0.0 + 11 +834.8316700276226 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027627 + 20 +23670.88067496866 + 30 +0.0 + 11 +2784.071470027627 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027629 + 20 +23670.88067496866 + 30 +0.0 + 11 +2134.324870027627 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +1484.578270027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5ED +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.57827002763 + 20 +22670.88067496866 + 30 +0.0 + 11 +1484.57827002763 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027631 + 20 +22670.88067496866 + 30 +0.0 + 11 +2134.324870027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5EF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +2784.071470027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +1484.578270027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +2134.324870027623 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027624 + 20 +24670.88067496866 + 30 +0.0 + 11 +2784.071470027624 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +4083.564670027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027628 + 20 +23670.88067496866 + 30 +0.0 + 11 +3433.818070027628 + 21 +24170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +3433.818070027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027629 + 20 +22670.88067496866 + 30 +0.0 + 11 +4083.564670027629 + 21 +23170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +3433.818070027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027625 + 20 +24670.88067496866 + 30 +0.0 + 11 +4083.564670027625 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5F9 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +26670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +26670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FC +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +25670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +25670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FE +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +5FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +600 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +26670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +601 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +602 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +25670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +603 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108844 + 20 +23670.88067496867 + 30 +0.0 + 11 +6032.79714210884 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +604 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474844 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.052984748438 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +605 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388035 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.308827388032 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +606 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388037 + 20 +22670.88067496867 + 30 +0.0 + 11 +4733.308827388037 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +607 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388037 + 20 +22670.88067496866 + 30 +0.0 + 11 +4733.308827388035 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +608 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748442 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.052984748442 + 21 +22670.88067496867 + 31 +0.0 + 0 +LINE + 5 +609 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748442 + 20 +22670.88067496867 + 30 +0.0 + 11 +5383.05298474844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388035 + 20 +23670.88067496867 + 30 +0.0 + 11 +4733.308827388035 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.05298474844 + 20 +23670.88067496867 + 30 +0.0 + 11 +5383.05298474844 + 21 +23670.88067496867 + 31 +0.0 + 0 +LINE + 5 +60C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108846 + 20 +22670.88067496868 + 30 +0.0 + 11 +6032.797142108846 + 21 +22670.88067496868 + 31 +0.0 + 0 +LINE + 5 +60D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108846 + 20 +22670.88067496867 + 30 +0.0 + 11 +6032.797142108844 + 21 +23170.88067496867 + 31 +0.0 + 0 +LINE + 5 +60E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108844 + 20 +23670.88067496868 + 30 +0.0 + 11 +6032.797142108844 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +60F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388031 + 20 +24670.88067496866 + 30 +0.0 + 11 +4733.308827388029 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +610 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748435 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +611 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388031 + 20 +24670.88067496867 + 30 +0.0 + 11 +4733.308827388031 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +612 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748435 + 20 +24670.88067496867 + 30 +0.0 + 11 +5383.052984748435 + 21 +24670.88067496867 + 31 +0.0 + 0 +LINE + 5 +613 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.79714210884 + 20 +24670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +25170.88067496866 + 31 +0.0 + 0 +LINE + 5 +614 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.79714210884 + 20 +24670.88067496868 + 30 +0.0 + 11 +6032.79714210884 + 21 +24670.88067496868 + 31 +0.0 + 0 +LINE + 5 +615 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469247 + 20 +23670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +24170.88067496867 + 31 +0.0 + 0 +LINE + 5 +616 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469247 + 20 +23670.88067496868 + 30 +0.0 + 11 +6682.541299469247 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +617 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.797142108837 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +618 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +26670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +619 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.052984748432 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +25670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +25670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +26170.88067496866 + 31 +0.0 + 0 +LINE + 5 +61C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +25670.88067496867 + 30 +0.0 + 11 +5383.052984748432 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +61E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +26670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +61F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +5383.052984748434 + 20 +26670.88067496867 + 30 +0.0 + 11 +5383.052984748434 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +620 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +621 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +25670.88067496867 + 30 +0.0 + 11 +6032.797142108837 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +622 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6032.797142108838 + 20 +26670.88067496867 + 30 +0.0 + 11 +6032.797142108838 + 21 +26670.88067496867 + 31 +0.0 + 0 +LINE + 5 +623 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469241 + 20 +26670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +624 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469242 + 20 +26670.88067496868 + 30 +0.0 + 11 +6682.541299469242 + 21 +26670.88067496868 + 31 +0.0 + 0 +LINE + 5 +625 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469241 + 20 +27670.88067496867 + 30 +0.0 + 11 +6682.541299469242 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +626 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +6682.541299469242 + 20 +27670.88067496868 + 30 +0.0 + 11 +6682.541299469242 + 21 +27670.88067496868 + 31 +0.0 + 0 +LINE + 5 +627 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +1484.578270027623 + 20 +28670.88067496866 + 30 +0.0 + 11 +1484.578270027623 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +628 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2134.324870027623 + 20 +28670.88067496866 + 30 +0.0 + 11 +2134.324870027621 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +629 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +2784.071470027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +2784.071470027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +3433.818070027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +3433.818070027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4083.564670027622 + 20 +28670.88067496866 + 30 +0.0 + 11 +4083.564670027622 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +62C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +28670.88067496867 + 30 +0.0 + 11 +4733.308827388029 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +62D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +4733.308827388029 + 20 +28670.88067496866 + 30 +0.0 + 11 +4733.308827388028 + 21 +29170.88067496866 + 31 +0.0 + 0 +TEXT + 5 +62E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +62F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI + 11 +8432.910636263379 + 21 +21920.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +630 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22170.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +631 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +21670.88067496869 + 31 +0.0 + 0 +LINE + 5 +632 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +20670.8806749687 + 31 +0.0 + 0 +LINE + 5 +633 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21170.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.8806749687 + 31 +0.0 + 0 +TEXT + 5 +634 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 40 +500.0000000000003 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 1 + 11 +11549.57730293004 + 21 +20920.8806749687 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +LINE + 5 +635 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +19670.88067496871 + 31 +0.0 + 0 +LINE + 5 +636 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20170.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +TEXT + 5 +637 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI + 72 + 2 + 11 +15266.24396959671 + 21 +19920.88067496871 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +638 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +18737.54734163539 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI + 11 +8432.910636263379 + 21 +18670.88067496872 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +639 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19170.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +63A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18670.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +18670.88067496872 + 31 +0.0 + 0 +TEXT + 5 +63B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +17604.21400830207 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +63C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18170.88067496873 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +63D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 11 +15266.24396959671 + 21 +17670.88067496873 + 31 +0.0 + 0 +TEXT + 5 +63E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263384 + 20 +16670.88067496875 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +16604.21400830208 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +63F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +16670.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +16670.88067496874 + 31 +0.0 + 0 +LINE + 5 +640 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17170.88067496875 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +641 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +16670.88067496875 + 30 +0.0 + 11 +8432.910636263379 + 21 +17170.88067496874 + 31 +0.0 + 0 +LINE + 5 +642 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +8432.910636263384 + 20 +13184.11129932598 + 30 +0.0 + 11 +12965.81622044203 + 21 +13184.11129932597 + 31 +0.0 + 0 +LINE + 5 +643 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +MTEXT + 5 +644 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 40 +500.0 + 41 +4532.905584178652 + 71 + 1 + 72 + 5 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +645 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +15140.89629083319 + 31 +0.0 + 0 +TEXT + 5 +646 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 40 +1000.0 + 1 +‚‚³‚ðŠm”F + 7 +KANJI + 72 + 2 + 11 +14166.24396959671 + 21 +15140.89629083319 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +647 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +16140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +648 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +14517.44463265931 + 30 +0.0 + 11 +8432.910636263384 + 21 +13184.11129932598 + 31 +0.0 + 0 +LINE + 5 +649 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263384 + 20 +15140.89629083319 + 30 +0.0 + 11 +8432.910636263384 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +64A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +12965.81622044203 + 20 +13184.11129932597 + 30 +0.0 + 11 +12965.81622044203 + 21 +14517.44463265931 + 31 +0.0 + 0 +LINE + 5 +64D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14166.24396959671 + 20 +15140.89629083319 + 30 +0.0 + 11 +14166.24396959671 + 21 +16140.89629083319 + 31 +0.0 + 0 +LINE + 5 +64E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +19670.88067496871 + 30 +0.0 + 11 +8432.910636263379 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +64F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +17670.88067496874 + 30 +0.0 + 11 +8432.910636263379 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +650 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +18670.88067496872 + 30 +0.0 + 11 +8432.910636263379 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +651 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +20670.8806749687 + 30 +0.0 + 11 +8432.910636263379 + 21 +21170.8806749687 + 31 +0.0 + 0 +LINE + 5 +652 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +21670.88067496869 + 30 +0.0 + 11 +8432.910636263379 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +653 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +16670.88067496874 + 30 +0.0 + 11 +14666.24396959671 + 21 +17170.88067496875 + 31 +0.0 + 0 +LINE + 5 +654 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +19670.88067496871 + 30 +0.0 + 11 +15266.24396959671 + 21 +20170.88067496871 + 31 +0.0 + 0 +LINE + 5 +655 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +17670.88067496873 + 30 +0.0 + 11 +15266.24396959671 + 21 +18170.88067496873 + 31 +0.0 + 0 +LINE + 5 +656 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +18670.88067496872 + 30 +0.0 + 11 +14666.24396959671 + 21 +19170.88067496872 + 31 +0.0 + 0 +LINE + 5 +657 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +20670.8806749687 + 30 +0.0 + 11 +14666.24396959671 + 21 +21170.8806749687 + 31 +0.0 + 0 +LINE + 5 +658 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +21670.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +22170.88067496869 + 31 +0.0 + 0 +LINE + 5 +659 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26670.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +26670.88067496866 + 31 +0.0 + 0 +LINE + 5 +65A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +TEXT + 5 +65B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263381 + 20 +26670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI + 72 + 2 + 11 +15232.91063626337 + 21 +26670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +65C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI + 72 + 2 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +65D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +25670.88067496867 + 31 +0.0 + 0 +LINE + 5 +65E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26170.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +65F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +24670.88067496868 + 31 +0.0 + 0 +LINE + 5 +660 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25170.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.88067496868 + 31 +0.0 + 0 +TEXT + 5 +661 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI + 11 +8432.910636263379 + 21 +25170.88067496868 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +662 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.9272727272727273 + 7 +KANJI + 72 + 5 + 11 +15232.91063626337 + 21 +27670.88067496866 + 31 +0.0 +100 +AcDbText + 0 +LINE + 5 +663 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +27670.88067496866 + 31 +0.0 + 0 +LINE + 5 +664 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28170.88067496867 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +665 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 11 +14666.24396959671 + 21 +22670.88067496868 + 31 +0.0 + 0 +LINE + 5 +666 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23170.88067496869 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +667 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 11 +15266.24396959671 + 21 +23670.88067496868 + 31 +0.0 + 0 +LINE + 5 +668 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24170.88067496869 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.88067496869 + 31 +0.0 + 0 +TEXT + 5 +669 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI + 72 + 1 + 11 +11849.57730293004 + 21 +24170.88067496869 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +66A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI +100 +AcDbText + 0 +LINE + 5 +66B +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +23670.88067496868 + 30 +0.0 + 11 +8432.910636263379 + 21 +24170.88067496868 + 31 +0.0 + 0 +LINE + 5 +66C +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +22670.88067496869 + 30 +0.0 + 11 +8432.910636263379 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +66D +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +24670.88067496868 + 30 +0.0 + 11 +8432.910636263379 + 21 +25170.88067496867 + 31 +0.0 + 0 +LINE + 5 +66E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +26670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +27170.88067496866 + 31 +0.0 + 0 +LINE + 5 +66F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +25670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +670 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +27670.88067496866 + 30 +0.0 + 11 +8432.910636263379 + 21 +28170.88067496866 + 31 +0.0 + 0 +LINE + 5 +671 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +29170.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +672 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +28670.88067496867 + 31 +0.0 + 0 +LINE + 5 +673 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +8432.910636263379 + 20 +28670.88067496867 + 30 +0.0 + 11 +8432.910636263379 + 21 +29170.88067496866 + 31 +0.0 + 0 +LINE + 5 +674 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +13432.91063626337 + 20 +28670.88067496867 + 30 +0.0 + 11 +13432.91063626337 + 21 +29170.88067496867 + 31 +0.0 + 0 +LINE + 5 +675 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15266.24396959671 + 20 +23670.88067496868 + 30 +0.0 + 11 +15266.24396959671 + 21 +24170.88067496869 + 31 +0.0 + 0 +LINE + 5 +676 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +22670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +23170.88067496869 + 31 +0.0 + 0 +LINE + 5 +677 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +24670.88067496868 + 30 +0.0 + 11 +14666.24396959671 + 21 +25170.88067496868 + 31 +0.0 + 0 +LINE + 5 +678 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15232.91063626337 + 20 +26670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +27170.88067496867 + 31 +0.0 + 0 +LINE + 5 +679 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +14666.24396959671 + 20 +25670.88067496867 + 30 +0.0 + 11 +14666.24396959671 + 21 +26170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67A +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15232.91063626337 + 20 +27670.88067496866 + 30 +0.0 + 11 +15232.91063626337 + 21 +28170.88067496867 + 31 +0.0 + 0 +LINE + 5 +67D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.20600900591 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 + 0 +LINE + 5 +67E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.20600900591 + 30 +0.0 + 11 +17739.86399912307 + 21 +23517.20600900591 + 31 +0.0 + 0 +LINE + 5 +680 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17739.86399912307 + 20 +23517.2060090059 + 30 +0.0 + 11 +18739.86399912308 + 21 +23517.2060090059 + 31 +0.0 + 0 +TEXT + 5 +681 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +25683.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰Eã + 7 +KANJI3 + 72 + 2 + 11 +25683.30873463529 + 21 +12102.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +685 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +21683.30873463532 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶‰º + 7 +KANJI3 + 11 +21683.30873463532 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +TEXT + 5 +686 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +22683.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E’†‰› + 7 +KANJI3 + 72 + 2 + 11 +22683.30873463531 + 21 +11468.7721504546 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +689 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +23683.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 1 + 11 +23683.3087346353 + 21 +16577.10548378792 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +68E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +24683.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶’†‰› + 7 +KANJI3 + 11 +24683.3087346353 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 2 + 0 +TEXT + 5 +697 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +26683.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontã’†S + 7 +KANJI3 + 72 + 1 + 11 +26683.30873463528 + 21 +16277.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +TEXT + 5 +69E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +30683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfontƒtƒBƒbƒg + 41 +0.6677577741407528 + 7 +KANJI3 + 72 + 2 + 11 +30683.30873463527 + 21 +10902.10548378792 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +69F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +27683.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont¶ã + 7 +KANJI3 + 11 +27683.30873463528 + 21 +21085.43881712126 + 31 +0.0 +100 +AcDbText + 73 + 3 + 0 +LINE + 5 +6A2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6A3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +28433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28433.30873463526 + 21 +12068.77215045459 + 31 +0.0 + 0 +TEXT + 5 +6A4 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +28683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont’†‰› + 7 +KANJI3 + 72 + 2 + 11 +28683.30873463527 + 21 +12068.77215045459 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6A5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +29683.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰EŠñ‚¹ + 7 +KANJI3 + 72 + 2 + 11 +29683.30873463527 + 21 +11502.10548378792 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6A8 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +31683.30873463526 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont + 7 +KANJI3 + 72 + 2 + 11 +31683.30873463526 + 21 +13418.77215045459 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +6BB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +19683.30873463535 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰E‰º + 7 +KANJI3 + 72 + 2 + 11 +19683.30873463535 + 21 +12068.7721504546 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +TEXT + 5 +6BD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +20683.30873463533 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 1 +txt/bigfont‰º’†S + 7 +KANJI3 + 72 + 1 + 11 +20683.30873463533 + 21 +16277.10548378793 + 31 +0.0 +100 +AcDbText + 73 + 1 + 0 +LINE + 5 +6BF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +18903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +TEXT + 5 +6C0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +18403.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 40 +1000.0 + 1 +•‚ðŠm”F + 7 +KANJI3 +100 +AcDbText + 0 +LINE + 5 +6C1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +17903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +MTEXT + 5 +6C2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbMText + 10 +15946.53935899258 + 20 +21085.43881712126 + 30 +0.0 + 40 +500.0 + 41 +6072.728764697807 + 71 + 1 + 72 + 5 + 1 +2s‚Ì\Pƒ}ƒ‹ƒ`ƒeƒLƒXƒg + 7 +KANJI3 +1001 +ACAD +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND +1000 +MTEXTBEGIN +1070 + 73 +1070 + 1 +1070 + 44 +1040 +1.0 +1070 + 74 +1070 + 0 +1000 +MTEXTEND + 0 +LINE + 5 +6C3 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17479.87269232592 + 20 +21085.43881712126 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6C4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +15946.53935899258 + 20 +21085.43881712126 + 30 +0.0 + 11 +15946.53935899257 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6C5 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17479.87269232592 + 20 +21085.43881712126 + 30 +0.0 + 11 +15946.53935899258 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6C6 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +17903.3243504998 + 20 +21085.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6C7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +15946.53935899257 + 20 +15002.24551827521 + 30 +0.0 + 11 +17479.87269232592 + 21 +15002.24551827521 + 31 +0.0 + 0 +LINE + 5 +6CC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +17903.3243504998 + 20 +16485.43881712126 + 30 +0.0 + 11 +18903.3243504998 + 21 +16485.43881712126 + 31 +0.0 + 0 +LINE + 5 +6CD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +28433.30873463526 + 20 +12068.77215045459 + 30 +0.0 + 11 +28933.30873463527 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +6CF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +28433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +28933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D0 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +27433.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6D1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +27933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6D3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +27933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +25433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6D9 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +25433.30873463527 + 20 +12102.10548378793 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25433.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +25933.30873463528 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6DC +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6F0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27433.30873463527 + 20 +12102.10548378793 + 30 +0.0 + 11 +27933.30873463527 + 21 +12102.10548378793 + 31 +0.0 + 0 +LINE + 5 +6F1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29433.30873463526 + 21 +11502.10548378793 + 31 +0.0 + 0 +LINE + 5 +6F2 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +29933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +29433.30873463526 + 20 +11502.10548378793 + 30 +0.0 + 11 +29933.30873463527 + 21 +11502.10548378792 + 31 +0.0 + 0 +LINE + 5 +6F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +29433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +29933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6FA +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26433.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FB +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +26933.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +21085.43881712126 + 30 +0.0 + 11 +26933.30873463528 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +6FE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +26433.30873463528 + 20 +11468.7721504546 + 30 +0.0 + 11 +26933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +6FF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24433.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +700 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +24933.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +701 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +11468.7721504546 + 30 +0.0 + 11 +24933.30873463528 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +702 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +703 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +24433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +24933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +704 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23433.30873463528 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +705 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +23933.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +706 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +23433.30873463528 + 20 +12068.77215045459 + 30 +0.0 + 11 +23933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +707 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +23433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +23933.30873463529 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +708 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +709 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22433.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +70A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +11468.7721504546 + 30 +0.0 + 11 +22933.30873463529 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +70B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +22433.30873463529 + 20 +21085.43881712126 + 30 +0.0 + 11 +22933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +70E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +70F +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +21433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21433.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +710 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +21433.30873463529 + 20 +12068.77215045459 + 30 +0.0 + 11 +21933.30873463529 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +711 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +21433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +21933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +712 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20433.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +713 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +20933.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +714 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +11468.7721504546 + 30 +0.0 + 11 +20933.3087346353 + 21 +11468.7721504546 + 31 +0.0 + 0 +LINE + 5 +715 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +716 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +20433.3087346353 + 20 +21085.43881712126 + 30 +0.0 + 11 +20933.3087346353 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +717 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19433.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19433.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +718 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +19933.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19933.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +719 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19433.3087346353 + 20 +12068.77215045459 + 30 +0.0 + 11 +19933.3087346353 + 21 +12068.77215045459 + 31 +0.0 + 0 +LINE + 5 +71A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +19433.30873463531 + 20 +21085.43881712126 + 30 +0.0 + 11 +19933.30873463531 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +720 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31433.30873463526 + 21 +13418.7721504546 + 31 +0.0 + 0 +LINE + 5 +721 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +31933.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +722 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +31433.30873463526 + 20 +13418.7721504546 + 30 +0.0 + 11 +31933.30873463527 + 21 +13418.77215045459 + 31 +0.0 + 0 +LINE + 5 +723 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +31433.30873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +31933.30873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +726 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30516.60873463526 + 20 +21085.43881712126 + 30 +0.0 + 11 +30516.60873463526 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +727 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +30850.00873463527 + 20 +21085.43881712126 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +729 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30516.60873463526 + 20 +10902.10548378792 + 30 +0.0 + 11 +30850.00873463527 + 21 +10902.10548378792 + 31 +0.0 + 0 +LINE + 5 +72A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30516.60873463526 + 20 +21085.43881712126 + 30 +0.0 + 11 +30850.00873463527 + 21 +21085.43881712126 + 31 +0.0 + 0 +LINE + 5 +730 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +29231.97245541628 + 21 +10114.99828738483 + 31 +0.0 + 0 +LINE + 5 +731 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +27731.97245541628 + 21 +7516.922076031523 + 31 +0.0 + 0 +LINE + 5 +732 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +7516.922076031523 + 30 +0.0 + 11 +29231.97245541628 + 21 +10114.99828738483 + 31 +0.0 + 0 +LINE + 5 +735 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +29231.97245541628 + 21 +6867.403023193194 + 31 +0.0 + 0 +LINE + 5 +736 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +27731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +30731.97245541628 + 21 +9465.479234546508 + 31 +0.0 + 0 +LINE + 5 +737 +102 +{ACAD_REACTORS +330 +739 +102 +} +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +30731.97245541628 + 20 +9465.479234546508 + 30 +0.0 + 11 +29231.97245541628 + 21 +6867.403023193194 + 31 +0.0 + 0 +TEXT + 5 +73B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +27375.98522036158 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒOƒ‹[ƒv}Œ` + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +73C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23443.86458478673 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒuƒƒbƒN}Œ` + 7 +KANJI +100 +AcDbText + 0 +INSERT + 5 +74D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockReference + 2 +NONAME + 10 +12199.75897743096 + 20 +4508.97892854021 + 30 +0.0 + 41 +0.6 + 42 +0.6 + 43 +0.6 + 0 +LINE + 5 +74E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +40162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +40162.95930789137 + 21 +6789.515827027426 + 31 +0.0 + 0 +LINE + 5 +74F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +38110.78354696862 + 20 +8789.515827027434 + 30 +0.0 + 11 +38110.78354696862 + 21 +6789.515827027428 + 31 +0.0 + 0 +LINE + 5 +750 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +36162.95930789138 + 20 +6789.515827027429 + 30 +0.0 + 11 +36162.95930789138 + 21 +8789.515827027434 + 31 +0.0 + 0 +LINE + 5 +752 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +34144.21740571502 + 20 +8789.515827027434 + 30 +0.0 + 11 +34144.21740571502 + 21 +6789.515827027432 + 31 +0.0 + 0 +LINE + 5 +753 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbLine + 10 +32162.95930789137 + 20 +8789.515827027434 + 30 +0.0 + 11 +32162.95930789137 + 21 +6789.515827027435 + 31 +0.0 + 0 +DIMENSION + 5 +755 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D10 + 10 +3334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +2084.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +834.8316700276482 + 23 +3391.885493772555 + 33 +0.0 + 14 +3334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 + +1070 + 173 +1070 + 1 +1070 + 7 +1000 + +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +801 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D12 + 10 +5834.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +4584.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +3334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +5834.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSEDBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSEDBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +83A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +684.8316700276475 + 20 +5515.901028694454 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +2084.831670027647 + 21 +5515.901028694454 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +83B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +1568.165003360981 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +–îˆó + 7 +KANJI + 72 + 1 + 11 +2084.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +83C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +3768.165003360982 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +‹ó–îˆó + 7 +KANJI + 72 + 1 + 11 +4584.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +83D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D14 + 10 +8334.831670027648 + 20 +4323.35489965057 + 30 +0.0 + 11 +7084.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +5834.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +8334.831670027648 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +CLOSED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +CLOSED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +865 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6251.498336694315 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +•Â–îˆó + 7 +KANJI + 72 + 1 + 11 +7084.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +866 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D15 + 10 +10834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +9584.831670027648 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +8334.831670027648 + 23 +3391.885493772555 + 33 +0.0 + 14 +10834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOT +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOT +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +893 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +9051.498336694313 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +•ŠÛ + 7 +KANJI + 72 + 1 + 11 +9584.831670027648 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +89C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +11534.83167002764 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +(‘¾) + 7 +KANJI + 72 + 1 + 11 +12084.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +89D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D17 + 10 +13334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +12084.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +10834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +13334.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ARCHTICK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ARCHTICK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8C9 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +13468.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +14584.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +8CA +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D19 + 10 +15834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +14584.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +13334.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +15834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OBLIQUE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OBLIQUE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F6 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +10968.16500336098 + 20 +5452.894222873409 + 30 +0.0 + 40 +500.0 + 1 +ƒeƒBƒbƒN + 7 +KANJI + 72 + 1 + 11 +12084.83167002764 + 21 +5452.894222873409 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +8F7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D21 + 10 +18334.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +17084.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +15834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +18334.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +8F8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +16251.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŠJ–îˆó + 7 +KANJI + 72 + 1 + 11 +17084.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +92F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D23 + 10 +20834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +19584.83167002764 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +18334.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +20834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +930 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +18868.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ1 + 7 +KANJI + 72 + 1 + 11 +19584.83167002764 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +97D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D25 + 10 +23334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +22084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +20834.83167002764 + 23 +3391.885493772555 + 33 +0.0 + 14 +23334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +ORIGIN2 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +ORIGIN2 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +97E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +21284.83167002765 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +”’ŠÛ2 + 7 +KANJI + 72 + 1 + 11 +22084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +9C3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D27 + 10 +25834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +24584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +23334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +25834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN90 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN90 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +9C4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +23468.16500336098 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +’¼Šp–îˆó + 7 +KANJI + 72 + 1 + 11 +24584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +AAF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D29 + 10 +28334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +27084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +25834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +28334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +OPEN30 +1070 + 173 +1070 + 1 +1070 + 7 +1000 +OPEN30 +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +AB0 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25809.83167002764 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +30‹–îˆó + 7 +KANJI + 72 + 1 + 11 +27084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +AE7 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +28751.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +¬•ŠÛ + 7 +KANJI + 72 + 1 + 11 +29584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +AE8 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D31 + 10 +30834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +29584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +28334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +30834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTSMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTSMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +B1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D33 + 10 +33334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +32084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +30834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +33334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DOTBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DOTBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B1E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +31251.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +32084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +B55 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D35 + 10 +35834.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +34584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +33334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +35834.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +SMALL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +SMALL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +B56 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +33451.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +¬‹ó”’ŠÛ + 7 +KANJI + 72 + 1 + 11 +34584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +B82 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +36551.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +37084.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +B83 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D37 + 10 +38334.83167002765 + 20 +4323.35489965057 + 30 +0.0 + 11 +37084.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +35834.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +38334.83167002765 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E64 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +39051.49833669431 + 20 +4919.627964172512 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠp + 7 +KANJI + 72 + 1 + 11 +39584.83167002765 + 21 +4919.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +E65 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D39 + 10 +40834.83167002764 + 20 +4323.35489965057 + 30 +0.0 + 11 +39584.83167002765 + 21 +4535.85489965057 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +38334.83167002765 + 23 +3391.885493772555 + 33 +0.0 + 14 +40834.83167002764 + 24 +3391.885493772555 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +BOXFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +BOXFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E92 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +38184.83167002765 + 20 +5419.627964172512 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +39584.83167002765 + 21 +5419.627964172512 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +E93 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D41 + 10 +6374.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +5124.072001619017 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +3874.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +6374.072001619017 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMBLANK +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMBLANK +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +E94 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +4007.405334952351 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +5124.072001619017 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +ED4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +4624.072001619017 + 20 +2702.193038433077 + 30 +0.0 + 40 +500.0 + 1 +‹ó”’ + 7 +KANJI + 72 + 1 + 11 +5124.072001619017 + 21 +2702.193038433077 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +F80 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6507.405334952351 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ƒf[ƒ^ƒ€ + 7 +KANJI + 72 + 1 + 11 +7624.072001619016 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +F81 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D43 + 10 +8874.072001619017 + 20 +1663.887067986979 + 30 +0.0 + 11 +7624.072001619016 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +6374.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +8874.072001619017 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +DATUMFILLED +1070 + 173 +1070 + 1 +1070 + 7 +1000 +DATUMFILLED +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +FAD +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +6224.072001619017 + 20 +2702.193038433077 + 30 +0.0 + 40 +500.0 + 1 +“h‚è‚‚Ԃµ + 7 +KANJI + 72 + 1 + 11 +7624.072001619016 + 21 +2702.193038433077 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +114E +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D45 + 10 +11374.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +10124.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +8874.072001619017 + 23 +732.4176621089645 + 33 +0.0 + 14 +11374.07200161901 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +INTEGRAL +1070 + 173 +1070 + 1 +1070 + 7 +1000 +INTEGRAL +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +114F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +9590.738668285684 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +”gŒ` + 7 +KANJI + 72 + 1 + 11 +10124.07200161901 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +117C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D47 + 10 +13874.07200161901 + 20 +1663.887067986979 + 30 +0.0 + 11 +12624.07200161901 + 21 +1876.387067986979 + 31 +0.0 + 70 + 32 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +11374.07200161901 + 23 +732.4176621089645 + 33 +0.0 + 14 +13874.07200161901 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 6 +1000 +NONE +1070 + 173 +1070 + 1 +1070 + 7 +1000 +NONE +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +117D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +12124.07200161901 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +‚È‚µ + 7 +KANJI + 72 + 1 + 11 +12624.07200161901 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +13F4 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D49 + 10 +16108.82612140059 + 20 +1663.887067986979 + 30 +0.0 + 11 +16871.32612140059 + 21 +1663.887067986979 + 31 +0.0 + 70 + 160 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +14608.82612140059 + 23 +732.4176621089645 + 33 +0.0 + 14 +16108.82612140059 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +DIMENSION + 5 +147B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D50 + 10 +19554.68096413649 + 20 +1663.887067986979 + 30 +0.0 + 11 +20467.18096413649 + 21 +1663.887067986979 + 31 +0.0 + 70 + 160 + 1 +<> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +19054.68096413649 + 23 +732.4176621089645 + 33 +0.0 + 14 +19554.68096413649 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 279 +1070 + 0 +1070 + 40 +1040 +100.0 +1070 + 173 +1070 + 1 +1070 + 6 +1000 +OPEN30 +1070 + 7 +1000 +OPEN30 +1002 +} + 0 +TEXT + 5 +151F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +14219.42234363432 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ŠOŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +15936.08901030098 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +152B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +18038.39553279113 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +“àŒü‚«‚Ì–îˆó + 7 +KANJI + 72 + 1 + 11 +19771.72886612446 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +156C +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +22164.30081507835 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +À•W¡–@ + 7 +KANJI + 72 + 1 + 11 +23297.63414841168 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1682 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D53 + 10 +38079.23269341683 + 20 +22516.99684345932 + 30 +0.0 + 11 +36161.20554944833 + 21 +20899.49008149508 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +33902.64286594653 + 23 +19622.51885906414 + 33 +0.0 + 14 +37438.17677187927 + 24 +23158.05276499688 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +168F +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D54 + 10 +38005.66793242672 + 20 +23725.54392554433 + 30 +0.0 + 11 +37625.59803753895 + 21 +24406.13420243639 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +36377.51660009945 + 23 +24218.7129367767 + 33 +0.0 + 14 +37438.17677187927 + 24 +23158.05276499688 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AE +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D55 + 10 +39061.61755388569 + 20 +26056.56410520013 + 30 +0.0 + 11 +36561.61755388569 + 21 +26269.06410520013 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +34061.61755388569 + 23 +26963.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +26963.15408367813 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +DIMENSION + 5 +16AF +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbDimension + 2 +*D56 + 10 +39864.17124965874 + 20 +26963.15408367813 + 30 +0.0 + 11 +39651.67124965873 + 21 +27713.15408367814 + 31 +0.0 + 70 + 33 + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +39061.61755388569 + 23 +28463.15408367813 + 33 +0.0 + 14 +39061.61755388569 + 24 +26963.15408367813 + 34 +0.0 +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +TEXT + 5 +1710 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33826.09168609505 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1711 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33472.53829550178 + 20 +20318.35664042155 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1712 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +33826.09168609505 + 20 +19964.80324982827 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 50 +45.0 + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1840 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27759.31555586257 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1841 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27759.31555586257 + 30 +0.0 + 40 +500.0 + 1 +ŽlŠpŒ`‚Æ’·‚³¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1842 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27259.31555586257 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1843 +330 +1F +100 +AcDbEntity + 8 +1 + 62 + 0 +100 +AcDbText + 10 +34249.51930930849 + 20 +27259.31555586257 + 30 +0.0 + 40 +500.0 + 1 +•½s¡–@ + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CB +330 +1F +100 +AcDbEntity + 8 +ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +2369.538337786623 + 30 +0.0 + 40 +500.0 + 1 +ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CC +330 +1F +100 +AcDbEntity + 8 +”ñ•\Ž¦‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +1869.538337786623 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CD +330 +1F +100 +AcDbEntity + 8 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +1369.538337786623 + 30 +0.0 + 40 +500.0 + 1 +”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +18CF +330 +1F +100 +AcDbEntity + 8 +ƒƒbƒN‚³‚ꂽ‰æ‘w +100 +AcDbText + 10 +29297.88047843924 + 20 +869.5383377866237 + 30 +0.0 + 40 +500.0 + 1 +ƒƒbƒN‚³‚ꂽ‰æ‘w‚É‘‚©‚ꂽ•¶Žš + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1ABE +330 +1F +100 +AcDbEntity + 8 +ƒtƒŠ[ƒY‰æ‘w +100 +AcDbText + 10 +18013.26504642274 + 20 +8351.553922912222 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI +100 +AcDbText + 0 +TEXT + 5 +1ABF +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +15934.06065949847 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +(ƒ|ƒŠƒ‰ƒCƒ“) + 7 +KANJI + 72 + 1 + 11 +17684.06065949847 + 21 +10232.27806776508 + 31 +0.0 +100 +AcDbText + 0 +LWPOLYLINE + 5 +1AC1 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbPolyline + 90 + 21 + 70 + 1 + 43 +0.0 + 10 +17355.64886932063 + 20 +9506.927495816984 + 42 +0.52056705 + 10 +16857.00923996034 + 20 +9506.927495816984 + 42 +0.52056705 + 10 +16477.09299069931 + 20 +9328.998963914726 + 42 +0.52056705 + 10 +16239.64555880858 + 20 +8996.86581798768 + 42 +0.52056705 + 10 +16061.55981696746 + 20 +8617.285079785302 + 42 +0.52056705 + 10 +16120.9217309145 + 20 +8202.118586506607 + 42 +0.52056705 + 10 +16346.49700391324 + 20 +7869.985440579533 + 42 +0.52056705 + 10 +16643.30634975101 + 20 +7514.128376775044 + 42 +0.52056705 + 10 +17023.22237511465 + 20 +7348.061803811521 + 42 +0.52056705 + 10 +17498.11746279351 + 20 +7265.02857819965 + 42 +0.52056705 + 10 +17913.65063652536 + 20 +7312.476170474926 + 42 +0.52056705 + 10 +18293.56666188899 + 20 +7478.542743438477 + 42 +0.52056705 + 10 +18720.97221841025 + 20 +7644.609316401998 + 42 +0.52056705 + 10 +19041.52655372422 + 20 +7905.57107391613 + 42 +0.52056705 + 10 +19207.73968887853 + 20 +8273.289974919549 + 42 +0.52056705 + 10 +19326.4635167726 + 20 +8664.732672060607 + 42 +0.52056705 + 10 +19362.08066514082 + 20 +9079.899165339332 + 42 +0.52056705 + 10 +19112.76085046067 + 20 +9412.032311266376 + 42 +0.52056705 + 10 +18768.46174956788 + 20 +9625.546476505203 + 42 +0.52056705 + 10 +18341.05619304662 + 20 +9756.027416132157 + 42 +0.52056705 + 10 +17913.65063652536 + 20 +9815.336845606392 + 42 +0.52056705 + 0 +TEXT + 5 +1AE3 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +20103.52469524904 + 20 +10232.27806776508 + 30 +0.0 + 40 +500.0 + 1 +ƒŠ[ƒWƒ‡ƒ“ + 7 +KANJI +100 +AcDbText + 0 +REGION + 5 +1AE7 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbModelerGeometry + 70 + 1 + 1 +noi io n o + 1 +=0;& {rn {n {rn {rn | + 1 +3*2/ {rn {rn {m {o | + 1 +,7:33 {rn {rn {rn {l {n | + 1 +9><: {rn {rn {k {m {rn {j 90-(>-; ;0*=3: 0*+ | + 1 +300/ {rn {rn {i {l | + 1 +/3>1:r,*-9><: {rn mnkjfqjilkkillkig gjffqkjlglohimoifi o o o n n o o o V V V V | + 1 +<0:;8: {rn {h {g {rn {f n {k {rn | + 1 +<0:;8: {rn {no {i {rn {nn n {k {rn | + 1 +<0:;8: {rn {i {nm {rn {nl o {k {rn | + 1 +:;8: {rn {nk {nj {i {ni o | + 1 +<0:;8: {rn {nh {h {rn {ng o {k {rn | + 1 +:;8: {rn {nf {nk {h {mo o | + 1 +<0:;8: {rn {g {mn {rn {mm n {k {rn | + 1 +:;8: {rn {ml {nj {g {mk o | + 1 +):-+:' {rn {nn {mj | + 1 +):-+:' {rn {f {mi | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig fkijqkhfmlkjkijogj o roqjoooooooooooooomm roqgiiomjkolhgkklgi o V V | + 1 +<0:;8: {rn {mh {no {rn {mg n {k {rn | + 1 +:;8: {rn {nf {mf {no {mk o | + 1 +):-+:' {rn {nn {lo | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o n o o V V | + 1 +<0:;8: {rn {nm {ln {rn {lm n {k {rn | + 1 +:;8: {rn {ml {ll {nm {lk o | + 1 +):-+:' {rn {mm {lj | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o roqjoooooooooooooomm oqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mmfjfqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +/061+ {rn mmlfhqoilkkillkig gkfnqmooijjmgfonin o | + 1 +<0:;8: {rn {li {nh {rn {lh n {k {rn | + 1 +:;8: {rn {lg {mf {nh {lf o | + 1 +):-+:' {rn {mg {ko | + 1 +/061+ {rn mnglkqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +<0:;8: {rn {mn {kn {rn {km o {k {rn | + 1 +:;8: {rn {ll {kl {mn {ni o | + 1 +):-+:' {rn {lm {kk | + 1 +,+->687+r<*-): {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o rn o o V V | + 1 +/061+ {rn mmfjfqjilkkillkig hjniqfmmohiolnjmm o | + 1 +<0:;8: {rn {kj {mh {rn {ki o {k {rn | + 1 +:;8: {rn {kh {lg {mh {mo o | + 1 +):-+:' {rn {lh {kg | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig hjniqfmmohiolnjmm o oqjoooooooooooooomm oqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mnkjfqjilkkillkig nonnkqffgmghlgkglh o | + 1 +<0:;8: {rn {ln {kj {rn {kf n {k {rn | + 1 +:;8: {rn {jo {kl {ln {jn o | + 1 +):-+:' {rn {lm {jm | + 1 +/061+ {rn mnglkqjilkkillkig hjniqfmmohiolnjmm o | + 1 +<0:;8: {rn {kn {li {rn {jl n {k {rn | + 1 +:;8: {rn {kh {jk {li {jn o | + 1 +):-+:' {rn {lh {jj | + 1 +/061+ {rn mnogkqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +:;8: {rn {jo {ji {kn {lk o | + 1 +):-+:' {rn {km {jh | + 1 +,+->687+r<*-): {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o oqjoooooooooooooomm roqgiiomjkolhgkklgi o V V | + 1 +/061+ {rn mnkjfqjilkkillkig igihqkolomlnflnflg o | + 1 +:;8: {rn {ji {jk {kj {lf o | + 1 +):-+:' {rn {jl {jg | + 1 +/061+ {rn nffjfqjilkkillkig fkijqkhfmlkjkijogj o | + 1 +):-+:' {rn {kf {jf | + 1 +/061+ {rn mnogkqjilkkillkig hjniqfmmohiolnjmm o | + 1 +/061+ {rn mojmmqoilkkillkig gkfnqmooijjmgfonin o | + 1 +/061+ {rn nffjfqjilkkillkig hjniqfmmohiolnjmm o | + 0 +TEXT + 5 +1B72 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbText + 10 +16584.06065949847 + 20 +10732.27806776508 + 30 +0.0 + 40 +500.0 + 1 +‰_ƒ}[ƒN + 7 +KANJI + 72 + 1 + 11 +17684.06065949847 + 21 +10732.27806776508 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1DFD +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D57 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +24827.83753739796 + 21 +2292.399842974457 + 31 +0.0 + 70 + 102 + 3 +ISO-25 +100 +AcDbOrdinateDimension + 13 +24000.0 + 23 +703.3640086830565 + 33 +0.0 + 14 +24978.46253739796 + 24 +1666.774842974453 + 34 +0.0 + 0 +DIMENSION + 5 +1E0E +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D58 + 10 +26446.29486998995 + 20 +1653.666411913524 + 30 +0.0 + 11 +27433.79486998995 + 21 +1653.666411913524 + 31 +0.0 + 70 + 160 + 1 +<<>> + 3 +ISO-25 +100 +AcDbAlignedDimension + 13 +25446.29486998995 + 23 +732.4176621089645 + 33 +0.0 + 14 +26446.29486998995 + 24 +732.4176621089645 + 34 +0.0 +100 +AcDbRotatedDimension +1001 +ACAD +1000 +DSTYLE +1002 +{ +1070 + 40 +1040 +100.0 +1002 +} + 0 +LINE + 5 +1E26 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbLine + 10 +25446.29486998995 + 20 +732.4176621089645 + 30 +0.0 + 11 +26446.29486998995 + 21 +732.4176621089645 + 31 +0.0 + 0 +TEXT + 5 +1F2A +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25832.99885892392 + 20 +2161.68455103159 + 30 +0.0 + 40 +500.0 + 1 +ã‘‚« + 7 +KANJI + 72 + 1 + 11 +26632.99885892392 + 21 +2161.68455103159 + 31 +0.0 +100 +AcDbText + 0 +TEXT + 5 +1F2B +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbText + 10 +25516.33219225725 + 20 +2661.684551031591 + 30 +0.0 + 40 +500.0 + 1 +¡–@’l‚Ì + 7 +KANJI + 72 + 1 + 11 +26632.99885892392 + 21 +2661.684551031591 + 31 +0.0 +100 +AcDbText + 0 +DIMENSION + 5 +1F54 +330 +1F +100 +AcDbEntity + 8 +1 +100 +AcDbDimension + 2 +*D59 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +22870.3274027464 + 21 +1811.026028986983 + 31 +0.0 + 70 + 38 + 3 +ISO-25 +100 +AcDbOrdinateDimension + 13 +21761.90789325554 + 23 +700.0 + 33 +0.0 + 14 +22519.7024027464 + 24 +1660.401028986984 + 34 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACAD_PLOTSTYLENAME +350 +E + 3 +ACADDIM +350 +3A2 + 3 +ACDBHEADERROUNDTRIPXREC +350 +208D + 3 +ACDBVARIABLEDICTIONARY +350 +424 + 0 +DICTIONARY + 5 +12CA +330 +1F +100 +AcDbDictionary +280 + 1 + 3 +ACAD_LAYOUTSELFREF +360 +20AE + 0 +DICTIONARY + 5 +12CC +330 +1B +100 +AcDbDictionary +280 + 1 + 3 +ACAD_LAYOUTSELFREF +360 +20AD + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +*A1 +350 +739 + 3 +*A2 +350 +1AE4 + 3 +*A3 +350 +1AE5 + 0 +DICTIONARY + 5 +1A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 0 +ACDBDICTIONARYWDFLT + 5 +E +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Normal +350 +F +100 +AcDbDictionaryWithDefault +340 +F + 0 +XRECORD + 5 +3A2 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbXrecord + 90 + 990106 + 3 + + 60 + 0 + 61 + 0 + 62 + 1 + 63 + 3 + 64 + 0 + 65 + 0 + 66 + 0 + 67 + 3 + 68 + 1 + 69 + 0 + 70 + 0 + 71 + 0 + 72 + 0 + 40 +843.2087290138007 +170 + 0 + 0 +DICTIONARY + 5 +208D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +CEPSNTYPE +350 +2097 + 3 +FINGERPRINTGUID +350 +2098 + 3 +HYPERLINKBASE +350 +2090 + 3 +INSUNITS +350 +2096 + 3 +LAYOUTDICT +350 +2092 + 3 +LWETCUNION +350 +2095 + 3 +PLOTSETDICT +350 +2093 + 3 +PLOTSTYLNAMDICT +350 +2094 + 3 +PSVPSCALE +350 +209A + 3 +PUCSBASE +350 +209D + 3 +PUCSORGBACK +350 +20A3 + 3 +PUCSORGBOTTOM +350 +209F + 3 +PUCSORGFRONT +350 +20A2 + 3 +PUCSORGLEFT +350 +20A0 + 3 +PUCSORGRIGHT +350 +20A1 + 3 +PUCSORGTOP +350 +209E + 3 +PUCSORTHOREF +350 +209B + 3 +PUCSORTHOVIEW +350 +209C + 3 +STYLESHEET +350 +2091 + 3 +TSTACKALIGN +350 +208E + 3 +TSTACKSIZE +350 +208F + 3 +UCSBASE +350 +20A6 + 3 +UCSORGBACK +350 +20AC + 3 +UCSORGBOTTOM +350 +20A8 + 3 +UCSORGFRONT +350 +20AB + 3 +UCSORGLEFT +350 +20A9 + 3 +UCSORGRIGHT +350 +20AA + 3 +UCSORGTOP +350 +20A7 + 3 +UCSORTHOREF +350 +20A4 + 3 +UCSORTHOVIEW +350 +20A5 + 3 +VERSIONGUID +350 +2099 + 0 +DICTIONARY + 5 +424 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary + 3 +SORTENTS +350 +425 + 0 +XRECORD + 5 +20AE +102 +{ACAD_REACTORS +330 +12CA +102 +} +330 +12CA +100 +AcDbXrecord +340 +1F + 0 +XRECORD + 5 +20AD +102 +{ACAD_REACTORS +330 +12CC +102 +} +330 +12CC +100 +AcDbXrecord +340 +1B + 0 +GROUP + 5 +739 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 +340 +736 +340 +735 +340 +731 +340 +732 +340 +737 +340 +730 + 0 +GROUP + 5 +1AE4 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 + 0 +GROUP + 5 +1AE5 +102 +{ACAD_REACTORS +330 +D +102 +} +330 +D +100 +AcDbGroup +300 + + 70 + 1 + 71 + 1 + 0 +MLINESTYLE + 5 +18 +102 +{ACAD_REACTORS +330 +17 +102 +} +330 +17 +100 +AcDbMlineStyle + 2 +STANDARD + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 2 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 0 +ACDBPLACEHOLDER + 5 +F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E +100 +AcDbPlaceHolder +280 + 0 + 0 +XRECORD + 5 +2097 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 90 + 0 + 0 +XRECORD + 5 +2098 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 1 +{79020B87-180D-11D5-B9BB-0004ACE8BA24} + 0 +XRECORD + 5 +2090 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 1 + + 0 +XRECORD + 5 +2096 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 90 + 4 + 0 +XRECORD + 5 +2092 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +1A + 0 +XRECORD + 5 +2095 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 90 + 10781 + 0 +XRECORD + 5 +2093 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +19 + 0 +XRECORD + 5 +2094 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +E + 0 +XRECORD + 5 +209A +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 40 +0.0 + 0 +XRECORD + 5 +209D +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +0 + 0 +XRECORD + 5 +20A3 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +209F +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A2 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A0 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A1 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +209E +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +209B +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +0 + 0 +XRECORD + 5 +209C +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 70 + 0 + 0 +XRECORD + 5 +2091 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 1 + + 0 +XRECORD + 5 +208E +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 90 + 1 + 0 +XRECORD + 5 +208F +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 90 + 70 + 0 +XRECORD + 5 +20A6 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +0 + 0 +XRECORD + 5 +20AC +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A8 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20AB +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A9 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20AA +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A7 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +XRECORD + 5 +20A4 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord +340 +0 + 0 +XRECORD + 5 +20A5 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 70 + 0 + 0 +XRECORD + 5 +2099 +102 +{ACAD_REACTORS +330 +208D +102 +} +330 +208D +100 +AcDbXrecord + 1 +{204F4E54-184B-11D5-B9BB-0004ACE8BA24} + 0 +DICTIONARYVAR + 5 +425 +102 +{ACAD_REACTORS +330 +424 +102 +} +330 +424 +100 +DictionaryVariables +280 + 0 + 1 +96 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test_extrude.dxf b/share/extensions/tests/data/io/test_extrude.dxf new file mode 100644 index 0000000..96ae975 --- /dev/null +++ b/share/extensions/tests/data/io/test_extrude.dxf @@ -0,0 +1,20478 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1027 + 9 +$ACADMAINTVER + 70 + 125 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$LASTSAVEDBY + 1 +Administrator + 9 +$REQUIREDVERSIONS +160 + 0 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +0.0 + 20 +0.0 + 30 +-12.5 + 9 +$EXTMAX + 10 +297.0 + 20 +210.0 + 30 +17.5 + 9 +$LIMMIN + 10 +0.0 + 20 +0.0 + 9 +$LIMMAX + 10 +297.0 + 20 +210.0 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +0.75 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +3.5 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +3.5 + 9 +$DIMEXO + 40 +2.0 + 9 +$DIMDLI + 40 +9.899495 + 9 +$DIMRND + 40 +0.0 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +2.0 + 9 +$DIMTP + 40 +0.1 + 9 +$DIMTM + 40 +0.1 + 9 +$DIMTXT + 40 +3.5 + 9 +$DIMCEN + 40 +0.0 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 12 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 +in + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 4 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +ISO-25 + 9 +$DIMCLRD + 70 + 256 + 9 +$DIMCLRE + 70 + 256 + 9 +$DIMCLRT + 70 + 256 + 9 +$DIMTFAC + 40 +0.714 + 9 +$DIMGAP + 40 +1.5 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 12 + 9 +$DIMALTZ + 70 + 12 + 9 +$DIMALTTZ + 70 + 12 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 4 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 2 + 9 +$DIMALTRND + 40 +0.0 + 9 +$DIMAZIN + 70 + 3 + 9 +$DIMDSEP + 70 + 46 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1.0 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.785398 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$DIMTXTDIRECTION + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +0.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 0 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0.0 + 9 +$CHAMFERB + 40 +0.0 + 9 +$CHAMFERC + 40 +0.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2459076.906840278 + 9 +$TDUCREATE + 40 +2459076.823506944 + 9 +$TDUPDATE + 40 +2459076.906840278 + 9 +$TDUUPDATE + 40 +2459076.823506944 + 9 +$TDINDWG + 40 +0.0000000000 + 9 +$TDUSRTIMER + 40 +0.0000000000 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 6 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +181 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +1.000000E+20 + 20 +1.000000E+20 + 30 +1.000000E+20 + 9 +$PEXTMAX + 10 +-1.000000E+20 + 20 +-1.000000E+20 + 30 +-1.000000E+20 + 9 +$PLIMMIN + 10 +0.0 + 20 +0.0 + 9 +$PLIMMAX + 10 +12.0 + 20 +9.0 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20.0 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 4 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$FINGERPRINTGUID + 2 +{A2130B74-5662-6D49-A155-A5BD296E74C2} + 9 +$VERSIONGUID + 2 +{284F1E24-B7BE-1642-9CB5-EA0869993D28} + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +280 + 2 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 2 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50.0 + 9 +$CAMERAHEIGHT + 40 +0.0 + 9 +$STEPSPERSEC + 40 +2.0 + 9 +$STEPSIZE + 40 +6.0 + 9 +$3DDWFPREC + 40 +2.0 + 9 +$PSOLWIDTH + 40 +5.0 + 9 +$PSOLHEIGHT + 40 +80.0 + 9 +$LOFTANG1 + 40 +1.570796 + 9 +$LOFTANG2 + 40 +1.570796 + 9 +$LOFTMAG1 + 40 +0.0 + 9 +$LOFTMAG2 + 40 +0.0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +37.795 + 9 +$LONGITUDE + 40 +-122.394 + 9 +$NORTHDIRECTION + 40 +0.0 + 9 +$TIMEZONE + 70 + -8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$CMATERIAL +347 +11 + 9 +$SOLIDHIST +280 + 0 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$INTERFEREOBJVS +345 +33 + 9 +$INTERFEREVPVS +346 +30 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 + 0 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MATERIAL + 2 +AcDbMaterial + 3 +ObjectDBX Classes + 90 + 1153 + 91 + 3 +280 + 0 +281 + 0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 + 4095 + 91 + 24 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 + 1153 + 91 + 19 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 + 4095 + 91 + 2 +280 + 0 +281 + 0 + 0 +CLASS + 1 +MLEADERSTYLE + 2 +AcDbMLeaderStyle + 3 +ACDB_MLEADERSTYLE_CLASS + 90 + 4095 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBSECTIONVIEWSTYLE + 2 +AcDbSectionViewStyle + 3 +ObjectDBX Classes + 90 + 1025 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBDETAILVIEWSTYLE + 2 +AcDbDetailViewStyle + 3 +ObjectDBX Classes + 90 + 1025 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACMESCOPE + 2 +AcMeScope + 3 +AcMeServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACMECOMMANDHISTORY + 2 +AcMeCommandHistory + 3 +AcMeServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACIMSYSVARMAN + 2 +AcImSysVarManager + 3 +AcMeServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACIMINTSYSVAR + 2 +AcImIntSysVar + 3 +AcMeServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACMESTATEMGR + 2 +AcMeStateMgr + 3 +AcMeServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACGREFMASTER + 2 +AcGrefMaster + 3 +AcAttribServices + 90 + 1024 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SORTENTSTABLE + 2 +AcDbSortentsTable + 3 +ObjectDBX Classes + 90 + 0 + 91 + 5 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACAD_TABLE + 2 +AcDbTable + 3 +ObjectDBX Classes + 90 + 1025 + 91 + 1 +280 + 0 +281 + 1 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 + 0 + 91 + 6 +280 + 0 +281 + 0 + 0 +CLASS + 1 +CELLSTYLEMAP + 2 +AcDbCellStyleMap + 3 +ObjectDBX Classes + 90 + 1152 + 91 + 2 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLECONTENT + 2 +AcDbTableContent + 3 +ObjectDBX Classes + 90 + 1152 + 91 + 1 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLEGEOMETRY + 2 +AcDbTableGeometry + 3 +ObjectDBX Classes + 90 + 1152 + 91 + 1 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 +1001 +ACAD +1000 +DbSaveVer +1071 + 223 + 0 +VPORT + 5 +57 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +148.5 + 22 +105.0 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +0.0 + 25 +0.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +210.0 + 41 +2.302158 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 20000 + 73 + 1 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 + 0 +146 +0.0 +348 +2F + 60 + 3 + 61 + 5 +292 + 1 +282 + 1 +141 +0.0 +142 +0.0 + 63 + 250 +421 + 3355443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 16 + 0 +LTYPE + 5 +5B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +5C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +5D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +81 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +HIDDEN + 70 + 0 + 3 +Hidden __ __ __ __ __ __ __ __ __ __ __ __ __ __ + 72 + 65 + 73 + 2 + 40 +9.525 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +82 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +PHANTOM2 + 70 + 0 + 3 +Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +15.875 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +83 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +9E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +9F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +AM_ISO02W050 + 70 + 0 + 3 +__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ + 72 + 65 + 73 + 2 + 40 +7.5 + 49 +6.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 0 +LTYPE + 5 +A0 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +AM_ISO08W050 + 70 + 0 + 3 +____ . ____ . ____ . ____ . ____ . ____ . ____ + 72 + 65 + 73 + 4 + 40 +18.0 + 49 +12.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 49 +3.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 0 +LTYPE + 5 +A1 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +AM_ISO09W050 + 70 + 0 + 3 +_____ . . _____ . . _____ . . ____ .. ____ + 72 + 65 + 73 + 6 + 40 +22.5 + 49 +12.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 49 +3.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 49 +3.0 + 74 + 0 + 49 +-1.5 + 74 + 0 + 0 +LTYPE + 5 +A2 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Amconstr + 70 + 0 + 3 +_______________________ + 72 + 65 + 73 + 2 + 40 +9999.0 + 49 +9999.0 + 74 + 0 + 49 +0.0 + 74 + 0 + 0 +LTYPE + 5 +A3 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +AM_ISO08W050x2 + 70 + 0 + 3 +__ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +9.0 + 49 +6.0 + 74 + 0 + 49 +-0.75 + 74 + 0 + 49 +1.5 + 74 + 0 + 49 +-0.75 + 74 + 0 + 0 +LTYPE + 5 +A4 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +AM_ISO02W050x2 + 70 + 0 + 3 + _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +3.75 + 49 +3.0 + 74 + 0 + 49 +-0.75 + 74 + 0 + 0 +LTYPE + 5 +A5 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Amzigzag + 70 + 0 + 3 +/\/-/\/-/\/-/\/-/\/-/\/ + 72 + 65 + 73 + 2 + 40 +11.0001 + 49 +0.0001 + 74 + 4 + 75 + 136 +340 +9B + 46 +0.04 + 50 +0.0 + 44 +0.0 + 45 +0.0 + 49 +-11.0 + 74 + 0 + 0 +LTYPE + 5 +A6 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ACISOWELD + 70 + 0 + 3 +_ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.0 + 49 +2.0 + 74 + 0 + 49 +-1.0 + 74 + 0 + 0 +LTYPE + 5 +A7 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ACISOTGL + 70 + 0 + 3 +_ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +3.0 + 49 +2.0 + 74 + 0 + 49 +-1.0 + 74 + 0 + 0 +LTYPE + 5 +A8 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ACISOTGB + 70 + 0 + 3 +__ . . __ . . + 72 + 65 + 73 + 6 + 40 +9.0 + 49 +4.0 + 74 + 0 + 49 +-1.0 + 74 + 0 + 49 +1.0 + 74 + 0 + 49 +-1.0 + 74 + 0 + 49 +1.0 + 74 + 0 + 49 +-1.0 + 74 + 0 + 0 +LTYPE + 5 +A9 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ACAD_VIEWBORDER_LINETYPE + 70 + 0 + 3 +Dashed line in view border + 72 + 83 + 73 + 2 + 40 +10.0 + 49 +1.59 + 74 + 0 + 49 +-6.35 + 74 + 0 +1001 +ACAD_EXEMPT_FROM_CAD_STANDARDS +1070 + 1 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 8 + 0 +LAYER + 5 +54 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +Continuous +370 + -3 +390 +F +347 +21 +348 +0 +1001 +AcAecLayerStandard +1000 + +1000 + + 0 +LAYER + 5 +79 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Defpoints + 70 + 0 + 62 + 7 + 6 +Continuous +290 + 0 +370 + -3 +390 +F +347 +21 +348 +0 +1001 +AcAecLayerStandard +1000 + +1000 + + 0 +LAYER + 5 +B6 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Visible + 70 + 0 + 62 + 7 + 6 +Continuous +370 + 35 +390 +F +347 +21 +348 +0 + 0 +LAYER + 5 +FB +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Border + 70 + 0 + 62 + 7 + 6 +Continuous +370 + 25 +390 +F +347 +21 +348 +0 +1001 +AcAecLayerStandard +1000 + +1000 + +1001 +AcCmTransparency +1071 + 0 + 0 +LAYER + 5 +112 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Annotations + 70 + 0 + 62 + 7 + 6 +Continuous +370 + 18 +390 +F +347 +21 +348 +0 + 0 +LAYER + 5 +118 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +BOM + 70 + 0 + 62 + 7 + 6 +Continuous +370 + 18 +390 +F +347 +21 +348 +0 + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +STYLE + 5 +55 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +3.5 + 3 +Arial.ttf + 4 + +1001 +ACAD +1000 +Arial +1071 + 34 + 0 +STYLE + 5 +5A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Annotative + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +0.2 + 3 +txt + 4 + +1001 +AcadAnnotative +1000 +AnnotativeData +1002 +{ +1070 + 1 +1070 + 1 +1002 +} + 0 +STYLE + 5 +9A +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +FusionTitle + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +Arial Unicode.ttf + 4 + +1001 +ACAD +1000 +Arial Unicode MS +1071 + 34 + 0 +STYLE + 5 +9B +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 + + 70 + 1 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +10.0 + 3 +genltshp.shx + 4 + + 0 +STYLE + 5 +9C +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +ACISOGDT + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +10.0 + 3 +amgdt.shx + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 27 + 0 +APPID + 5 +56 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +5E +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +AcadAnnotative + 70 + 0 + 0 +APPID + 5 +78 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_PSEXT + 70 + 0 + 0 +APPID + 5 +7A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +MCAD_NO_VIS + 70 + 0 + 0 +APPID + 5 +7B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_TEMP_GRAPHIC + 70 + 0 + 0 +APPID + 5 +84 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIMJAG + 70 + 0 + 0 +APPID + 5 +85 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIMTALN + 70 + 0 + 0 +APPID + 5 +86 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_NAV_VCDISPLAY + 70 + 0 + 0 +APPID + 5 +87 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +AcAecLayerStandard + 70 + 0 + 0 +APPID + 5 +88 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +AcCmTransparency + 70 + 0 + 0 +APPID + 5 +89 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +AcDbDynamicBlockGUID + 70 + 0 + 0 +APPID + 5 +8A +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_EXEMPT_FROM_CAD_STANDARDS + 70 + 0 + 0 +APPID + 5 +8B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIMBREAK + 70 + 0 + 0 +APPID + 5 +8C +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIMRADIAL_EXTENSION + 70 + 0 + 0 +APPID + 5 +8D +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +FUSIONTITLEBLOCK + 70 + 0 + 0 +APPID + 5 +8E +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +FUSIONCURRENTTITLEBLOCK + 70 + 0 + 0 +APPID + 5 +8F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +AcSynergy + 70 + 0 + 0 +APPID + 5 +90 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +GENIUS_GENSCREG_15 + 70 + 0 + 0 +APPID + 5 +91 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +GENIUS_GENOBJ-N-SDF_13 + 70 + 0 + 0 +APPID + 5 +92 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +GENIUS_GENODEF_13 + 70 + 0 + 0 +APPID + 5 +93 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DIMASSOC_CALC_DIMLFAC + 70 + 0 + 0 +APPID + 5 +94 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DIMASSOC_DIMLFAC + 70 + 0 + 0 +APPID + 5 +95 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DIMASSOC_OVERRIDDEN_DIMLFAC + 70 + 0 + 0 +APPID + 5 +96 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +SYNERGY_BODY_TBR_ID + 70 + 0 + 0 +APPID + 5 +97 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +FusionCutBodyId + 70 + 0 + 0 +APPID + 5 +98 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_TSTYLE_FLIPHORIZ + 70 + 0 + 0 +APPID + 5 +99 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACATTRIBSERVICES + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 3 +100 +AcDbDimStyleTable + 71 + 1 +340 +AC + 0 +DIMSTYLE +105 +58 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 43 +9.899495 + 78 + 12 + 79 + 3 +140 +3.5 +179 + 2 +271 + 2 +272 + 2 +284 + 12 +285 + 12 +286 + 12 +340 +55 + 0 +DIMSTYLE +105 +59 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Annotative + 70 + 0 + 40 +0.0 + 41 +2.5 + 42 +0.625 + 43 +9.899495 + 44 +1.25 + 73 + 0 + 74 + 0 + 77 + 1 + 78 + 12 + 79 + 3 +140 +3.5 +141 +2.5 +143 +0.03937 +147 +0.625 +171 + 3 +172 + 1 +179 + 2 +271 + 2 +272 + 2 +274 + 3 +278 + 44 +283 + 0 +284 + 12 +285 + 12 +286 + 12 +340 +55 +1001 +AcadAnnotative +1000 +AnnotativeData +1002 +{ +1070 + 1 +1070 + 1 +1002 +} + 0 +DIMSTYLE +105 +AC +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 4 +in + 41 +3.5 + 42 +2.0 + 43 +9.899495 + 44 +2.0 + 47 +0.1 + 48 +0.1 + 73 + 0 + 74 + 0 + 77 + 1 + 78 + 12 + 79 + 3 +140 +3.5 +141 +0.0 +143 +0.03937 +146 +0.714 +147 +1.5 +171 + 4 +172 + 1 +176 + 256 +177 + 256 +178 + 256 +179 + 2 +271 + 2 +272 + 2 +274 + 4 +283 + 0 +284 + 12 +285 + 12 +286 + 12 +340 +55 +1001 +ACAD_DSTYLE_DIMBREAK +1070 + 391 +1040 +3.5 +1001 +ACAD_DSTYLE_DIMJAG +1070 + 388 +1040 +1.5 +1001 +ACAD_DSTYLE_DIMTALN +1070 + 392 +1070 + 1 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 5 + 0 +BLOCK_RECORD + 5 +70 +102 +{ACAD_XDICTIONARY +360 +AF +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +73 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +6C +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +6F + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +74 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space0 +340 +77 + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +FC +102 +{ACAD_XDICTIONARY +360 +FD +102 +} +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +ISO_A4(L)_SHEET +340 +0 +310 +2800000020000000200000000100080000000000000400000000000000000000000000000000000000000000000080000080000000808000800000008000800080800000C0C0C000C0DCC000F0CAA6000020400000206000002080000020A0000020C0000020E00000400000004020000040400000406000004080000040A0 +310 +000040C0000040E00000600000006020000060400000606000006080000060A0000060C0000060E00000800000008020000080400000806000008080000080A0000080C0000080E00000A0000000A0200000A0400000A0600000A0800000A0A00000A0C00000A0E00000C0000000C0200000C0400000C0600000C0800000C0 +310 +A00000C0C00000C0E00000E0000000E0200000E0400000E0600000E0800000E0A00000E0C00000E0E00040000000400020004000400040006000400080004000A0004000C0004000E00040200000402020004020400040206000402080004020A0004020C0004020E000404000004040200040404000404060004040800040 +310 +40A0004040C0004040E00040600000406020004060400040606000406080004060A0004060C0004060E00040800000408020004080400040806000408080004080A0004080C0004080E00040A0000040A0200040A0400040A0600040A0800040A0A00040A0C00040A0E00040C0000040C0200040C0400040C0600040C08000 +310 +40C0A00040C0C00040C0E00040E0000040E0200040E0400040E0600040E0800040E0A00040E0C00040E0E00080000000800020008000400080006000800080008000A0008000C0008000E00080200000802020008020400080206000802080008020A0008020C0008020E00080400000804020008040400080406000804080 +310 +008040A0008040C0008040E00080600000806020008060400080606000806080008060A0008060C0008060E00080800000808020008080400080806000808080008080A0008080C0008080E00080A0000080A0200080A0400080A0600080A0800080A0A00080A0C00080A0E00080C0000080C0200080C0400080C0600080C0 +310 +800080C0A00080C0C00080C0E00080E0000080E0200080E0400080E0600080E0800080E0A00080E0C00080E0E000C0000000C0002000C0004000C0006000C0008000C000A000C000C000C000E000C0200000C0202000C0204000C0206000C0208000C020A000C020C000C020E000C0400000C0402000C0404000C0406000C0 +310 +408000C040A000C040C000C040E000C0600000C0602000C0604000C0606000C0608000C060A000C060C000C060E000C0800000C0802000C0804000C0806000C0808000C080A000C080C000C080E000C0A00000C0A02000C0A04000C0A06000C0A08000C0A0A000C0A0C000C0A0E000C0C00000C0C02000C0C04000C0C06000 +310 +C0C08000C0C0A000F0FBFF00A4A0A000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF0049494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949 +310 +494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949FFFFFFFFFFFFFFFFFFFFFFFFFF +310 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4949FFFF494949494949494949494949FF49494949494949494949494949FFFF494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF49494949494949494949 +310 +49494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF494949494949494949 +310 +4949494949494949494949494949494949FF49494949FFFF494949494949494949494949494949494949494949494949FFFF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949 +310 +494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF4949494949494949494949494949494949494949494949494949FF49494949FF49494949494949 +310 +49494949494949494949494949494949494949FF49494949FF494949494949494949494949FF49494949494949494949494949FF494949FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4949FFFFFF494949494949494949494949494949494949494949494949FFFFFF49494949494949494949 +310 +49494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949 +310 +4949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949 +102 +{BLKREFS +331 +FA +102 +} + 70 + 4 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +119 +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*T4 +340 +0 +102 +{BLKREFS +331 +117 +102 +} + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +71 +330 +70 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +72 +330 +70 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +6D +330 +6C +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +6E +330 +6C +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +75 +330 +74 +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space0 + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space0 + 1 + + 0 +ENDBLK + 5 +76 +330 +74 +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +FF +330 +FC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +ISO_A4(L)_SHEET + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +ISO_A4(L)_SHEET + 1 + + 0 +LINE + 5 +100 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +0.0 + 20 +210.0 + 30 +0.0 + 11 +0.0 + 21 +195.0 + 31 +0.0 + 0 +LINE + 5 +101 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +0.0 + 20 +15.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +102 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +15.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +103 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +282.0 + 20 +0.0 + 30 +0.0 + 11 +297.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +104 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +297.0 + 20 +0.0 + 30 +0.0 + 11 +297.0 + 21 +15.0 + 31 +0.0 + 0 +LINE + 5 +105 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +297.0 + 20 +195.0 + 30 +0.0 + 11 +297.0 + 21 +210.0 + 31 +0.0 + 0 +LINE + 5 +106 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +287.0 + 20 +10.0 + 30 +0.0 + 11 +287.0 + 21 +200.0 + 31 +0.0 + 0 +LINE + 5 +107 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +297.0 + 20 +210.0 + 30 +0.0 + 11 +282.0 + 21 +210.0 + 31 +0.0 + 0 +LINE + 5 +108 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +15.0 + 20 +210.0 + 30 +0.0 + 11 +0.0 + 21 +210.0 + 31 +0.0 + 0 +LINE + 5 +109 +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +287.0 + 20 +10.0 + 30 +0.0 + 11 +20.0 + 21 +10.0 + 31 +0.0 + 0 +LINE + 5 +10A +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +15.0 + 20 +100.0 + 30 +0.0 + 11 +25.0 + 21 +100.0 + 31 +0.0 + 0 +LINE + 5 +10B +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +292.0 + 20 +100.0 + 30 +0.0 + 11 +282.0 + 21 +100.0 + 31 +0.0 + 0 +LINE + 5 +10C +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +148.5 + 20 +205.0 + 30 +0.0 + 11 +148.5 + 21 +195.0 + 31 +0.0 + 0 +LINE + 5 +10D +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +148.5 + 20 +5.0 + 30 +0.0 + 11 +148.5 + 21 +15.0 + 31 +0.0 + 0 +LINE + 5 +10E +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +287.0 + 20 +200.0 + 30 +0.0 + 11 +20.0 + 21 +200.0 + 31 +0.0 + 0 +LINE + 5 +10F +330 +FC +100 +AcDbEntity + 8 +Border +100 +AcDbLine + 10 +20.0 + 20 +200.0 + 30 +0.0 + 11 +20.0 + 21 +10.0 + 31 +0.0 + 0 +ENDBLK + 5 +110 +330 +FC +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +11A +330 +119 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*T4 + 70 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*T4 + 1 + + 0 +MTEXT + 5 +11B +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +52.5 + 20 +-3.833333 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 5 + 72 + 5 + 1 +W + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +11C +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +87.5 + 20 +-3.833333 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 5 + 72 + 5 + 1 +H + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +11D +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +17.5 + 20 +-11.5 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 5 + 72 + 5 + 1 +viewing area + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +11E +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +52.5 + 20 +-11.5 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 5 + 72 + 5 + 1 +71.35 + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +11F +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +87.5 + 20 +-11.5 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 5 + 72 + 5 + 1 +18.1 + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +120 +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +17.5 + 20 +-16.833333 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 2 + 72 + 5 + 1 +recess + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +121 +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +52.5 + 20 +-16.833333 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 2 + 72 + 5 + 1 +73.35 + 73 + 1 + 44 +1.0 + 0 +MTEXT + 5 +122 +330 +119 +100 +AcDbEntity + 8 +BOM + 62 + 0 +440 + 16777216 +100 +AcDbMText + 10 +87.5 + 20 +-16.833333 + 30 +0.0 + 40 +3.5 + 41 +32.0 + 46 +0.0 + 71 + 2 + 72 + 5 + 1 +20.1 + 73 + 1 + 44 +1.0 + 0 +LINE + 5 +123 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +105.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 5 +124 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +0.0 + 20 +-7.666667 + 30 +0.0 + 11 +105.0 + 21 +-7.666667 + 31 +0.0 + 0 +LINE + 5 +125 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +0.0 + 20 +-15.333333 + 30 +0.0 + 11 +105.0 + 21 +-15.333333 + 31 +0.0 + 0 +LINE + 5 +126 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +0.0 + 20 +-23.0 + 30 +0.0 + 11 +105.0 + 21 +-23.0 + 31 +0.0 + 0 +LINE + 5 +127 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +-23.0 + 31 +0.0 + 0 +LINE + 5 +128 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +35.0 + 20 +0.0 + 30 +0.0 + 11 +35.0 + 21 +-23.0 + 31 +0.0 + 0 +LINE + 5 +129 +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +70.0 + 20 +0.0 + 30 +0.0 + 11 +70.0 + 21 +-23.0 + 31 +0.0 + 0 +LINE + 5 +12A +330 +119 +100 +AcDbEntity + 8 +BOM + 6 +ByBlock + 62 + 0 +440 + 16777216 +370 + -2 +100 +AcDbLine + 10 +105.0 + 20 +0.0 + 30 +0.0 + 11 +105.0 + 21 +-23.0 + 31 +0.0 + 0 +LINE + 5 +12B +330 +119 +100 +AcDbEntity + 8 +Defpoints + 62 + 8 +440 + 16777216 + 60 + 1 +370 + 0 +100 +AcDbLine + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +ENDBLK + 5 +12C +330 +119 +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +INSERT + 5 +FA +330 +70 +100 +AcDbEntity + 8 +Border +100 +AcDbBlockReference + 2 +ISO_A4(L)_SHEET + 10 +0.0 + 20 +0.0 + 30 +0.0 + 0 +MTEXT + 5 +111 +330 +70 +100 +AcDbEntity + 8 +Annotations +100 +AcDbMText + 10 +135.305605 + 20 +104.320338 + 30 +0.0 + 40 +3.5 + 41 +87.871947 + 46 +0.0 + 71 + 1 + 72 + 5 + 1 +back view + 73 + 1 + 44 +1.0 +1001 +ACAD +1000 +ACAD_MTEXT_COLUMN_INFO_BEGIN +1070 + 75 +1070 + 2 +1070 + 79 +1070 + 0 +1070 + 76 +1070 + 1 +1070 + 78 +1070 + 0 +1070 + 48 +1040 +87.871947 +1070 + 49 +1040 +17.5 +1070 + 50 +1070 + 1 +1040 +0.0 +1000 +ACAD_MTEXT_COLUMN_INFO_END + 0 +MTEXT + 5 +113 +330 +70 +100 +AcDbEntity + 8 +Annotations +100 +AcDbMText + 10 +243.853306 + 20 +197.026225 + 30 +0.0 + 40 +3.5 + 41 +46.520442 + 46 +0.0 + 71 + 1 + 72 + 5 + 1 +1:1 for DXF export + 73 + 1 + 44 +1.0 +1001 +ACAD +1000 +ACAD_MTEXT_COLUMN_INFO_BEGIN +1070 + 75 +1070 + 2 +1070 + 79 +1070 + 0 +1070 + 76 +1070 + 1 +1070 + 78 +1070 + 0 +1070 + 48 +1040 +46.520442 +1070 + 49 +1040 +17.5 +1070 + 50 +1070 + 1 +1040 +9.820982 +1000 +ACAD_MTEXT_COLUMN_INFO_END + 0 +MTEXT + 5 +114 +330 +70 +100 +AcDbEntity + 8 +Annotations +100 +AcDbMText + 10 +97.218693 + 20 +179.083151 + 30 +0.0 + 40 +3.5 + 41 +53.593727 + 46 +0.0 + 71 + 1 + 72 + 5 + 1 +front view + 73 + 1 + 44 +1.0 +1001 +ACAD +1000 +ACAD_MTEXT_COLUMN_INFO_BEGIN +1070 + 75 +1070 + 2 +1070 + 79 +1070 + 0 +1070 + 76 +1070 + 1 +1070 + 78 +1070 + 0 +1070 + 48 +1040 +53.593727 +1070 + 49 +1040 +17.5 +1070 + 50 +1070 + 1 +1040 +0.0 +1000 +ACAD_MTEXT_COLUMN_INFO_END + 0 +MTEXT + 5 +115 +330 +70 +100 +AcDbEntity + 8 +Annotations +100 +AcDbMText + 10 +105.108125 + 20 +52.122302 + 30 +0.0 + 40 +3.5 + 41 +99.57007 + 46 +0.0 + 71 + 1 + 72 + 5 + 1 +internal hole is the viewing area, the second outline (2mm inner) is the recess area to make the glass not fall + 73 + 1 + 44 +1.0 +1001 +ACAD +1000 +ACAD_MTEXT_COLUMN_INFO_BEGIN +1070 + 75 +1070 + 2 +1070 + 79 +1070 + 0 +1070 + 76 +1070 + 1 +1070 + 78 +1070 + 0 +1070 + 48 +1040 +99.57007 +1070 + 49 +1040 +17.5 +1070 + 50 +1070 + 1 +1040 +0.0 +1000 +ACAD_MTEXT_COLUMN_INFO_END + 0 +MTEXT + 5 +116 +330 +70 +100 +AcDbEntity + 8 +Annotations +100 +AcDbMText + 10 +72.734248 + 20 +137.48784 + 30 +0.0 + 40 +3.5 + 41 +75.629727 + 46 +0.0 + 71 + 1 + 72 + 5 + 1 +{\fArial|b0|i0|c0|p0;L FUEL R\POIL PRESS L VAC R VOLTS} + 73 + 1 + 44 +1.0 +1001 +ACAD +1000 +ACAD_MTEXT_COLUMN_INFO_BEGIN +1070 + 75 +1070 + 2 +1070 + 79 +1070 + 0 +1070 + 76 +1070 + 1 +1070 + 78 +1070 + 0 +1070 + 48 +1040 +75.629727 +1070 + 49 +1040 +17.5 +1070 + 50 +1070 + 1 +1040 +9.545318 +1000 +ACAD_MTEXT_COLUMN_INFO_END + 0 +ACAD_TABLE + 5 +117 +102 +{ACAD_XDICTIONARY +360 +178 +102 +} +330 +70 +100 +AcDbEntity + 8 +BOM +160 + 3028 +310 +D40B000046000000880000001D000000000000000000F03F0000000000000000000000000000000020B2E61951A066400000000000000000000000000000F03F000000000000000076E52E9B5A19674000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000 +310 +000000000000000000000000000000F03F0C00000016000000070000C30C00000017000000120000000C0000001200000000000000B4000000260000008B8F299D5618494040555555555516C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000 +310 +0000000000005700000001000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000002200000041007200690061006C00000000000000000000000C00000016000000070000C30C0000001700000012 +310 +0000000C0000001200000000000000B400000026000000EBF6E14D156F554040555555555516C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000004800000001000000010000000000000000000C40000000000000F03F00000000 +310 +00000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000002200000041007200690061006C00000000006F7200006F6E0C00000016000000070000C30C00000017000000120000000C0000001200000000000000CC0000002600000074860BEB6BC70E408A79F414947829 +310 +C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000760069006500770069006E00670020006100720065006100000000000C000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F0000 +310 +0000000000000000000000000000000000000000000000000000010000002200000041007200690061006C000000000000000000554D0C00000016000000070000C30C00000017000000120000000C0000001200000000000000BC0000002600000060F2D2F49F2E474098311AB9C6732AC000000000000000000000000000 +310 +0000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000370031002E0033003500000005000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000001000000 +310 +2200000041007200690061006C00000000000000000000000C00000016000000070000C30C00000017000000120000000C0000001200000000000000BC00000026000000DF805B422ABB544051E2D82F63742AC0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000 +310 +00000000000000000000000000310038002E0031000000000004000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000002200000041007200690061006C00000000000000000000000C0000001600 +310 +0000070000C30C00000017000000120000000C0000001200000000000000C00000002600000017C0A2065178244050555555555534C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000007200650063006500730073000000000006 +310 +000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000002200000041007200690061006C0000000000000000000C000C00000016000000070000C30C00000017000000120000000C00000012000000 +310 +00000000BC0000002600000060F2D2F49F2E4740A279CD1D005934C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000370033002E0033003500000005000000010000000000000000000C40000000000000F03F00000000000000 +310 +00000000000000F03F00000000000000000000000000000000000000000000000000000000010000002200000041007200690061006C00000000000000000000000C00000016000000070000C30C00000017000000120000000C0000001200000000000000BC000000260000008DD1C8359EC75440A279CD1D005934C00000 +310 +00000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000320030002E0031000000000004000000010000000000000000000C40000000000000F03F0000000000000000000000000000F03F000000000000000000000000000000000000000000 +310 +00000000000000010000002200000041007200690061006C00000000000000000000000C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000000000000000000000000000000000000000000000000000405A40000000000000000000000000 +310 +0000000000000000000000000000000000000000000000000000F03F0C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000000000A0AAAAAAAAAA1EC000000000000000000000000000405A40A0AAAAAAAAAA1EC00000000000000000000000 +310 +00000000000000000000000000000000000000F03F0C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000000000A0AAAAAAAAAA2EC000000000000000000000000000405A40A0AAAAAAAAAA2EC0000000000000000000000000000000000000 +310 +000000000000000000000000F03F0C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000000000F8FFFFFFFFFF36C000000000000000000000000000405A40F8FFFFFFFFFF36C000000000000000000000000000000000000000000000000000 +310 +0000000000F03F0C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000000000000000000000000000000000000000000000000000000000F8FFFFFFFFFF36C0000000000000000000000000000000000000000000000000000000000000F03F +310 +0C00000016000000070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000804140000000000000000000000000000000000000000000804140F8FFFFFFFFFF36C0000000000000000000000000000000000000000000000000000000000000F03F0C000000160000 +310 +00070000C30C00000017000000120000000C00000012000000000000005400000020000000020000000000000000805140000000000000000000000000000000000000000000805140F8FFFFFFFFFF36C0000000000000000000000000000000000000000000000000000000000000F03F0C00000016000000070000C30C00 +310 +000017000000120000000C00000012000000000000005400000020000000020000000000000000405A40000000000000000000000000000000000000000000405A40F8FFFFFFFFFF36C0000000000000000000000000000000000000000000000000000000000000F03F0C00000016000000080000C30C0000001700000000 +310 +0000000C000000120000000000000054000000200000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F080000001F000000 +100 +AcDbBlockReference + 2 +*T4 + 10 +181.0099 + 20 +184.79231 + 30 +0.0 +100 +AcDbTable +280 + 0 +342 +12D +343 +119 + 11 +1.0 + 21 +0.0 + 31 +0.0 + 90 + 20 + 91 + 3 + 92 + 3 + 93 + 1 + 94 + 0 + 95 + 0 + 96 + 0 +280 + 1 +141 +7.666667 +141 +7.666667 +141 +7.666667 +142 +35.0 +142 +35.0 +142 +35.0 +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 5 + 90 + 4 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +W + 94 + 0 +300 + +302 +W +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +H + 94 + 0 +300 + +302 +H +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 1 +178 + 0 +145 +0.0 +170 + 5 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +viewing area + 94 + 0 +300 + +302 +viewing area +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 1 +178 + 0 +145 +0.0 +170 + 5 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +71.35 + 94 + 0 +300 + +302 +71.35 +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 1 +178 + 0 +145 +0.0 +170 + 5 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +18.1 + 94 + 0 +300 + +302 +18.1 +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +recess + 94 + 0 +300 + +302 +recess +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +73.35 + 94 + 0 +300 + +302 +73.35 +304 +ACVALUE_END +171 + 1 +172 + 0 +173 + 0 +174 + 0 +175 + 1 +176 + 1 + 91 + 0 +178 + 0 +145 +0.0 + 92 + 0 +301 +CELL_VALUE + 93 + 6 + 90 + 4 + 1 +20.1 + 94 + 0 +300 + +302 +20.1 +304 +ACVALUE_END +1001 +ACAD_TSTYLE_FLIPHORIZ +1071 + 1 + 0 +LINE + 5 +12F +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +115.497666 + 20 +73.574292 + 30 +17.5 + 11 +115.497666 + 21 +91.024292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +130 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-116.822666 + 20 +73.574292 + 30 +-17.5 + 40 +1.325000000000216 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +270.0 + 51 +360.0 + 0 +LINE + 5 +131 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +187.522666 + 20 +72.249292 + 30 +17.5 + 11 +116.822666 + 21 +72.249292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +132 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-187.522666 + 20 +73.574292 + 30 +-17.5 + 40 +1.324999999999078 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +133 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +188.847666 + 20 +91.024292 + 30 +17.5 + 11 +188.847666 + 21 +73.574292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +134 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-187.522666 + 20 +91.024292 + 30 +-17.5 + 40 +1.324999999999505 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +LINE + 5 +135 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +116.822666 + 20 +92.349292 + 30 +17.5 + 11 +187.522666 + 21 +92.349292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +136 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-116.822666 + 20 +91.024292 + 30 +-17.5 + 40 +1.324999999999931 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +360.0 + 51 +90.0 + 0 +LINE + 5 +137 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +187.522666 + 20 +94.349292 + 30 +17.5 + 11 +116.822666 + 21 +94.349292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +138 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +187.522666 + 20 +91.024292 + 30 +17.5 + 40 +3.325000000000386 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LINE + 5 +139 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +190.847666 + 20 +73.574292 + 30 +17.5 + 11 +190.847666 + 21 +91.024292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +13A +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +187.522666 + 20 +73.574292 + 30 +17.5 + 40 +3.32499999999868 +100 +AcDbArc + 50 +270.0 + 51 +0.0 + 0 +LINE + 5 +13B +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +116.822666 + 20 +70.249292 + 30 +17.5 + 11 +187.522666 + 21 +70.249292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +13C +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +116.822666 + 20 +73.574292 + 30 +17.5 + 40 +3.325000000000102 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +13D +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +113.497666 + 20 +91.024292 + 30 +17.5 + 11 +113.497666 + 21 +73.574292 + 31 +17.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +13E +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +116.822666 + 20 +91.024292 + 30 +17.5 + 40 +3.325000000000102 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +ARC + 5 +13F +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +195.172666 + 20 +76.049292 + 30 +-12.5 + 40 +6.999999999999886 +100 +AcDbArc + 50 +270.0 + 51 +0.0 + 0 +LINE + 5 +140 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +202.172666 + 20 +76.049292 + 30 +-12.5 + 11 +202.172666 + 21 +88.549292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +141 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +195.172666 + 20 +88.549292 + 30 +-12.5 + 40 +7.000000000000454 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LINE + 5 +142 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +195.172666 + 20 +95.549292 + 30 +-12.5 + 11 +109.172666 + 21 +95.549292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +143 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +109.172666 + 20 +88.549292 + 30 +-12.5 + 40 +6.999999999999744 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +LINE + 5 +144 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +102.172666 + 20 +88.549292 + 30 +-12.5 + 11 +102.172666 + 21 +76.049292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +145 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +109.172666 + 20 +76.049292 + 30 +-12.5 + 40 +7.000000000001307 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +146 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +109.172666 + 20 +69.049292 + 30 +-12.5 + 11 +195.172666 + 21 +69.049292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +CIRCLE + 5 +147 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-109.172666 + 20 +82.299292 + 30 +12.5 + 40 +1.999999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +CIRCLE + 5 +148 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-195.172666 + 20 +82.299292 + 30 +12.5 + 40 +1.999999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +149 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-187.522666 + 20 +73.574292 + 30 +12.5 + 40 +0.324999999999136 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +14A +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +187.522666 + 20 +73.249292 + 30 +-12.5 + 11 +116.822666 + 21 +73.249292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +14B +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-116.822666 + 20 +73.574292 + 30 +12.5 + 40 +0.3249999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +270.0 + 51 +360.0 + 0 +LINE + 5 +14C +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +116.497666 + 20 +73.574292 + 30 +-12.5 + 11 +116.497666 + 21 +91.024292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +LINE + 5 +14D +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +187.847666 + 20 +91.024292 + 30 +-12.5 + 11 +187.847666 + 21 +73.574292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +14E +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-187.522666 + 20 +91.024292 + 30 +12.5 + 40 +0.3249999999995623 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +LINE + 5 +14F +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +116.822666 + 20 +91.349292 + 30 +-12.5 + 11 +187.522666 + 21 +91.349292 + 31 +-12.5 +210 +0.0 +220 +0.0 +230 +-1.0 + 0 +ARC + 5 +150 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-116.822666 + 20 +91.024292 + 30 +12.5 + 40 +0.3249999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +ARC + 5 +151 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-72.206569 + 20 +146.705915 + 30 +-16.5 + 40 +0.324999999999136 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +270.0 + 51 +0.0 + 0 +LINE + 5 +152 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +142.906569 + 20 +146.380915 + 30 +16.5 + 11 +72.206569 + 21 +146.380915 + 31 +16.5 + 0 +ARC + 5 +153 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-142.906569 + 20 +146.705915 + 30 +-16.5 + 40 +0.3249999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +154 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +143.231569 + 20 +164.155915 + 30 +16.5 + 11 +143.231569 + 21 +146.705915 + 31 +16.5 + 0 +LINE + 5 +155 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +69.881569 + 20 +164.155915 + 30 +16.5 + 11 +69.881569 + 21 +146.705915 + 31 +16.5 + 0 +LINE + 5 +156 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +71.881569 + 20 +146.705915 + 30 +16.5 + 11 +71.881569 + 21 +164.155915 + 31 +16.5 + 0 +ARC + 5 +157 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +72.206569 + 20 +146.705915 + 30 +16.5 + 40 +2.324999999998738 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +158 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +72.206569 + 20 +144.380915 + 30 +16.5 + 11 +142.906569 + 21 +144.380915 + 31 +16.5 + 0 +ARC + 5 +159 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +142.906569 + 20 +146.705915 + 30 +16.5 + 40 +2.325000000000301 +100 +AcDbArc + 50 +270.0 + 51 +0.0 + 0 +LINE + 5 +15A +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +145.231569 + 20 +146.705915 + 30 +16.5 + 11 +145.231569 + 21 +164.155915 + 31 +16.5 + 0 +ARC + 5 +15B +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-142.906569 + 20 +164.155915 + 30 +-16.5 + 40 +0.3250000000001307 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +ARC + 5 +15C +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +142.906569 + 20 +164.155915 + 30 +16.5 + 40 +2.325000000000159 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LINE + 5 +15D +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +72.206569 + 20 +164.480915 + 30 +16.5 + 11 +142.906569 + 21 +164.480915 + 31 +16.5 + 0 +LINE + 5 +15E +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +142.906569 + 20 +166.480915 + 30 +16.5 + 11 +72.206569 + 21 +166.480915 + 31 +16.5 + 0 +ARC + 5 +15F +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-72.206569 + 20 +164.155915 + 30 +-16.5 + 40 +0.3249999999997044 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +ARC + 5 +160 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +72.206569 + 20 +164.155915 + 30 +16.5 + 40 +2.324999999999306 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +CIRCLE + 5 +161 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +150.556569 + 20 +155.430915 + 30 +14.5 + 40 +1.999999999999886 + 0 +CIRCLE + 5 +162 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +64.556569 + 20 +155.430915 + 30 +14.5 + 40 +1.999999999999886 + 0 +LINE + 5 +163 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +64.556569 + 20 +142.180915 + 30 +14.5 + 11 +150.556569 + 21 +142.180915 + 31 +14.5 + 0 +ARC + 5 +164 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-150.556569 + 20 +149.180915 + 30 +-14.5 + 40 +7.000000000001307 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +180.0 + 51 +270.0 + 0 +LINE + 5 +165 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +157.556569 + 20 +149.180915 + 30 +14.5 + 11 +157.556569 + 21 +161.680915 + 31 +14.5 + 0 +ARC + 5 +166 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-150.556569 + 20 +161.680915 + 30 +-14.5 + 40 +6.999999999999744 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +90.0 + 51 +180.0 + 0 +LINE + 5 +167 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +150.556569 + 20 +168.680915 + 30 +14.5 + 11 +64.556569 + 21 +168.680915 + 31 +14.5 + 0 +ARC + 5 +168 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-64.556569 + 20 +161.680915 + 30 +-14.5 + 40 +7.000000000000454 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +0.0 + 51 +90.0 + 0 +LINE + 5 +169 +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbLine + 10 +57.556569 + 20 +161.680915 + 30 +14.5 + 11 +57.556569 + 21 +149.180915 + 31 +14.5 + 0 +ARC + 5 +16A +330 +70 +100 +AcDbEntity + 8 +Visible +100 +AcDbCircle + 10 +-64.556569 + 20 +149.180915 + 30 +-14.5 + 40 +6.999999999999886 +210 +0.0 +220 +0.0 +230 +-1.0 +100 +AcDbArc + 50 +270.0 + 51 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_COLOR +350 +63 + 3 +ACAD_DETAILVIEWSTYLE +350 +6A + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +62 + 3 +ACAD_MATERIAL +350 +10 + 3 +ACAD_MLEADERSTYLE +350 +66 + 3 +ACAD_MLINESTYLE +350 +5F + 3 +ACAD_PLOTSETTINGS +350 +61 + 3 +ACAD_PLOTSTYLENAME +350 +E + 3 +ACAD_SCALELIST +350 +42 + 3 +ACAD_SECTIONVIEWSTYLE +350 +68 + 3 +ACAD_TABLESTYLE +350 +64 + 3 +ACAD_VISUALSTYLE +350 +29 + 3 +ACDB_RECOMPOSE_DATA +350 +17C + 3 +AcDbVariableDictionary +350 +16D + 0 +DICTIONARY + 5 +AF +330 +70 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_SORTENTS +360 +F9 + 0 +DICTIONARY + 5 +FD +330 +FC +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_SORTENTS +360 +12E + 0 +DICTIONARY + 5 +178 +330 +117 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_XREC_ROUNDTRIP +360 +179 + 0 +DICTIONARY + 5 +63 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +DICTIONARY + 5 +6A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Imperial24 +350 +6B + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +DICTIONARY + 5 +62 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Feuille1 +350 +6F + 3 +Feuille2 +350 +77 + 3 +Model +350 +73 + 0 +DICTIONARY + 5 +10 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +ByBlock +350 +19 + 3 +ByLayer +350 +11 + 3 +Global +350 +21 + 0 +DICTIONARY + 5 +66 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Standard +350 +67 + 0 +DICTIONARY + 5 +5F +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Standard +350 +60 + 0 +DICTIONARY + 5 +61 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ACDBDICTIONARYWDFLT + 5 +E +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Normal +350 +F +100 +AcDbDictionaryWithDefault +340 +F + 0 +DICTIONARY + 5 +42 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +*A1 +350 +AD + 3 +*A2 +350 +AE + 3 +A0 +350 +43 + 3 +A1 +350 +44 + 3 +A2 +350 +45 + 3 +A3 +350 +46 + 3 +A4 +350 +47 + 3 +A5 +350 +48 + 3 +A6 +350 +49 + 3 +A7 +350 +4A + 3 +A8 +350 +4B + 3 +A9 +350 +4C + 3 +B0 +350 +4D + 3 +B1 +350 +4E + 3 +B2 +350 +4F + 3 +B3 +350 +50 + 3 +B4 +350 +51 + 3 +B5 +350 +52 + 3 +B6 +350 +53 + 0 +DICTIONARY + 5 +68 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Imperial24 +350 +69 + 0 +DICTIONARY + 5 +64 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +ISO_TABLE +350 +12D + 3 +Standard +350 +65 + 0 +DICTIONARY + 5 +29 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +2dWireframe +350 +2F + 3 +Basic +350 +2E + 3 +Brighten +350 +35 + 3 +ColorChange +350 +39 + 3 +Conceptual +350 +32 + 3 +Dim +350 +34 + 3 +EdgeColorOff +350 +41 + 3 +Facepattern +350 +38 + 3 +Flat +350 +2A + 3 +FlatWithEdges +350 +2B + 3 +Gouraud +350 +2C + 3 +GouraudWithEdges +350 +2D + 3 +Hidden +350 +31 + 3 +JitterOff +350 +3F + 3 +Linepattern +350 +37 + 3 +OverhangOff +350 +40 + 3 +Realistic +350 +33 + 3 +Shaded +350 +3E + 3 +Shaded with edges +350 +3D + 3 +Shades of Gray +350 +3A + 3 +Sketchy +350 +3B + 3 +Thicken +350 +36 + 3 +Wireframe +350 +30 + 3 +X-Ray +350 +3C + 0 +XRECORD + 5 +17C +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbXrecord +280 + 1 + 90 + 1 +330 +65 +330 +111 +330 +113 +330 +114 +330 +115 +330 +116 +330 +117 +330 +12D + 0 +DICTIONARY + 5 +16D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +ANNOALLVISIBLE +350 +172 + 3 +CANNOSCALE +350 +173 + 3 +CMLEADERSTYLE +350 +16F + 3 +CTABLESTYLE +350 +16E + 3 +CVIEWDETAILSTYLE +350 +170 + 3 +CVIEWSECTIONSTYLE +350 +171 + 0 +SORTENTSTABLE + 5 +F9 +102 +{ACAD_REACTORS +330 +AF +102 +} +330 +AF +100 +AcDbSortentsTable +330 +70 + 0 +SORTENTSTABLE + 5 +12E +102 +{ACAD_REACTORS +330 +FD +102 +} +330 +FD +100 +AcDbSortentsTable +330 +FC +331 +105 + 5 +104 +331 +102 + 5 +101 +331 +103 + 5 +102 +331 +100 + 5 +109 +331 +101 + 5 +10A +331 +10E + 5 +108 +331 +10F + 5 +100 +331 +10C + 5 +10E +331 +10D + 5 +10F +331 +10A + 5 +10C +331 +10B + 5 +10D +331 +108 + 5 +107 +331 +109 + 5 +10B +331 +106 + 5 +105 +331 +107 + 5 +106 +331 +104 + 5 +103 + 0 +XRECORD + 5 +179 +102 +{ACAD_REACTORS +330 +178 +102 +} +330 +178 +100 +AcDbXrecord +280 + 1 +102 +ACAD_ROUNDTRIP_2008_TABLE_ENTITY +360 +176 + 70 + 1 + 90 + 14 + 90 + 4 + 40 +0.0 + 90 + 0 + 90 + 0 + 90 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 40 +38.333333 + 90 + 2 + 90 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 90 + 0 + 90 + 2 + 90 + 0 +361 +177 + 0 +ACDBDETAILVIEWSTYLE + 5 +6B +102 +{ACAD_XDICTIONARY +360 +17F +102 +} +102 +{ACAD_REACTORS +330 +6A +102 +} +330 +6A +100 +AcDbModelDocViewStyle + 70 + 0 + 3 +Imperial24 +290 + 0 +100 +AcDbDetailViewStyle + 70 + 0 + 71 + 0 + 90 + 3 + 71 + 1 +340 +55 + 62 + 256 + 40 +0.24 +340 +0 + 62 + 256 + 40 +0.24 +300 + + 40 +0.36 +280 + 3 + 71 + 2 +340 +5D + 90 + 25 + 62 + 256 + 71 + 3 +340 +55 + 62 + 256 + 40 +0.24 + 90 + 1 + 40 +0.75 + 90 + 1 +300 +%<\AcVar ViewType \f "%tc1">% %<\AcVar ViewDetailId>%\PECHELLE %<\AcVar ViewScale \f "%sn">% + 71 + 4 +340 +5D + 90 + 25 + 62 + 256 +340 +5D + 90 + 25 + 62 + 256 +280 + 0 + 0 +LAYOUT + 5 +6F +102 +{ACAD_REACTORS +330 +62 +102 +} +330 +62 +100 +AcDbPlotSettings + 1 + + 2 + + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 + 688 + 72 + 0 + 73 + 0 + 74 + 5 + 7 + + 75 + 16 +147 +1.0 + 76 + 0 + 77 + 2 + 78 + 300 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Feuille1 + 70 + 1 + 71 + 1 + 10 +0.0 + 20 +0.0 + 11 +12.0 + 21 +9.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +6C + 0 +LAYOUT + 5 +77 +102 +{ACAD_REACTORS +330 +62 +102 +} +330 +62 +100 +AcDbPlotSettings + 1 + + 2 + + 4 + + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +0.0 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 + 688 + 72 + 0 + 73 + 0 + 74 + 5 + 7 + + 75 + 16 +147 +1.0 + 76 + 0 + 77 + 2 + 78 + 300 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Feuille2 + 70 + 1 + 71 + 2 + 10 +0.0 + 20 +0.0 + 11 +12.0 + 21 +9.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +74 + 0 +LAYOUT + 5 +73 +102 +{ACAD_REACTORS +330 +62 +102 +} +330 +62 +100 +AcDbPlotSettings + 1 + + 2 +AutoCAD PDF (High Quality Print).pc3 + 4 +ISO_full_bleed_A4_(297.00_x_210.00_MM) + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +297.0 + 45 +210.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.758703 + 70 + 11952 + 72 + 1 + 73 + 0 + 74 + 0 + 7 + + 75 + 0 +147 +0.568601 + 76 + 0 + 77 + 2 + 78 + 300 +148 +112.667398 +149 +8.367609 +100 +AcDbLayout + 1 +Model + 70 + 1 + 71 + 0 + 10 +0.0 + 20 +0.0 + 11 +12.0 + 21 +9.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +0.0 + 24 +0.0 + 34 +0.0 + 15 +0.0 + 25 +0.0 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +70 +1001 +ACAD_PSEXT +1000 +AutoCAD PDF (High Quality Print).pc3 +1000 +DWG To PDF +1000 +Fichier +1000 + +1070 + 0 + 0 +MATERIAL + 5 +19 +102 +{ACAD_XDICTIONARY +360 +1A +102 +} +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMaterial + 1 +ByBlock + 72 + 0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 77 + 0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 +171 + 0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 +175 + 0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +179 + 0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 + 0 +MATERIAL + 5 +11 +102 +{ACAD_XDICTIONARY +360 +12 +102 +} +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMaterial + 1 +ByLayer + 72 + 0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 77 + 0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 +171 + 0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 +175 + 0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +179 + 0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 + 0 +MATERIAL + 5 +21 +102 +{ACAD_XDICTIONARY +360 +22 +102 +} +102 +{ACAD_REACTORS +330 +10 +102 +} +330 +10 +100 +AcDbMaterial + 1 +Global + 72 + 0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.020833 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +0.0 + 43 +1.0 + 77 + 0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.020833 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +0.0 + 47 +1.0 +171 + 0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.020833 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +0.0 + 49 +1.0 +175 + 0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.020833 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +0.0 +142 +1.0 +179 + 0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.020833 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +0.0 +144 +1.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.020833 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +0.0 +147 +1.0 + 0 +MLEADERSTYLE + 5 +67 +102 +{ACAD_REACTORS +330 +66 +102 +} +330 +66 +100 +AcDbMLeaderStyle +179 + 2 +170 + 2 +171 + 1 +172 + 0 + 90 + 2 + 40 +0.0 + 41 +0.0 +173 + 1 + 91 +-1056964608 +340 +5B + 92 + -2 +290 + 1 + 42 +0.09 +291 + 1 + 43 +0.36 + 3 +Standard + 44 +0.18 +300 + +342 +55 +174 + 1 +178 + 6 +175 + 1 +176 + 0 + 93 +-1056964608 + 45 +0.18 +292 + 0 +297 + 0 + 46 +0.18 + 94 +-1056964608 + 47 +1.0 + 49 +1.0 +140 +1.0 +293 + 1 +141 +0.0 +294 + 1 +177 + 0 +142 +1.0 +295 + 0 +296 + 0 +143 +0.125 +271 + 0 +272 + 9 +273 + 9 +298 + 1 + 0 +MLINESTYLE + 5 +60 +102 +{ACAD_REACTORS +330 +5F +102 +} +330 +5F +100 +AcDbMlineStyle + 2 +STANDARD + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 0 + 0 +ACDBPLACEHOLDER + 5 +F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E + 0 +SCALE + 5 +AD +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:3 +140 +0.333333 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +AE +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +3:1 +140 +3.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +43 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:1 +140 +1.0 +141 +1.0 +290 + 1 + 0 +SCALE + 5 +44 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:2 +140 +1.0 +141 +2.0 +290 + 0 + 0 +SCALE + 5 +45 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:4 +140 +1.0 +141 +4.0 +290 + 0 + 0 +SCALE + 5 +46 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:5 +140 +1.0 +141 +5.0 +290 + 0 + 0 +SCALE + 5 +47 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:8 +140 +1.0 +141 +8.0 +290 + 0 + 0 +SCALE + 5 +48 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:10 +140 +1.0 +141 +10.0 +290 + 0 + 0 +SCALE + 5 +49 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:16 +140 +1.0 +141 +16.0 +290 + 0 + 0 +SCALE + 5 +4A +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:20 +140 +1.0 +141 +20.0 +290 + 0 + 0 +SCALE + 5 +4B +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:30 +140 +1.0 +141 +30.0 +290 + 0 + 0 +SCALE + 5 +4C +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:40 +140 +1.0 +141 +40.0 +290 + 0 + 0 +SCALE + 5 +4D +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:50 +140 +1.0 +141 +50.0 +290 + 0 + 0 +SCALE + 5 +4E +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +1:100 +140 +1.0 +141 +100.0 +290 + 0 + 0 +SCALE + 5 +4F +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +2:1 +140 +2.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +50 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +4:1 +140 +4.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +51 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +8:1 +140 +8.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +52 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +10:1 +140 +10.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +53 +102 +{ACAD_REACTORS +330 +42 +102 +} +330 +42 +100 +AcDbScale + 70 + 0 +300 +100:1 +140 +100.0 +141 +1.0 +290 + 0 + 0 +ACDBSECTIONVIEWSTYLE + 5 +69 +102 +{ACAD_XDICTIONARY +360 +17D +102 +} +102 +{ACAD_REACTORS +330 +68 +102 +} +330 +68 +100 +AcDbModelDocViewStyle + 70 + 0 + 3 +Imperial24 +290 + 0 +100 +AcDbSectionViewStyle + 70 + 0 + 71 + 0 + 90 + 78 + 71 + 1 +340 +55 + 62 + 256 + 40 +0.24 +340 +0 +340 +0 + 62 + 256 + 40 +0.24 +300 +I, O, Q, S, X, Z + 40 +0.48 + 90 + 3 + 40 +0.18 + 90 + 1 + 71 + 2 +340 +5D + 90 + 25 + 62 + 256 +340 +5D + 90 + 50 + 62 + 256 + 40 +0.24 + 40 +0.0 + 40 +0.24 + 71 + 3 +340 +55 + 62 + 256 + 40 +0.24 + 90 + 1 + 40 +0.75 + 90 + 1 +300 +%<\AcVar ViewType \f "%tc1">% %<\AcVar ViewSectionStartId>%-%<\AcVar ViewSectionEndId>%\PECHELLE %<\AcVar ViewScale \f "%sn">% + 71 + 4 + 62 + 256 + 62 + 257 +300 +ANSI31 + 40 +1.0 + 90 + 0 +290 + 0 +290 + 0 + 90 + 6 + 40 +0.0 + 40 +1.570796 + 40 +0.261799 + 40 +1.308997 + 40 +-0.261799 + 40 +1.832596 + 0 +TABLESTYLE + 5 +12D +102 +{ACAD_XDICTIONARY +360 +17A +102 +} +102 +{ACAD_REACTORS +330 +117 +330 +64 +102 +} +330 +64 +100 +AcDbTableStyle +280 + 0 + 3 +Standard + 70 + 0 + 71 + 0 + 40 +1.5 + 41 +1.5 +280 + 0 +281 + 0 + 7 +Standard +140 +3.5 +170 + 2 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 4 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +3.5 +170 + 5 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 4 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +3.5 +170 + 5 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 4 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 0 +TABLESTYLE + 5 +65 +102 +{ACAD_XDICTIONARY +360 +174 +102 +} +102 +{ACAD_REACTORS +330 +64 +102 +} +330 +64 +100 +AcDbTableStyle +280 + 0 + 3 +Standard + 70 + 0 + 71 + 0 + 40 +1.5 + 41 +1.5 +280 + 0 +281 + 0 + 7 +Standard +140 +0.18 +170 + 2 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 512 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +0.25 +170 + 5 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 512 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +0.18 +170 + 5 + 62 + 0 + 63 + 7 +283 + 0 + 90 + 512 + 91 + 0 + 1 + +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 0 +VISUALSTYLE + 5 +2F +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +2dWireframe + 70 + 4 +177 + 3 +291 + 0 + 70 + 58 + 90 + 0 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2E +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Basic + 70 + 7 +177 + 3 +291 + 1 + 70 + 58 + 90 + 1 +176 + 1 + 90 + 0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 0 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +35 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Brighten + 70 + 12 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +50.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +39 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +ColorChange + 70 + 16 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 8 +420 + 8421504 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 8 +420 + 8421504 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +32 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Conceptual + 70 + 9 +177 + 3 +291 + 0 + 70 + 58 + 90 + 3 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +179.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +34 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Dim + 70 + 11 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +-50.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +41 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +EdgeColorOff + 70 + 22 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 0 + 90 + 2 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 + 40 +0.6 +176 + 0 + 40 +30.0 +176 + 0 + 62 + 7 +420 + 16777215 +176 + 0 + 90 + 1 +176 + 0 + 90 + 4 +176 + 0 + 62 + 7 +176 + 0 + 62 + 257 +176 + 0 + 90 + 1 +176 + 0 + 90 + 1 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 8 +176 + 2 + 62 + 7 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 1 +176 + 0 + 90 + 6 +176 + 0 + 90 + 2 +176 + 0 + 62 + 7 +176 + 0 + 90 + 5 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 1 +176 + 0 + 40 +0.0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 1 +176 + 0 +290 + 1 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 40 +0.0 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 0 +176 + 0 + 62 + 18 +420 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 3 +176 + 0 + 62 + 5 +420 + 255 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 0 + 1 +strokes_ogs.tif +176 + 0 +290 + 0 +176 + 0 + 40 +1.0 +176 + 0 + 40 +1.0 +176 + 0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +38 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Facepattern + 70 + 15 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2A +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Flat + 70 + 0 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2B +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +FlatWithEdges + 70 + 1 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Gouraud + 70 + 2 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2D +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +GouraudWithEdges + 70 + 3 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +31 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Hidden + 70 + 6 +177 + 3 +291 + 0 + 70 + 58 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 40 +40.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3F +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +JitterOff + 70 + 20 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 0 + 90 + 2 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 + 40 +0.6 +176 + 0 + 40 +30.0 +176 + 0 + 62 + 7 +420 + 16777215 +176 + 0 + 90 + 1 +176 + 0 + 90 + 4 +176 + 0 + 62 + 7 +176 + 0 + 62 + 257 +176 + 0 + 90 + 1 +176 + 0 + 90 + 1 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 10 +176 + 2 + 62 + 7 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 1 +176 + 0 + 90 + 6 +176 + 0 + 90 + 2 +176 + 0 + 62 + 7 +176 + 0 + 90 + 5 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 1 +176 + 0 + 40 +0.0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 1 +176 + 0 +290 + 1 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 40 +0.0 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 0 +176 + 0 + 62 + 18 +420 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 3 +176 + 0 + 62 + 5 +420 + 255 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 0 + 1 +strokes_ogs.tif +176 + 0 +290 + 0 +176 + 0 + 40 +1.0 +176 + 0 + 40 +1.0 +176 + 0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +37 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Linepattern + 70 + 14 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 7 +176 + 1 + 90 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +40 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +OverhangOff + 70 + 21 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 0 + 90 + 2 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 + 40 +0.6 +176 + 0 + 40 +30.0 +176 + 0 + 62 + 7 +420 + 16777215 +176 + 0 + 90 + 1 +176 + 0 + 90 + 4 +176 + 0 + 62 + 7 +176 + 0 + 62 + 257 +176 + 0 + 90 + 1 +176 + 0 + 90 + 1 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 9 +176 + 2 + 62 + 7 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 1 +176 + 0 + 90 + 6 +176 + 0 + 90 + 2 +176 + 0 + 62 + 7 +176 + 0 + 90 + 5 +176 + 0 + 90 + 0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 1 +176 + 0 + 40 +0.0 +176 + 0 + 90 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 1 +176 + 0 +290 + 1 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 40 +0.0 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 0 +176 + 0 + 62 + 18 +420 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 3 +176 + 0 + 62 + 5 +420 + 255 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 + 90 + 50 +176 + 0 +290 + 0 +176 + 0 + 90 + 50 +176 + 0 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 0 + 1 +strokes_ogs.tif +176 + 0 +290 + 0 +176 + 0 + 40 +1.0 +176 + 0 + 40 +1.0 +176 + 0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +33 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Realistic + 70 + 8 +177 + 3 +291 + 0 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3E +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Shaded + 70 + 27 +177 + 3 +291 + 0 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 0 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 8 +420 + 7895160 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 5 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3D +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Shaded with edges + 70 + 26 +177 + 3 +291 + 0 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 5 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3A +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Shades of Gray + 70 + 23 +177 + 3 +291 + 0 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 62 + 7 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +40.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3B +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Sketchy + 70 + 24 +177 + 3 +291 + 0 + 70 + 58 + 90 + 1 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 62 + 7 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +40.0 +176 + 1 + 90 + 11 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 6 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +36 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Thicken + 70 + 13 +177 + 3 +291 + 1 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 12 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 5 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +30 +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +Wireframe + 70 + 5 +177 + 3 +291 + 0 + 70 + 58 + 90 + 0 +176 + 1 + 90 + 2 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 + 40 +0.6 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 4 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 257 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3C +102 +{ACAD_REACTORS +330 +29 +102 +} +330 +29 +100 +AcDbVisualStyle + 2 +X-Ray + 70 + 25 +177 + 3 +291 + 0 + 70 + 58 + 90 + 2 +176 + 1 + 90 + 2 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +0.5 +176 + 1 + 40 +30.0 +176 + 1 + 62 + 7 +420 + 16777215 +176 + 1 + 90 + 1 +176 + 1 + 90 + 0 +176 + 1 + 62 + 7 +176 + 1 + 62 + 257 +176 + 1 + 90 + 1 +176 + 1 + 90 + 1 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 8 +176 + 1 + 62 + 7 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 1 +176 + 1 + 90 + 6 +176 + 1 + 90 + 2 +176 + 1 + 62 + 7 +176 + 1 + 90 + 3 +176 + 1 + 90 + 0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 13 +176 + 1 + 40 +0.0 +176 + 1 + 90 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 1 +176 + 1 +290 + 1 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 40 +0.0 +176 + 1 + 40 +1.0 +176 + 1 + 90 + 0 +176 + 1 + 62 + 18 +420 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 3 +176 + 1 + 62 + 5 +420 + 255 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 + 90 + 50 +176 + 1 +290 + 0 +176 + 1 + 90 + 50 +176 + 1 + 62 + 256 +176 + 0 + 40 +1.0 +176 + 0 + 90 + 2 +176 + 1 + 1 +strokes_ogs.tif +176 + 1 +290 + 0 +176 + 1 + 40 +1.0 +176 + 1 + 40 +1.0 +176 + 1 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +DICTIONARYVAR + 5 +172 +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +0 + 0 +DICTIONARYVAR + 5 +173 +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +1:1 + 0 +DICTIONARYVAR + 5 +16F +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +STANDARD + 0 +DICTIONARYVAR + 5 +16E +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +ISO_TABLE + 0 +DICTIONARYVAR + 5 +170 +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +Imperial24 + 0 +DICTIONARYVAR + 5 +171 +102 +{ACAD_REACTORS +330 +16D +102 +} +330 +16D +100 +DictionaryVariables +280 + 0 + 1 +Imperial24 + 0 +TABLECONTENT + 5 +176 +330 +179 +100 +AcDbLinkedData + 1 + +300 + +100 +AcDbLinkedTableData + 90 + 3 +300 +COLUMN + 1 +LINKEDTABLEDATACOLUMN_BEGIN +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATACOLUMN_END + 1 +FORMATTEDTABLEDATACOLUMN_BEGIN +300 +COLUMNTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 3 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACOLUMN_END + 1 +TABLECOLUMN_BEGIN + 90 + 0 + 40 +35.0 +309 +TABLECOLUMN_END +300 +COLUMN + 1 +LINKEDTABLEDATACOLUMN_BEGIN +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATACOLUMN_END + 1 +FORMATTEDTABLEDATACOLUMN_BEGIN +300 +COLUMNTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 3 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACOLUMN_END + 1 +TABLECOLUMN_BEGIN + 90 + 0 + 40 +35.0 +309 +TABLECOLUMN_END +300 +COLUMN + 1 +LINKEDTABLEDATACOLUMN_BEGIN +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATACOLUMN_END + 1 +FORMATTEDTABLEDATACOLUMN_BEGIN +300 +COLUMNTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 3 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACOLUMN_END + 1 +TABLECOLUMN_BEGIN + 90 + 0 + 40 +35.0 +309 +TABLECOLUMN_END + 91 + 3 +301 +ROW + 1 +LINKEDTABLEDATAROW_BEGIN + 90 + 3 +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +0.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 5 + 90 + 4 + 94 + 0 +300 + +302 + +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +87.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +W + 94 + 0 +300 + +302 +W +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +72.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +H + 94 + 0 +300 + +302 +H +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATAROW_END + 1 +FORMATTEDTABLEDATAROW_BEGIN +300 +ROWTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 2 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATAROW_END + 1 +TABLEROW_BEGIN + 90 + 2 + 40 +7.666667 +309 +TABLEROW_END +301 +ROW + 1 +LINKEDTABLEDATAROW_BEGIN + 90 + 3 +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +7557.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +viewing area + 94 + 0 +300 + +302 +viewing area +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +760.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +71.35 + 94 + 0 +300 + +302 +71.35 +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +495.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +18.1 + 94 + 0 +300 + +302 +18.1 +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATAROW_END + 1 +FORMATTEDTABLEDATAROW_BEGIN +300 +ROWTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 2 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATAROW_END + 1 +TABLEROW_BEGIN + 90 + 2 + 40 +7.666667 +309 +TABLEROW_END +301 +ROW + 1 +LINKEDTABLEDATAROW_BEGIN + 90 + 3 +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +2282.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +recess + 94 + 0 +300 + +302 +recess +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 2 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +764.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +73.35 + 94 + 0 +300 + +302 +73.35 +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 2 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END +300 +CELL + 1 +LINKEDTABLEDATACELL_BEGIN + 90 + 0 +300 + + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 1 +300 +ACAD_ROUNDTRIP_2008_CELL_CHECKSUM +301 +DATAMAP_VALUE + 93 + 2 + 90 + 2 +140 +480.0 + 94 + 0 +300 + +302 + +304 +ACVALUE_END +309 +DATAMAP_END + 92 + 0 + 95 + 1 +302 +CONTENT + 1 +CELLCONTENT_BEGIN + 90 + 1 +300 +VALUE + 93 + 6 + 90 + 4 + 1 +20.1 + 94 + 0 +300 + +302 +20.1 +304 +ACVALUE_END + 91 + 0 +309 +CELLCONTENT_END + 1 +FORMATTEDCELLCONTENT_BEGIN +170 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +309 +FORMATTEDCELLCONTENT_END +309 +LINKEDTABLEDATACELL_END + 1 +FORMATTEDTABLEDATACELL_BEGIN +300 +CELLTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 1 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 2 + 62 + 0 +340 +0 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 0 + 94 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATACELL_END + 1 +TABLECELL_BEGIN + 90 + 0 + 91 + 0 +309 +TABLECELL_END + 91 + 0 +301 +CUSTOMDATA + 1 +DATAMAP_BEGIN + 90 + 0 +309 +DATAMAP_END +309 +LINKEDTABLEDATAROW_END + 1 +FORMATTEDTABLEDATAROW_BEGIN +300 +ROWTABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 2 +170 + 0 +309 +TABLEFORMAT_END +309 +FORMATTEDTABLEDATAROW_END + 1 +TABLEROW_BEGIN + 90 + 3 + 40 +7.666667 +309 +TABLEROW_END + 92 + 0 +100 +AcDbFormattedTableData +300 +TABLEFORMAT + 1 +TABLEFORMAT_BEGIN + 90 + 4 +170 + 0 +309 +TABLEFORMAT_END + 90 + 0 +100 +AcDbTableContent +340 +12D + 0 +TABLEGEOMETRY + 5 +177 +330 +179 +100 +AcDbTableGeometry + 90 + 3 + 91 + 3 + 92 + 9 + 93 + 3 + 40 +3.0 + 41 +6.5 +330 +0 + 94 + 1 + 10 +17.5 + 20 +-2.083333 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +0.0 + 44 +3.5 + 45 +0.0 + 46 +3.5 + 95 + 0 + 93 + 3 + 40 +7.600341 + 41 +6.5 +330 +0 + 94 + 1 + 10 +15.199829 + 20 +-2.083333 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +4.600341 + 44 +3.5 + 45 +4.600341 + 46 +3.5 + 95 + 0 + 93 + 3 + 40 +5.845566 + 41 +6.5 +330 +0 + 94 + 1 + 10 +16.077217 + 20 +-2.083333 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +2.845566 + 44 +3.5 + 45 +2.845566 + 46 +3.5 + 95 + 0 + 93 + 3 + 40 +30.281105 + 41 +7.52899 +330 +0 + 94 + 1 + 10 +3.859447 + 20 +-1.568838 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +27.281105 + 44 +4.52899 + 45 +27.281105 + 46 +4.52899 + 95 + 0 + 93 + 3 + 40 +14.908322 + 41 +6.576398 +330 +0 + 94 + 1 + 10 +11.545839 + 20 +-2.045134 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +11.908322 + 44 +3.576398 + 45 +11.908322 + 46 +3.576398 + 95 + 0 + 93 + 3 + 40 +11.186289 + 41 +6.574011 +330 +0 + 94 + 1 + 10 +13.406855 + 20 +-2.046328 + 30 +0.0 + 11 +17.5 + 21 +-3.833333 + 31 +0.0 + 43 +8.186289 + 44 +3.574011 + 45 +8.186289 + 46 +3.574011 + 95 + 0 + 93 + 3 + 40 +16.994952 + 41 +6.557299 +330 +0 + 94 + 1 + 10 +10.502524 + 20 +-1.5 + 30 +0.0 + 11 +17.5 + 21 +-1.5 + 31 +0.0 + 43 +13.994952 + 44 +3.557299 + 45 +13.994952 + 46 +3.557299 + 95 + 0 + 93 + 3 + 40 +14.908322 + 41 +6.576398 +330 +0 + 94 + 1 + 10 +11.545839 + 20 +-1.5 + 30 +0.0 + 11 +17.5 + 21 +-1.5 + 31 +0.0 + 43 +11.908322 + 44 +3.576398 + 45 +11.908322 + 46 +3.576398 + 95 + 0 + 93 + 3 + 40 +11.575443 + 41 +6.574011 +330 +0 + 94 + 1 + 10 +13.212278 + 20 +-1.5 + 30 +0.0 + 11 +17.5 + 21 +-1.5 + 31 +0.0 + 43 +8.575443 + 44 +3.574011 + 45 +8.575443 + 46 +3.574011 + 95 + 0 + 0 +DICTIONARY + 5 +17F +330 +6B +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_XREC_ROUNDTRIP +360 +180 + 0 +DICTIONARY + 5 +1A +330 +19 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +BUMPTILE +360 +1C + 3 +DIFFUSETILE +360 +1B + 3 +OPACITYTILE +360 +1F + 3 +REFLECTIONTILE +360 +1E + 3 +REFRACTIONTILE +360 +20 + 3 +SPECULARTILE +360 +1D + 0 +DICTIONARY + 5 +12 +330 +11 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +BUMPTILE +360 +14 + 3 +DIFFUSETILE +360 +13 + 3 +OPACITYTILE +360 +17 + 3 +REFLECTIONTILE +360 +16 + 3 +REFRACTIONTILE +360 +18 + 3 +SPECULARTILE +360 +15 + 0 +DICTIONARY + 5 +22 +330 +21 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +BUMPTILE +360 +24 + 3 +DIFFUSETILE +360 +23 + 3 +OPACITYTILE +360 +27 + 3 +REFLECTIONTILE +360 +26 + 3 +REFRACTIONTILE +360 +28 + 3 +SPECULARTILE +360 +25 + 0 +DICTIONARY + 5 +17D +330 +69 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_XREC_ROUNDTRIP +360 +17E + 0 +DICTIONARY + 5 +17A +330 +12D +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_ROUNDTRIP_2008_TABLESTYLE_CELLSTYLEMAP +360 +17B + 0 +DICTIONARY + 5 +174 +330 +65 +100 +AcDbDictionary +280 + 1 +281 + 1 + 3 +ACAD_ROUNDTRIP_2008_TABLESTYLE_CELLSTYLEMAP +360 +175 + 0 +XRECORD + 5 +180 +102 +{ACAD_REACTORS +330 +17F +102 +} +330 +17F +100 +AcDbXrecord +280 + 1 +102 +DISPLAYNAME + 1 +Imperial24 +102 +FLAGS + 90 + 0 + 0 +XRECORD + 5 +1C +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +1B +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +1F +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +1E +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +20 +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +1D +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +14 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +13 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +17 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +16 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +18 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +15 +102 +{ACAD_REACTORS +330 +12 +102 +} +330 +12 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +24 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +23 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +27 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +26 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +28 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +25 +102 +{ACAD_REACTORS +330 +22 +102 +} +330 +22 +100 +AcDbXrecord +280 + 1 +270 + 1 +271 + 1 + 0 +XRECORD + 5 +17E +102 +{ACAD_REACTORS +330 +17D +102 +} +330 +17D +100 +AcDbXrecord +280 + 1 +102 +DISPLAYNAME + 1 +Imperial24 +102 +FLAGS + 90 + 0 + 0 +CELLSTYLEMAP + 5 +17B +102 +{ACAD_REACTORS +330 +17A +102 +} +330 +17A +100 +AcDbCellStyleMap + 90 + 4 +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 32768 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +4.5 + 40 +4.5 +309 +CELLMARGIN_END + 94 + 6 + 95 + 1 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 2 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 4 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 8 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 16 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 32 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 1 + 91 + 1 +300 +_TITLE +309 +CELLSTYLE_END +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +4.5 + 40 +4.5 +309 +CELLMARGIN_END + 94 + 6 + 95 + 1 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 2 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 4 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 8 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 16 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 32 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 2 + 91 + 1 +300 +_HEADER +309 +CELLSTYLE_END +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 2 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +4.5 + 40 +4.5 +309 +CELLMARGIN_END + 94 + 6 + 95 + 1 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 2 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 4 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 8 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 16 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 32 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 3 + 91 + 2 +300 +_DATA +309 +CELLSTYLE_END +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 4 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 1 + 62 + 0 +340 +55 +144 +3.5 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +4.5 + 40 +4.5 +309 +CELLMARGIN_END + 94 + 6 + 95 + 1 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 2 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 4 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 8 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 16 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END + 95 + 32 +302 +GRIDFORMAT + 1 +GRIDFORMAT_BEGIN + 90 + 0 + 91 + 1 + 62 + 0 + 92 + -2 +340 +5B + 93 + 0 + 40 +1.125 +309 +GRIDFORMAT_END +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 101 + 91 + 2 +300 +DataLeftJustified +309 +CELLSTYLE_END + 0 +CELLSTYLEMAP + 5 +175 +102 +{ACAD_REACTORS +330 +174 +102 +} +330 +174 +100 +AcDbCellStyleMap + 90 + 3 +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 32768 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +55 +144 +0.25 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +0.18 + 40 +0.18 +309 +CELLMARGIN_END + 94 + 0 +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 1 + 91 + 1 +300 +_TITLE +309 +CELLSTYLE_END +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 5 + 62 + 0 +340 +55 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +0.18 + 40 +0.18 +309 +CELLMARGIN_END + 94 + 0 +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 2 + 91 + 1 +300 +_HEADER +309 +CELLSTYLE_END +300 +CELLSTYLE + 1 +TABLEFORMAT_BEGIN + 90 + 5 +170 + 1 + 91 + 0 + 92 + 0 + 62 + 257 + 93 + 1 +300 +CONTENTFORMAT + 1 +CONTENTFORMAT_BEGIN + 90 + 0 + 91 + 0 + 92 + 512 + 93 + 0 +300 + + 40 +0.0 +140 +1.0 + 94 + 2 + 62 + 0 +340 +55 +144 +0.18 +309 +CONTENTFORMAT_END +171 + 1 +301 +MARGIN + 1 +CELLMARGIN_BEGIN + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +1.5 + 40 +0.18 + 40 +0.18 +309 +CELLMARGIN_END + 94 + 0 +309 +TABLEFORMAT_END + 1 +CELLSTYLE_BEGIN + 90 + 3 + 91 + 2 +300 +_DATA +309 +CELLSTYLE_END + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test_r12.dxf b/share/extensions/tests/data/io/test_r12.dxf new file mode 100644 index 0000000..7b55631 --- /dev/null +++ b/share/extensions/tests/data/io/test_r12.dxf @@ -0,0 +1,5592 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMAX + 10 +1000.0 + 20 +1000.0 + 30 +0.0 + 9 +$FILLMODE + 70 + 0 + 9 +$SPLFRAME + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +LAYER + 70 +1 + 0 +LAYER + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +POLYLINE + 8 +0 + 62 + 174 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 1 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +12 + 41 +12 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 174 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +5.72917 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +5.70296 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.07269 + 20 +5.62424 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.04237 + 20 +5.52647 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.99436 + 20 +5.43799 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.93078 + 20 +5.36089 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.85368 + 20 +5.29731 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.76519 + 20 +5.24929 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.66743 + 20 +5.21897 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.58871 + 20 +5.20833 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.5625 + 20 +5.20833 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.53624 + 20 +5.20833 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.45751 + 20 +5.21897 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.35975 + 20 +5.24929 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.27127 + 20 +5.29731 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.19417 + 20 +5.36089 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.13059 + 20 +5.43799 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.08257 + 20 +5.52647 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.05225 + 20 +5.62424 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +5.70296 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +5.72917 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +5.75543 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.05225 + 20 +5.83415 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.08257 + 20 +5.93192 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.13059 + 20 +6.0204 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.19417 + 20 +6.0975 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.27127 + 20 +6.16108 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.35975 + 20 +6.2091 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.45751 + 20 +6.23942 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.53624 + 20 +6.25 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.5625 + 20 +6.25 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.58871 + 20 +6.25 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.66743 + 20 +6.23942 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.76519 + 20 +6.2091 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.85368 + 20 +6.16108 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.93078 + 20 +6.0975 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.99436 + 20 +6.0204 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.04237 + 20 +5.93192 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.07269 + 20 +5.83415 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +5.75543 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +5.72917 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 1 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +12 + 41 +12 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +5.72917 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +5.70296 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.18712 + 20 +5.62424 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.12646 + 20 +5.52647 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.03039 + 20 +5.43799 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.90321 + 20 +5.36089 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.74903 + 20 +5.29731 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.5721 + 20 +5.24929 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.37657 + 20 +5.21897 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.21913 + 20 +5.20833 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.16667 + 20 +5.20833 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.11415 + 20 +5.20833 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.95671 + 20 +5.21897 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.76118 + 20 +5.24929 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.58425 + 20 +5.29731 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.43007 + 20 +5.36089 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.3029 + 20 +5.43799 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.20682 + 20 +5.52647 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.14615 + 20 +5.62424 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +5.70296 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +5.72917 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +5.75543 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.14615 + 20 +5.83415 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.20682 + 20 +5.93192 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.3029 + 20 +6.0204 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.43007 + 20 +6.0975 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.58425 + 20 +6.16108 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.76118 + 20 +6.2091 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +3.95671 + 20 +6.23942 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.11415 + 20 +6.25 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.16667 + 20 +6.25 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.21913 + 20 +6.25 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.37657 + 20 +6.23942 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.5721 + 20 +6.2091 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.74903 + 20 +6.16108 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +4.90321 + 20 +6.0975 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.03039 + 20 +6.0204 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.12646 + 20 +5.93192 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.18712 + 20 +5.83415 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +5.75543 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +5.72917 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 2 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.15717 + 20 +5.43935 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.13249 + 20 +5.42096 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.05274 + 20 +5.37354 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.93099 + 20 +5.31799 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.79486 + 20 +5.27317 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.64725 + 20 +5.23964 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.49104 + 20 +5.21793 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.32915 + 20 +5.20865 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.16444 + 20 +5.21218 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.04075 + 20 +5.22325 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.99989 + 20 +5.22917 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.96035 + 20 +5.23497 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.84283 + 20 +5.25911 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.70014 + 20 +5.3004 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.57368 + 20 +5.35183 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.46528 + 20 +5.41211 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.37685 + 20 +5.48004 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.31028 + 20 +5.55442 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.26747 + 20 +5.634 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25119 + 20 +5.69656 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25028 + 20 +5.71756 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.24935 + 20 +5.73839 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25999 + 20 +5.80149 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.29568 + 20 +5.88194 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.35558 + 20 +5.95774 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.43782 + 20 +6.02756 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.54075 + 20 +6.09022 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.66249 + 20 +6.14437 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.80138 + 20 +6.18881 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.91672 + 20 +6.21556 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.95557 + 20 +6.22217 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.99599 + 20 +6.22906 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.11843 + 20 +6.24283 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.28267 + 20 +6.25006 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.44526 + 20 +6.24436 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.60325 + 20 +6.22618 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.75369 + 20 +6.19601 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.89367 + 20 +6.15429 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.02024 + 20 +6.10146 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.10417 + 20 +6.05583 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.13043 + 20 +6.03797 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.29167 + 20 +5.72917 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.15717 + 20 +5.43935 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 94 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +12 + 41 +12 + 0 +VERTEX + 8 +0 + 10 +8.15717 + 20 +5.43935 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.13249 + 20 +5.42096 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.05274 + 20 +5.37354 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.93099 + 20 +5.31799 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.79486 + 20 +5.27317 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.64725 + 20 +5.23964 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.49104 + 20 +5.21793 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.32915 + 20 +5.20865 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.16444 + 20 +5.21218 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.04075 + 20 +5.22325 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.99989 + 20 +5.22917 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.96035 + 20 +5.23497 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.84283 + 20 +5.25911 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.70014 + 20 +5.3004 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.57368 + 20 +5.35183 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.46528 + 20 +5.41211 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.37685 + 20 +5.48004 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.31028 + 20 +5.55442 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.26747 + 20 +5.634 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25119 + 20 +5.69656 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25028 + 20 +5.71756 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.24935 + 20 +5.73839 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25999 + 20 +5.80149 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.29568 + 20 +5.88194 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.35558 + 20 +5.95774 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.43782 + 20 +6.02756 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.54075 + 20 +6.09022 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.66249 + 20 +6.14437 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.80138 + 20 +6.18881 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.91672 + 20 +6.21556 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.95557 + 20 +6.22217 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.99599 + 20 +6.22906 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.11843 + 20 +6.24283 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.28267 + 20 +6.25006 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.44526 + 20 +6.24436 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.60325 + 20 +6.22618 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.75369 + 20 +6.19601 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.89367 + 20 +6.15429 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.02024 + 20 +6.10146 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.10417 + 20 +6.05583 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.13043 + 20 +6.03797 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.29167 + 20 +5.72917 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.15717 + 20 +5.43935 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 2 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.86518 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.88878 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.95975 + 20 +8.32514 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.04769 + 20 +8.3016 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.12722 + 20 +8.26426 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.1965 + 20 +8.21479 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.25358 + 20 +8.15479 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.2966 + 20 +8.08583 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.32383 + 20 +8.0096 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.94808 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.92757 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.69743 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.67697 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.32383 + 20 +7.61546 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.2966 + 20 +7.53922 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.25358 + 20 +7.47026 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.1965 + 20 +7.41026 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.12722 + 20 +7.36079 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +8.04769 + 20 +7.32346 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.95975 + 20 +7.29992 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.88878 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +7.86518 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.6945 + 20 +7.29167 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.62354 + 20 +7.29992 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.5356 + 20 +7.32346 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.45606 + 20 +7.36079 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.38683 + 20 +7.41026 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.32969 + 20 +7.47026 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.28668 + 20 +7.53922 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25944 + 20 +7.61546 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.67697 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.69743 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.92757 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.94808 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.25944 + 20 +8.0096 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.28668 + 20 +8.08583 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.32969 + 20 +8.15479 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.38683 + 20 +8.21479 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.45606 + 20 +8.26426 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.5356 + 20 +8.3016 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.62354 + 20 +8.32514 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.6945 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +8.33333 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 94 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +12 + 41 +12 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.86518 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.88878 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.95975 + 20 +8.32514 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.04769 + 20 +8.3016 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.12722 + 20 +8.26426 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.1965 + 20 +8.21479 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.25358 + 20 +8.15479 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.2966 + 20 +8.08583 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.32383 + 20 +8.0096 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.94808 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.92757 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.69743 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +7.67697 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.32383 + 20 +7.61546 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.2966 + 20 +7.53922 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.25358 + 20 +7.47026 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.1965 + 20 +7.41026 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.12722 + 20 +7.36079 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +8.04769 + 20 +7.32346 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.95975 + 20 +7.29992 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.88878 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +7.86518 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.6945 + 20 +7.29167 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.62354 + 20 +7.29992 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.5356 + 20 +7.32346 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.45606 + 20 +7.36079 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.38683 + 20 +7.41026 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.32969 + 20 +7.47026 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.28668 + 20 +7.53922 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25944 + 20 +7.61546 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.67697 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.69743 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.92757 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +7.94808 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.25944 + 20 +8.0096 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.28668 + 20 +8.08583 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.32969 + 20 +8.15479 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.38683 + 20 +8.21479 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.45606 + 20 +8.26426 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.5356 + 20 +8.3016 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.62354 + 20 +8.32514 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.6945 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +VERTEX + 8 +0 + 10 +6.71815 + 20 +8.33333 + 30 +0.0 + 40 +0.166667 + 41 +0.166667 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 0 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 40 +7.5 + 41 +7.5 + 0 +VERTEX + 8 +0 + 10 +1.04167 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.125 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.16667 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 0 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 40 +7.5 + 41 +7.5 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.20833 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.20856 + 20 +4.155 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.21035 + 20 +4.1219 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.21517 + 20 +4.07058 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.22461 + 20 +4.0039 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.24007 + 20 +3.92507 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.26324 + 20 +3.83708 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.29551 + 20 +3.743 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.33854 + 20 +3.64583 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.39372 + 20 +3.54872 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.46262 + 20 +3.45458 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.54682 + 20 +3.36664 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.64779 + 20 +3.28776 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.76704 + 20 +3.22114 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +5.90614 + 20 +3.16976 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.06663 + 20 +3.13672 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.20415 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.25 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.29297 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.42188 + 20 +3.13672 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.55111 + 20 +3.16976 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.64367 + 20 +3.22114 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.70574 + 20 +3.28776 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.74333 + 20 +3.36664 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.76269 + 20 +3.45458 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.76981 + 20 +3.54872 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.77083 + 20 +3.64583 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.77181 + 20 +3.743 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.77897 + 20 +3.83708 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.79829 + 20 +3.92507 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.83594 + 20 +4.0039 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.89794 + 20 +4.07058 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +6.99056 + 20 +4.1219 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.11974 + 20 +4.155 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.24864 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.29167 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.33746 + 20 +4.16667 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.47499 + 20 +4.155 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.63547 + 20 +4.1219 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.77458 + 20 +4.07058 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.89388 + 20 +4.0039 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +7.99479 + 20 +3.92507 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.079 + 20 +3.83708 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.14789 + 20 +3.743 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.20313 + 20 +3.64583 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.2461 + 20 +3.54872 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.27838 + 20 +3.45458 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.30154 + 20 +3.36664 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.31706 + 20 +3.28776 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.32644 + 20 +3.22114 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.33128 + 20 +3.16976 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.33306 + 20 +3.13672 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +8.33333 + 20 +3.125 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 2 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.55035 + 20 +1.15478 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.07807 + 20 +1.23953 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.7405 + 20 +0.898492 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.67518 + 20 +1.37386 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.24653 + 20 +1.58951 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.67844 + 20 +1.79856 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +1.75103 + 20 +2.27285 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +1.92671 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.55686 + 20 +2.00418 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.33035 + 20 +1.58122 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +2.55035 + 20 +1.15478 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 94 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +7.5 + 41 +7.5 + 0 +VERTEX + 8 +0 + 10 +2.55035 + 20 +1.15478 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.07807 + 20 +1.23953 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +1.7405 + 20 +0.898492 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +1.67518 + 20 +1.37386 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +1.24653 + 20 +1.58951 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +1.67844 + 20 +1.79856 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +1.75103 + 20 +2.27285 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.08333 + 20 +1.92671 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.55686 + 20 +2.00418 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.33035 + 20 +1.58122 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +2.55035 + 20 +1.15478 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 2 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.63368 + 20 +1.12359 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.1614 + 20 +1.20833 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +3.82383 + 20 +0.867296 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +3.75851 + 20 +1.34267 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +3.32986 + 20 +1.55826 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +3.76178 + 20 +1.76736 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +3.83436 + 20 +2.24164 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.16667 + 20 +1.89551 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.64019 + 20 +1.97299 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.41368 + 20 +1.54997 + 30 +0.0 + 40 +0 + 41 +0 + 0 +VERTEX + 8 +0 + 10 +4.63368 + 20 +1.12359 + 30 +0.0 + 40 +0 + 41 +0 + 0 +SEQEND + 8 +0 + 0 +POLYLINE + 8 +0 + 62 + 94 + 66 + 1 + 10 +0 + 20 +0 + 30 +0.0 + 70 + 1 + 40 +7.5 + 41 +7.5 + 0 +VERTEX + 8 +0 + 10 +4.63368 + 20 +1.12359 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.1614 + 20 +1.20833 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.82383 + 20 +0.867296 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.75851 + 20 +1.34267 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.32986 + 20 +1.55826 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.76178 + 20 +1.76736 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +3.83436 + 20 +2.24164 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.16667 + 20 +1.89551 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.64019 + 20 +1.97299 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.41368 + 20 +1.54997 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +VERTEX + 8 +0 + 10 +4.63368 + 20 +1.12359 + 30 +0.0 + 40 +0.104167 + 41 +0.104167 + 0 +SEQEND + 8 +0 + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/io/test_r14.dxf b/share/extensions/tests/data/io/test_r14.dxf new file mode 100644 index 0000000..f9bb93c --- /dev/null +++ b/share/extensions/tests/data/io/test_r14.dxf @@ -0,0 +1,1398 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 9 +$MEASUREMENT + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +210.0 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +341.0 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +2 + 0 +LAYER + 5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +51 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Layer_1 + 70 +0 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LWPOLYLINE + 5 +100 +100 +AcDbEntity + 8 +Layer_1 + 62 +7 +100 +AcDbPolyline + 90 +1 + 70 +1 + 10 +113.097368 + 20 +154.075207 + 30 +0.0 + 0 +LWPOLYLINE + 5 +101 +100 +AcDbEntity + 8 +Layer_1 + 62 +2 +100 +AcDbPolyline + 90 +10 + 70 +1 + 10 +120.275430 + 20 +164.135316 + 30 +0.0 + 10 +121.883216 + 20 +188.782038 + 30 +0.0 + 10 +102.491311 + 20 +204.079099 + 30 +0.0 + 10 +126.428570 + 20 +210.166260 + 30 +0.0 + 10 +134.984511 + 20 +233.336106 + 30 +0.0 + 10 +148.170764 + 20 +212.451457 + 30 +0.0 + 10 +172.850533 + 20 +211.474151 + 30 +0.0 + 10 +157.062824 + 20 +192.479564 + 30 +0.0 + 10 +163.759825 + 20 +168.705709 + 30 +0.0 + 10 +140.816225 + 20 +177.851061 + 30 +0.0 + 0 +SPLINE + 5 +102 +100 +AcDbEntity + 8 +Layer_1 + 62 +7 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +25 + 73 +21 + 74 +19 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +19.668030 + 40 +39.054581 + 40 +58.722611 + 40 +78.390642 + 40 +97.777192 + 40 +117.445222 + 40 +137.113253 + 40 +156.499803 + 40 +176.167833 + 40 +195.835864 + 40 +215.222414 + 40 +234.890444 + 40 +254.558475 + 40 +273.945025 + 40 +293.613055 + 40 +313.281086 + 40 +332.667636 + 40 +352.335666 + 40 +352.335666 + 40 +352.335666 + 40 +352.335666 + 10 +113.097368 + 20 +154.075207 + 30 +0.0 + 10 +112.423967 + 20 +147.485759 + 30 +0.0 + 10 +111.086802 + 20 +134.401170 + 30 +0.0 + 10 +100.712586 + 20 +117.109684 + 30 +0.0 + 10 +85.522978 + 20 +104.253917 + 30 +0.0 + 10 +66.713509 + 20 +97.435647 + 30 +0.0 + 10 +46.754542 + 20 +97.435647 + 30 +0.0 + 10 +27.971417 + 20 +104.253917 + 30 +0.0 + 10 +12.676624 + 20 +117.109684 + 30 +0.0 + 10 +2.693232 + 20 +134.401170 + 30 +0.0 + 10 +-0.792469 + 20 +154.075207 + 30 +0.0 + 10 +2.693232 + 20 +173.749243 + 30 +0.0 + 10 +12.676624 + 20 +191.040729 + 30 +0.0 + 10 +27.971417 + 20 +203.896496 + 30 +0.0 + 10 +46.754542 + 20 +210.714766 + 30 +0.0 + 10 +66.713509 + 20 +210.714766 + 30 +0.0 + 10 +85.522978 + 20 +203.896496 + 30 +0.0 + 10 +100.712586 + 20 +191.040729 + 30 +0.0 + 10 +111.086802 + 20 +173.749243 + 30 +0.0 + 10 +112.423967 + 20 +160.664654 + 30 +0.0 + 10 +113.097368 + 20 +154.075207 + 30 +0.0 + 11 +113.097368 + 21 +154.075207 + 31 +0.0 + 11 +109.666446 + 21 +134.708736 + 31 +0.0 + 11 +99.973171 + 21 +117.919491 + 31 +0.0 + 11 +84.916776 + 21 +105.264990 + 31 +0.0 + 11 +66.429459 + 21 +98.553020 + 31 +0.0 + 11 +47.042909 + 21 +98.553020 + 31 +0.0 + 11 +28.555593 + 21 +105.264990 + 31 +0.0 + 11 +13.499197 + 21 +117.919491 + 31 +0.0 + 11 +3.805922 + 21 +134.708736 + 31 +0.0 + 11 +0.375001 + 21 +154.075207 + 31 +0.0 + 11 +3.805922 + 21 +173.441678 + 31 +0.0 + 11 +13.499197 + 21 +190.230923 + 31 +0.0 + 11 +28.555593 + 21 +202.885423 + 31 +0.0 + 11 +47.042909 + 21 +209.597394 + 31 +0.0 + 11 +66.429459 + 21 +209.597394 + 31 +0.0 + 11 +84.916776 + 21 +202.885423 + 31 +0.0 + 11 +99.973171 + 21 +190.230923 + 31 +0.0 + 11 +109.666446 + 21 +173.441678 + 31 +0.0 + 11 +113.097368 + 21 +154.075207 + 31 +0.0 + 0 +SPLINE + 5 +103 +100 +AcDbEntity + 8 +Layer_1 + 62 +4 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +10 + 73 +6 + 74 +4 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +37.795543 + 40 +102.597632 + 40 +154.404451 + 40 +154.404451 + 40 +154.404451 + 40 +154.404451 + 10 +141.965294 + 20 +62.316437 + 30 +0.0 + 10 +150.647125 + 20 +53.810973 + 30 +0.0 + 10 +174.214329 + 20 +30.722525 + 30 +0.0 + 10 +221.078954 + 20 +-13.525722 + 30 +0.0 + 10 +254.105150 + 20 +15.667342 + 30 +0.0 + 10 +268.777976 + 20 +28.637189 + 30 +0.0 + 11 +141.965294 + 21 +62.316437 + 31 +0.0 + 11 +169.038517 + 21 +35.943274 + 31 +0.0 + 11 +224.292337 + 21 +2.085835 + 31 +0.0 + 11 +268.777976 + 21 +28.637189 + 31 +0.0 + 0 +LWPOLYLINE + 5 +104 +100 +AcDbEntity + 8 +Layer_1 + 62 +3 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +183.548854 + 20 +142.046895 + 30 +0.0 + 10 +141.965294 + 20 +62.316437 + 30 +0.0 + 0 +LWPOLYLINE + 5 +105 +100 +AcDbEntity + 8 +Layer_1 + 62 +32 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +242.659352 + 20 +114.209972 + 30 +0.0 + 10 +183.548854 + 20 +142.046895 + 30 +0.0 + 0 +LWPOLYLINE + 5 +106 +100 +AcDbEntity + 8 +Layer_1 + 62 +5 +100 +AcDbPolyline + 90 +3 + 70 +1 + 10 +227.194404 + 20 +97.026684 + 30 +0.0 + 10 +187.672839 + 20 +86.029373 + 30 +0.0 + 10 +202.450470 + 20 +54.412140 + 30 +0.0 + 0 +SPLINE + 5 +107 +100 +AcDbEntity + 8 +Layer_1 + 62 +212 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +10 + 73 +6 + 74 +4 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +57.671738 + 40 +87.553151 + 40 +100.924559 + 40 +100.924559 + 40 +100.924559 + 40 +100.924559 + 10 +268.777976 + 20 +28.637189 + 30 +0.0 + 10 +274.336610 + 20 +48.150317 + 30 +0.0 + 10 +282.775336 + 20 +77.773765 + 30 +0.0 + 10 +261.049821 + 20 +109.076545 + 30 +0.0 + 10 +247.002130 + 20 +112.997749 + 30 +0.0 + 10 +242.659352 + 20 +114.209972 + 30 +0.0 + 11 +268.777976 + 21 +28.637189 + 31 +0.0 + 11 +273.614745 + 21 +86.105747 + 31 +0.0 + 11 +255.234979 + 21 +109.665946 + 31 +0.0 + 11 +242.659352 + 21 +114.209972 + 31 +0.0 + 0 +LWPOLYLINE + 5 +108 +100 +AcDbEntity + 8 +Layer_1 + 62 +1 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +197.639141 + 20 +200.126412 + 30 +0.0 + 10 +235.442375 + 20 +200.126412 + 30 +0.0 + 10 +235.442375 + 20 +163.010511 + 30 +0.0 + 10 +197.639141 + 20 +163.010511 + 30 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/refs/addnodes.out b/share/extensions/tests/data/refs/addnodes.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/addnodes__--id__p1__--id__r3__--max__2__0.out b/share/extensions/tests/data/refs/addnodes__--id__p1__--id__r3__--max__2__0.out new file mode 100644 index 0000000..8479f52 --- /dev/null +++ b/share/extensions/tests/data/refs/addnodes__--id__p1__--id__r3__--max__2__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/addnodes__--id__rect723__--id__rect723-5__--id__path747__--id__path1080__--id__path1115__--method__bynum__--segments__3.out b/share/extensions/tests/data/refs/addnodes__--id__rect723__--id__rect723-5__--id__path747__--id__path1080__--id__path1115__--method__bynum__--segments__3.out new file mode 100644 index 0000000..d4005eb --- /dev/null +++ b/share/extensions/tests/data/refs/addnodes__--id__rect723__--id__rect723-5__--id__path747__--id__path1080__--id__path1115__--method__bynum__--segments__3.out @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/color_randomize__-y__0__-t__0__-m__0__-o__100__--id__layer_group_rect_uu2__--id__layer_group_path__--id__root_rect_uu.out b/share/extensions/tests/data/refs/color_randomize__-y__0__-t__0__-m__0__-o__100__--id__layer_group_rect_uu2__--id__layer_group_path__--id__root_rect_uu.out new file mode 100644 index 0000000..ef45a26 --- /dev/null +++ b/share/extensions/tests/data/refs/color_randomize__-y__0__-t__0__-m__0__-o__100__--id__layer_group_rect_uu2__--id__layer_group_path__--id__root_rect_uu.out @@ -0,0 +1,40 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/color_randomize__-y__50__-t__50__-m__50__-o__100__--id__r1__--id__r2__--id__r3__--id__r4__--id__r5__--id__r6.out b/share/extensions/tests/data/refs/color_randomize__-y__50__-t__50__-m__50__-o__100__--id__r1__--id__r2__--id__r3__--id__r4__--id__r5__--id__r6.out new file mode 100644 index 0000000..7698b26 --- /dev/null +++ b/share/extensions/tests/data/refs/color_randomize__-y__50__-t__50__-m__50__-o__100__--id__r1__--id__r2__--id__r3__--id__r4__--id__r5__--id__r6.out @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/color_replace__--id__rect184.out b/share/extensions/tests/data/refs/color_replace__--id__rect184.out new file mode 100644 index 0000000..9cd11ec --- /dev/null +++ b/share/extensions/tests/data/refs/color_replace__--id__rect184.out @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/color_replace__--id__rect184__--id__rect184-8.out b/share/extensions/tests/data/refs/color_replace__--id__rect184__--id__rect184-8.out new file mode 100644 index 0000000..100c535 --- /dev/null +++ b/share/extensions/tests/data/refs/color_replace__--id__rect184__--id__rect184-8.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/convert2dashes.out b/share/extensions/tests/data/refs/convert2dashes.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash__svg.out b/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash__svg.out new file mode 100644 index 0000000..7c4e92d --- /dev/null +++ b/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash__svg.out @@ -0,0 +1,17 @@ + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash_zerolength__svg.out b/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash_zerolength__svg.out new file mode 100644 index 0000000..c5282ae --- /dev/null +++ b/share/extensions/tests/data/refs/convert2dashes__--id__dashme2__dash_zerolength__svg.out @@ -0,0 +1,15 @@ + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dhw_input__PAGE_001__DHW.out b/share/extensions/tests/data/refs/dhw_input__PAGE_001__DHW.out new file mode 100644 index 0000000..f6ae72b --- /dev/null +++ b/share/extensions/tests/data/refs/dhw_input__PAGE_001__DHW.out @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dhw_input__PGLT_161__DHW.out b/share/extensions/tests/data/refs/dhw_input__PGLT_161__DHW.out new file mode 100644 index 0000000..7e90ed5 --- /dev/null +++ b/share/extensions/tests/data/refs/dhw_input__PGLT_161__DHW.out @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dhw_input__PGLT_162__DHW.out b/share/extensions/tests/data/refs/dhw_input__PGLT_162__DHW.out new file mode 100644 index 0000000..3c0a2e7 --- /dev/null +++ b/share/extensions/tests/data/refs/dhw_input__PGLT_162__DHW.out @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dhw_input__PGLT_163__DHW.out b/share/extensions/tests/data/refs/dhw_input__PGLT_163__DHW.out new file mode 100644 index 0000000..d02a0b6 --- /dev/null +++ b/share/extensions/tests/data/refs/dhw_input__PGLT_163__DHW.out @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dimension__--id__circle1.out b/share/extensions/tests/data/refs/dimension__--id__circle1.out new file mode 100644 index 0000000..0315951 --- /dev/null +++ b/share/extensions/tests/data/refs/dimension__--id__circle1.out @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--type__visual__--xoffset__100__0__--yoffset__100__0.out b/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--type__visual__--xoffset__100__0__--yoffset__100__0.out new file mode 100644 index 0000000..bc9a26d --- /dev/null +++ b/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--type__visual__--xoffset__100__0__--yoffset__100__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--xoffset__100__0__--yoffset__100__0.out b/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--xoffset__100__0__--yoffset__100__0.out new file mode 100644 index 0000000..039bb62 --- /dev/null +++ b/share/extensions/tests/data/refs/dimension__--id__p1__--id__r3__--xoffset__100__0__--yoffset__100__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dm2svg.out b/share/extensions/tests/data/refs/dm2svg.out new file mode 100644 index 0000000..643324f --- /dev/null +++ b/share/extensions/tests/data/refs/dm2svg.out @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_m_in__svg.out b/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_m_in__svg.out new file mode 100644 index 0000000..18043ed --- /dev/null +++ b/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_m_in__svg.out @@ -0,0 +1,24 @@ + + + Illustrator Import test document + This document should import as 8.5 x 11 inches. Illustrator uses a fixedresolution of 72 px per inch. + Text in Layer 1 + + + + + + Stroke only + Fill + stroke + Fill only + + + Three squares, each1 inch (2.54 cm) to a side.Objects do not changesize when stroke is added. + + + Text in Layer 2 + + Text in Layer 2A, a sub-layerof layer 2 + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_mm_in__svg.out b/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_mm_in__svg.out new file mode 100644 index 0000000..de38260 --- /dev/null +++ b/share/extensions/tests/data/refs/doc_ai_convert__doc_ai_conv_mm_in__svg.out @@ -0,0 +1,24 @@ + + + Illustrator Import test document + This document should import as 8.5 x 11 inches. Illustrator uses a fixedresolution of 72 px per inch. + Text in Layer 1 + + + + + + Stroke only + Fill + stroke + Fill only + + + Three squares, each1 inch (2.54 cm) to a side.Objects do not changesize when stroke is added. + + + Text in Layer 2 + + Text in Layer 2A, a sub-layerof layer 2 + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/doc_ai_convert__shapes__svg.out b/share/extensions/tests/data/refs/doc_ai_convert__shapes__svg.out new file mode 100644 index 0000000..fc2f6b0 --- /dev/null +++ b/share/extensions/tests/data/refs/doc_ai_convert__shapes__svg.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/docinfo__guides__svg.out b/share/extensions/tests/data/refs/docinfo__guides__svg.out new file mode 100644 index 0000000..822cecc --- /dev/null +++ b/share/extensions/tests/data/refs/docinfo__guides__svg.out @@ -0,0 +1,10 @@ +:::SVG document related info::: +version: 0.0 +width: 1000.0 +height: 1000.0 +viewbox: [0.0, 0.0, 1000.0, 1000.0] +document-units: None +units: None +Document has 6 guides +Grid number 1: Units: None +This is a single page document. diff --git a/share/extensions/tests/data/refs/docinfo__three_pages_and_two_grids__svg.out b/share/extensions/tests/data/refs/docinfo__three_pages_and_two_grids__svg.out new file mode 100644 index 0000000..31bbb8b --- /dev/null +++ b/share/extensions/tests/data/refs/docinfo__three_pages_and_two_grids__svg.out @@ -0,0 +1,14 @@ +:::SVG document related info::: +version: 1.2-dev (1:1.0+devel+202201200004+c1616499b1) +width: 793.7007874015748 +height: 1122.51968503937 +viewbox: [0.0, 0.0, 210.0, 297.0] +document-units: mm +units: None +Document has 3 guides +Grid number 1: Units: cm +Grid number 2: Units: in +Document has 3 pages +Page number 1: x: 0 y: 0 width: 210 height: 297 +Page number 2: x: 220 y: 0 width: 210 height: 297 +Page number 3: x: 0 y: 305 width: 430 height: 107.75 diff --git a/share/extensions/tests/data/refs/dpiswitcher.out b/share/extensions/tests/data/refs/dpiswitcher.out new file mode 100644 index 0000000..0b9cd97 --- /dev/null +++ b/share/extensions/tests/data/refs/dpiswitcher.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/dpiswitcher__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/dpiswitcher__--id__p1__--id__r3.out new file mode 100644 index 0000000..0b9cd97 --- /dev/null +++ b/share/extensions/tests/data/refs/dpiswitcher__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/dpiswitcher__--switcher__0.out b/share/extensions/tests/data/refs/dpiswitcher__--switcher__0.out new file mode 100644 index 0000000..7cbe84a --- /dev/null +++ b/share/extensions/tests/data/refs/dpiswitcher__--switcher__0.out @@ -0,0 +1,40 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dpiswitcher__--switcher__1.out b/share/extensions/tests/data/refs/dpiswitcher__--switcher__1.out new file mode 100644 index 0000000..6ccc988 --- /dev/null +++ b/share/extensions/tests/data/refs/dpiswitcher__--switcher__1.out @@ -0,0 +1,40 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/draw_from_triangle__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/draw_from_triangle__--id__p1__--id__r3.out new file mode 100644 index 0000000..61c34b2 --- /dev/null +++ b/share/extensions/tests/data/refs/draw_from_triangle__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/dxf12_outlines__clips_and_masks__svg.out b/share/extensions/tests/data/refs/dxf12_outlines__clips_and_masks__svg.out new file mode 100644 index 0000000..d66a962 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf12_outlines__clips_and_masks__svg.out @@ -0,0 +1,932 @@ +999 +"DXF R12 Output" (www.mydxf.blogspot.com) + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 + 0 + 20 + 0 + 9 +$EXTMAX + 10 + 8.5 + 20 + 11 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +0 +LINE +8 +Layer 1 +10 +103.010000 +20 +239.724000 +11 +102.887147 +21 +237.290427 +0 +LINE +8 +Layer 1 +10 +102.887147 +20 +237.290427 +11 +102.526500 +21 +234.927148 +0 +LINE +8 +Layer 1 +10 +102.526500 +20 +234.927148 +11 +101.940024 +21 +232.646127 +0 +LINE +8 +Layer 1 +10 +101.940024 +20 +232.646127 +11 +101.139681 +21 +230.459329 +0 +LINE +8 +Layer 1 +10 +101.139681 +20 +230.459329 +11 +100.137437 +21 +228.378717 +0 +LINE +8 +Layer 1 +10 +100.137437 +20 +228.378717 +11 +98.945254 +21 +226.416255 +0 +LINE +8 +Layer 1 +10 +98.945254 +20 +226.416255 +11 +97.575096 +21 +224.583908 +0 +LINE +8 +Layer 1 +10 +97.575096 +20 +224.583908 +11 +96.038926 +21 +222.893639 +0 +LINE +8 +Layer 1 +10 +96.038926 +20 +222.893639 +11 +94.348709 +21 +221.357413 +0 +LINE +8 +Layer 1 +10 +94.348709 +20 +221.357413 +11 +92.516408 +21 +219.987193 +0 +LINE +8 +Layer 1 +10 +92.516408 +20 +219.987193 +11 +90.553986 +21 +218.794944 +0 +LINE +8 +Layer 1 +10 +90.553986 +20 +218.794944 +11 +88.473408 +21 +217.792630 +0 +LINE +8 +Layer 1 +10 +88.473408 +20 +217.792630 +11 +86.286637 +21 +216.992214 +0 +LINE +8 +Layer 1 +10 +86.286637 +20 +216.992214 +11 +84.005636 +21 +216.405661 +0 +LINE +8 +Layer 1 +10 +84.005636 +20 +216.405661 +11 +81.642369 +21 +216.044935 +0 +LINE +8 +Layer 1 +10 +81.642369 +20 +216.044935 +11 +79.208800 +21 +215.922000 +0 +LINE +8 +Layer 1 +10 +79.208800 +20 +215.922000 +11 +76.856275 +21 +216.038472 +0 +LINE +8 +Layer 1 +10 +76.856275 +20 +216.038472 +11 +74.543598 +21 +216.383576 +0 +LINE +8 +Layer 1 +10 +74.543598 +20 +216.383576 +11 +72.286375 +21 +216.950849 +0 +LINE +8 +Layer 1 +10 +72.286375 +20 +216.950849 +11 +70.100214 +21 +217.733825 +0 +LINE +8 +Layer 1 +10 +70.100214 +20 +217.733825 +11 +68.000724 +21 +218.726040 +0 +LINE +8 +Layer 1 +10 +68.000724 +20 +218.726040 +11 +66.003512 +21 +219.921027 +0 +LINE +8 +Layer 1 +10 +66.003512 +20 +219.921027 +11 +64.124185 +21 +221.312323 +0 +LINE +8 +Layer 1 +10 +64.124185 +20 +221.312323 +11 +62.378350 +21 +222.893463 +0 +LINE +8 +Layer 1 +10 +62.378350 +20 +222.893463 +11 +60.797233 +21 +224.639317 +0 +LINE +8 +Layer 1 +10 +60.797233 +20 +224.639317 +11 +59.405961 +21 +226.518661 +0 +LINE +8 +Layer 1 +10 +59.405961 +20 +226.518661 +11 +58.210998 +21 +228.515889 +0 +LINE +8 +Layer 1 +10 +58.210998 +20 +228.515889 +11 +57.218810 +21 +230.615392 +0 +LINE +8 +Layer 1 +10 +57.218810 +20 +230.615392 +11 +56.435862 +21 +232.801562 +0 +LINE +8 +Layer 1 +10 +56.435862 +20 +232.801562 +11 +55.868617 +21 +235.058792 +0 +LINE +8 +Layer 1 +10 +55.868617 +20 +235.058792 +11 +55.523542 +21 +237.371474 +0 +LINE +8 +Layer 1 +10 +55.523542 +20 +237.371474 +11 +55.407100 +21 +239.724000 +0 +LINE +8 +Layer 1 +10 +55.407100 +20 +239.724000 +11 +55.530052 +21 +242.157533 +0 +LINE +8 +Layer 1 +10 +55.530052 +20 +242.157533 +11 +55.890788 +21 +244.520764 +0 +LINE +8 +Layer 1 +10 +55.890788 +20 +244.520764 +11 +56.477344 +21 +246.801731 +0 +LINE +8 +Layer 1 +10 +56.477344 +20 +246.801731 +11 +57.277757 +21 +248.988471 +0 +LINE +8 +Layer 1 +10 +57.277757 +20 +248.988471 +11 +58.280063 +21 +251.069020 +0 +LINE +8 +Layer 1 +10 +58.280063 +20 +251.069020 +11 +59.472299 +21 +253.031415 +0 +LINE +8 +Layer 1 +10 +59.472299 +20 +253.031415 +11 +60.842500 +21 +254.863693 +0 +LINE +8 +Layer 1 +10 +60.842500 +20 +254.863693 +11 +62.378704 +21 +256.553891 +0 +LINE +8 +Layer 1 +10 +62.378704 +20 +256.553891 +11 +64.068947 +21 +258.090045 +0 +LINE +8 +Layer 1 +10 +64.068947 +20 +258.090045 +11 +65.901265 +21 +259.460193 +0 +LINE +8 +Layer 1 +10 +65.901265 +20 +259.460193 +11 +67.863695 +21 +260.652371 +0 +LINE +8 +Layer 1 +10 +67.863695 +20 +260.652371 +11 +69.944274 +21 +261.654615 +0 +LINE +8 +Layer 1 +10 +69.944274 +20 +261.654615 +11 +72.131037 +21 +262.454964 +0 +LINE +8 +Layer 1 +10 +72.131037 +20 +262.454964 +11 +74.412022 +21 +263.041453 +0 +LINE +8 +Layer 1 +10 +74.412022 +20 +263.041453 +11 +76.775264 +21 +263.402119 +0 +LINE +8 +Layer 1 +10 +76.775264 +20 +263.402119 +11 +79.208800 +21 +263.525000 +0 +LINE +8 +Layer 1 +10 +79.208800 +20 +263.525000 +11 +81.642298 +21 +263.402072 +0 +LINE +8 +Layer 1 +10 +81.642298 +20 +263.402072 +11 +84.005501 +21 +263.041366 +0 +LINE +8 +Layer 1 +10 +84.005501 +20 +263.041366 +11 +86.286444 +21 +262.454845 +0 +LINE +8 +Layer 1 +10 +86.286444 +20 +262.454845 +11 +88.473166 +21 +261.654471 +0 +LINE +8 +Layer 1 +10 +88.473166 +20 +261.654471 +11 +90.553702 +21 +260.652209 +0 +LINE +8 +Layer 1 +10 +90.553702 +20 +260.652209 +11 +92.516091 +21 +259.460020 +0 +LINE +8 +Layer 1 +10 +92.516091 +20 +259.460020 +11 +94.348369 +21 +258.089868 +0 +LINE +8 +Layer 1 +10 +94.348369 +20 +258.089868 +11 +96.038573 +21 +256.553714 +0 +LINE +8 +Layer 1 +10 +96.038573 +20 +256.553714 +11 +97.574740 +21 +254.863523 +0 +LINE +8 +Layer 1 +10 +97.574740 +20 +254.863523 +11 +98.944908 +21 +253.031257 +0 +LINE +8 +Layer 1 +10 +98.944908 +20 +253.031257 +11 +100.137114 +21 +251.068878 +0 +LINE +8 +Layer 1 +10 +100.137114 +20 +251.068878 +11 +101.139394 +21 +248.988350 +0 +LINE +8 +Layer 1 +10 +101.139394 +20 +248.988350 +11 +101.939785 +21 +246.801635 +0 +LINE +8 +Layer 1 +10 +101.939785 +20 +246.801635 +11 +102.526325 +21 +244.520697 +0 +LINE +8 +Layer 1 +10 +102.526325 +20 +244.520697 +11 +102.887051 +21 +242.157497 +0 +LINE +8 +Layer 1 +10 +102.887051 +20 +242.157497 +11 +103.010000 +21 +239.724000 +0 +LINE +8 +Layer 1 +10 +103.010000 +20 +239.724000 +11 +103.010000 +21 +239.724000 +0 +LINE +8 +Layer 1 +10 +160.043000 +20 +35.117500 +11 +145.155900 +21 +46.099100 +0 +LINE +8 +Layer 1 +10 +145.155900 +20 +46.099100 +11 +127.669800 +21 +40.061060 +0 +LINE +8 +Layer 1 +10 +127.669800 +20 +40.061060 +11 +133.513510 +21 +57.613060 +0 +LINE +8 +Layer 1 +10 +133.513510 +20 +57.613060 +11 +122.367510 +21 +72.377460 +0 +LINE +8 +Layer 1 +10 +122.367510 +20 +72.377460 +11 +140.866210 +21 +72.243630 +0 +LINE +8 +Layer 1 +10 +140.866210 +20 +72.243630 +11 +151.463710 +21 +87.406530 +0 +LINE +8 +Layer 1 +10 +151.463710 +20 +87.406530 +11 +157.052850 +21 +69.771830 +0 +LINE +8 +Layer 1 +10 +157.052850 +20 +69.771830 +11 +174.748450 +21 +64.378650 +0 +LINE +8 +Layer 1 +10 +174.748450 +20 +64.378650 +11 +159.703950 +21 +53.613650 +0 +LINE +8 +Layer 1 +10 +159.703950 +20 +53.613650 +11 +160.043000 +21 +35.117500 + 0 +ENDSEC + 0 +EOF \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf12_outlines__dxf_nested_transforms__svg.out b/share/extensions/tests/data/refs/dxf12_outlines__dxf_nested_transforms__svg.out new file mode 100644 index 0000000..203f380 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf12_outlines__dxf_nested_transforms__svg.out @@ -0,0 +1,296 @@ +999 +"DXF R12 Output" (www.mydxf.blogspot.com) + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 + 0 + 20 + 0 + 9 +$EXTMAX + 10 + 8.5 + 20 + 11 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +0 +LINE +8 +Layer 1 +10 +106.205000 +20 +165.429000 +11 +66.544600 +21 +195.428900 +0 +LINE +8 +Layer 1 +10 +66.544600 +20 +195.428900 +11 +66.544800 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +66.544800 +20 +221.696000 +11 +100.871000 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +100.871000 +20 +221.696000 +11 +140.531400 +21 +191.696100 +0 +LINE +8 +Layer 1 +10 +140.531400 +20 +191.696100 +11 +140.532000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +140.532000 +20 +165.429000 +11 +106.205000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +0.000000 +20 +297.000000 +11 +210.000000 +21 +297.000000 +0 +LINE +8 +Layer 1 +10 +210.000000 +20 +297.000000 +11 +210.000000 +21 +0.000000 +0 +LINE +8 +Layer 1 +10 +210.000000 +20 +0.000000 +11 +0.000000 +21 +0.000000 +0 +LINE +8 +Layer 1 +10 +0.000000 +20 +0.000000 +11 +0.000000 +21 +297.000000 +0 +LINE +8 +Layer 1 +10 +66.542700 +20 +221.696000 +11 +100.869000 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +100.869000 +20 +221.696000 +11 +100.869000 +21 +195.428000 +0 +LINE +8 +Layer 1 +10 +100.869000 +20 +195.428000 +11 +66.542700 +21 +195.428000 +0 +LINE +8 +Layer 1 +10 +66.542700 +20 +195.428000 +11 +66.542700 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +106.203000 +20 +191.696000 +11 +140.530000 +21 +191.696000 +0 +LINE +8 +Layer 1 +10 +140.530000 +20 +191.696000 +11 +140.530000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +140.530000 +20 +165.429000 +11 +106.203000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +106.203000 +20 +165.429000 +11 +106.203000 +21 +191.696000 +0 +LINE +8 +Layer 1 +10 +185.881000 +20 +135.429000 +11 +151.555000 +21 +135.429000 +0 +LINE +8 +Layer 1 +10 +151.555000 +20 +135.429000 +11 +151.555000 +21 +161.696000 +0 +LINE +8 +Layer 1 +10 +151.555000 +20 +161.696000 +11 +185.881000 +21 +161.696000 +0 +LINE +8 +Layer 1 +10 +185.881000 +20 +161.696000 +11 +185.881000 +21 +135.429000 + 0 +ENDSEC + 0 +EOF \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf12_outlines__preserved-transforms__svg.out b/share/extensions/tests/data/refs/dxf12_outlines__preserved-transforms__svg.out new file mode 100644 index 0000000..1b2c6c3 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf12_outlines__preserved-transforms__svg.out @@ -0,0 +1,224 @@ +999 +"DXF R12 Output" (www.mydxf.blogspot.com) + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 + 0 + 20 + 0 + 9 +$EXTMAX + 10 + 8.5 + 20 + 11 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +0 +LINE +8 +Layer 1 +10 +0.000000 +20 +297.000000 +11 +210.000000 +21 +297.000000 +0 +LINE +8 +Layer 1 +10 +210.000000 +20 +297.000000 +11 +210.000000 +21 +0.000000 +0 +LINE +8 +Layer 1 +10 +210.000000 +20 +0.000000 +11 +0.000000 +21 +0.000000 +0 +LINE +8 +Layer 1 +10 +0.000000 +20 +0.000000 +11 +0.000000 +21 +297.000000 +0 +LINE +8 +Layer 1 +10 +66.542700 +20 +221.696000 +11 +100.869000 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +100.869000 +20 +221.696000 +11 +100.869000 +21 +195.428000 +0 +LINE +8 +Layer 1 +10 +100.869000 +20 +195.428000 +11 +66.542700 +21 +195.428000 +0 +LINE +8 +Layer 1 +10 +66.542700 +20 +195.428000 +11 +66.542700 +21 +221.696000 +0 +LINE +8 +Layer 1 +10 +106.203000 +20 +191.696000 +11 +140.530000 +21 +191.696000 +0 +LINE +8 +Layer 1 +10 +140.530000 +20 +191.696000 +11 +140.530000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +140.530000 +20 +165.429000 +11 +106.203000 +21 +165.429000 +0 +LINE +8 +Layer 1 +10 +106.203000 +20 +165.429000 +11 +106.203000 +21 +191.696000 +0 +LINE +8 +Layer 1 +10 +185.881000 +20 +135.429000 +11 +151.555000 +21 +135.429000 +0 +LINE +8 +Layer 1 +10 +151.555000 +20 +135.429000 +11 +151.555000 +21 +161.696000 +0 +LINE +8 +Layer 1 +10 +151.555000 +20 +161.696000 +11 +185.881000 +21 +161.696000 +0 +LINE +8 +Layer 1 +10 +185.881000 +20 +161.696000 +11 +185.881000 +21 +135.429000 + 0 +ENDSEC + 0 +EOF \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf12_outlines__scale_not_unity__svg.out b/share/extensions/tests/data/refs/dxf12_outlines__scale_not_unity__svg.out new file mode 100644 index 0000000..56a6360 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf12_outlines__scale_not_unity__svg.out @@ -0,0 +1,272 @@ +999 +"DXF R12 Output" (www.mydxf.blogspot.com) + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 + 0 + 20 + 0 + 9 +$EXTMAX + 10 + 8.5 + 20 + 11 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +0 +LINE +8 +Ebene 1 +10 +58.683500 +20 +179.770000 +11 +158.683000 +21 +179.770000 +0 +LINE +8 +Ebene 1 +10 +158.683000 +20 +179.770000 +11 +158.683000 +21 +109.770000 +0 +LINE +8 +Ebene 1 +10 +158.683000 +20 +109.770000 +11 +58.683500 +21 +109.770000 +0 +LINE +8 +Ebene 1 +10 +58.683500 +20 +109.770000 +11 +58.683500 +21 +179.770000 +0 +LINE +8 +Ebene 1 +10 +0.000000 +20 +297.000000 +11 +50.000000 +21 +297.000000 +0 +LINE +8 +Ebene 1 +10 +50.000000 +20 +297.000000 +11 +50.000000 +21 +217.000000 +0 +LINE +8 +Ebene 1 +10 +50.000000 +20 +217.000000 +11 +0.000000 +21 +217.000000 +0 +LINE +8 +Ebene 1 +10 +0.000000 +20 +217.000000 +11 +0.000000 +21 +297.000000 +0 +LINE +8 +Ebene 1 +10 +190.000000 +20 +297.000000 +11 +210.000000 +21 +297.000000 +0 +LINE +8 +Ebene 1 +10 +210.000000 +20 +297.000000 +11 +210.000000 +21 +287.000000 +0 +LINE +8 +Ebene 1 +10 +210.000000 +20 +287.000000 +11 +190.000000 +21 +287.000000 +0 +LINE +8 +Ebene 1 +10 +190.000000 +20 +287.000000 +11 +190.000000 +21 +297.000000 +0 +LINE +8 +Ebene 1 +10 +0.000000 +20 +30.000000 +11 +15.000000 +21 +30.000000 +0 +LINE +8 +Ebene 1 +10 +15.000000 +20 +30.000000 +11 +15.000000 +21 +0.000000 +0 +LINE +8 +Ebene 1 +10 +15.000000 +20 +0.000000 +11 +0.000000 +21 +0.000000 +0 +LINE +8 +Ebene 1 +10 +0.000000 +20 +0.000000 +11 +0.000000 +21 +30.000000 +0 +LINE +8 +Ebene 1 +10 +140.000000 +20 +70.000000 +11 +210.000000 +21 +51.259800 +0 +LINE +8 +Ebene 1 +10 +210.000000 +20 +51.259800 +11 +210.000000 +21 +0.000000 +0 +LINE +8 +Ebene 1 +10 +210.000000 +20 +0.000000 +11 +152.197000 +21 +0.000000 +0 +LINE +8 +Ebene 1 +10 +152.197000 +20 +0.000000 +11 +140.000000 +21 +70.000000 + 0 +ENDSEC + 0 +EOF \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf12_outlines__shapes__svg.out b/share/extensions/tests/data/refs/dxf12_outlines__shapes__svg.out new file mode 100644 index 0000000..dcf47fc --- /dev/null +++ b/share/extensions/tests/data/refs/dxf12_outlines__shapes__svg.out @@ -0,0 +1,1424 @@ +999 +"DXF R12 Output" (www.mydxf.blogspot.com) + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1009 + 9 +$EXTMIN + 10 + 0 + 20 + 0 + 9 +$EXTMAX + 10 + 8.5 + 20 + 11 + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES +0 +LINE +8 +Layer 1 +10 +2.828520 +20 +263.409000 +11 +-0.351372 +21 +264.578000 +0 +LINE +8 +Layer 1 +10 +-0.351372 +20 +264.578000 +11 +2.828520 +21 +265.748000 +0 +LINE +8 +Layer 1 +10 +2.828520 +20 +265.748000 +11 +2.543171 +21 +265.190016 +0 +LINE +8 +Layer 1 +10 +2.543171 +20 +265.190016 +11 +2.448604 +21 +264.583375 +0 +LINE +8 +Layer 1 +10 +2.448604 +20 +264.583375 +11 +2.543995 +21 +263.974297 +0 +LINE +8 +Layer 1 +10 +2.543995 +20 +263.974297 +11 +2.828520 +21 +263.409000 +0 +LINE +8 +Layer 1 +10 +2.828520 +20 +263.409000 +11 +2.828520 +21 +263.409000 +0 +LINE +8 +Slide2 +10 +207.191000 +20 +138.159000 +11 +204.538579 +21 +136.486927 +0 +LINE +8 +Slide2 +10 +204.538579 +20 +136.486927 +11 +201.446738 +21 +135.075179 +0 +LINE +8 +Slide2 +10 +201.446738 +20 +135.075179 +11 +197.989198 +21 +133.937144 +0 +LINE +8 +Slide2 +10 +197.989198 +20 +133.937144 +11 +194.239677 +21 +133.086207 +0 +LINE +8 +Slide2 +10 +194.239677 +20 +133.086207 +11 +190.271897 +21 +132.535757 +0 +LINE +8 +Slide2 +10 +190.271897 +20 +132.535757 +11 +186.159578 +21 +132.299179 +0 +LINE +8 +Slide2 +10 +186.159578 +20 +132.299179 +11 +181.976439 +21 +132.389861 +0 +LINE +8 +Slide2 +10 +181.976439 +20 +132.389861 +11 +177.796200 +21 +132.821190 +0 +LINE +8 +Slide2 +10 +177.796200 +20 +132.821190 +11 +173.808049 +21 +133.581652 +0 +LINE +8 +Slide2 +10 +173.808049 +20 +133.581652 +11 +170.183861 +21 +134.630080 +0 +LINE +8 +Slide2 +10 +170.183861 +20 +134.630080 +11 +166.971385 +21 +135.935365 +0 +LINE +8 +Slide2 +10 +166.971385 +20 +135.935365 +11 +164.218373 +21 +137.466396 +0 +LINE +8 +Slide2 +10 +164.218373 +20 +137.466396 +11 +161.972578 +21 +139.192064 +0 +LINE +8 +Slide2 +10 +161.972578 +20 +139.192064 +11 +160.281749 +21 +141.081259 +0 +LINE +8 +Slide2 +10 +160.281749 +20 +141.081259 +11 +159.659370 +21 +142.077457 +0 +LINE +8 +Slide2 +10 +159.659370 +20 +142.077457 +11 +159.193640 +21 +143.102871 +0 +LINE +8 +Slide2 +10 +159.193640 +20 +143.102871 +11 +158.890527 +21 +144.153611 +0 +LINE +8 +Slide2 +10 +158.890527 +20 +144.153611 +11 +158.756000 +21 +145.225790 +0 +LINE +8 +Slide2 +10 +158.756000 +20 +145.225790 +11 +158.794810 +21 +146.299897 +0 +LINE +8 +Slide2 +10 +158.794810 +20 +146.299897 +11 +159.003948 +21 +147.356344 +0 +LINE +8 +Slide2 +10 +159.003948 +20 +147.356344 +11 +159.377799 +21 +148.391114 +0 +LINE +8 +Slide2 +10 +159.377799 +20 +148.391114 +11 +159.910746 +21 +149.400189 +0 +LINE +8 +Slide2 +10 +159.910746 +20 +149.400189 +11 +161.431464 +21 +151.325184 +0 +LINE +8 +Slide2 +10 +161.431464 +20 +151.325184 +11 +163.521171 +21 +153.099184 +0 +LINE +8 +Slide2 +10 +163.521171 +20 +153.099184 +11 +166.134938 +21 +154.690048 +0 +LINE +8 +Slide2 +10 +166.134938 +20 +154.690048 +11 +169.227835 +21 +156.065632 +0 +LINE +8 +Slide2 +10 +169.227835 +20 +156.065632 +11 +172.754932 +21 +157.193793 +0 +LINE +8 +Slide2 +10 +172.754932 +20 +157.193793 +11 +176.671300 +21 +158.042390 +0 +LINE +8 +Slide2 +10 +176.671300 +20 +158.042390 +11 +180.808925 +21 +158.566469 +0 +LINE +8 +Slide2 +10 +180.808925 +20 +158.566469 +11 +184.979820 +21 +158.750305 +0 +LINE +8 +Slide2 +10 +184.979820 +20 +158.750305 +11 +189.109144 +21 +158.605628 +0 +LINE +8 +Slide2 +10 +189.109144 +20 +158.605628 +11 +193.122058 +21 +158.144169 +0 +LINE +8 +Slide2 +10 +193.122058 +20 +158.144169 +11 +196.943721 +21 +157.377657 +0 +LINE +8 +Slide2 +10 +196.943721 +20 +157.377657 +11 +200.499293 +21 +156.317823 +0 +LINE +8 +Slide2 +10 +200.499293 +20 +156.317823 +11 +203.713932 +21 +154.976397 +0 +LINE +8 +Slide2 +10 +203.713932 +20 +154.976397 +11 +206.512800 +21 +153.365110 +0 +LINE +8 +Slide2 +10 +206.512800 +20 +153.365110 +11 +185.208000 +21 +145.521000 +0 +LINE +8 +Slide2 +10 +185.208000 +20 +145.521000 +11 +207.191000 +21 +138.159000 +0 +LINE +8 +Slide2 +10 +26.458300 +20 +105.833000 +11 +52.916600 +21 +79.374900 +0 +LINE +8 +Slide2 +10 +52.916600 +20 +79.374900 +11 +79.374900 +21 +105.833000 +0 +LINE +8 +Slide2 +10 +79.374900 +20 +105.833000 +11 +105.833000 +21 +79.374900 +0 +LINE +8 +Slide2 +10 +132.292000 +20 +105.833000 +11 +132.343676 +21 +104.696120 +0 +LINE +8 +Slide2 +10 +132.343676 +20 +104.696120 +11 +132.705411 +21 +101.698891 +0 +LINE +8 +Slide2 +10 +132.705411 +20 +101.698891 +11 +133.099443 +21 +99.696431 +0 +LINE +8 +Slide2 +10 +133.099443 +20 +99.696431 +11 +133.687262 +21 +97.461429 +0 +LINE +8 +Slide2 +10 +133.687262 +20 +97.461429 +11 +134.507624 +21 +95.071397 +0 +LINE +8 +Slide2 +10 +134.507624 +20 +95.071397 +11 +135.599288 +21 +92.603850 +0 +LINE +8 +Slide2 +10 +135.599288 +20 +92.603850 +11 +137.001009 +21 +90.136303 +0 +LINE +8 +Slide2 +10 +137.001009 +20 +90.136303 +11 +138.751546 +21 +87.746271 +0 +LINE +8 +Slide2 +10 +138.751546 +20 +87.746271 +11 +140.889656 +21 +85.511269 +0 +LINE +8 +Slide2 +10 +140.889656 +20 +85.511269 +11 +143.454095 +21 +83.508809 +0 +LINE +8 +Slide2 +10 +143.454095 +20 +83.508809 +11 +146.483622 +21 +81.816408 +0 +LINE +8 +Slide2 +10 +146.483622 +20 +81.816408 +11 +150.016994 +21 +80.511580 +0 +LINE +8 +Slide2 +10 +150.016994 +20 +80.511580 +11 +151.984733 +21 +80.028729 +0 +LINE +8 +Slide2 +10 +151.984733 +20 +80.028729 +11 +154.092967 +21 +79.671839 +0 +LINE +8 +Slide2 +10 +154.092967 +20 +79.671839 +11 +156.346541 +21 +79.450600 +0 +LINE +8 +Slide2 +10 +156.346541 +20 +79.450600 +11 +158.750300 +21 +79.374700 +0 +LINE +8 +Slide2 +10 +158.750300 +20 +79.374700 +11 +161.078966 +21 +79.450600 +0 +LINE +8 +Slide2 +10 +161.078966 +20 +79.450600 +11 +163.116953 +21 +79.671839 +0 +LINE +8 +Slide2 +10 +163.116953 +20 +79.671839 +11 +164.883639 +21 +80.028729 +0 +LINE +8 +Slide2 +10 +164.883639 +20 +80.028729 +11 +166.398402 +21 +80.511580 +0 +LINE +8 +Slide2 +10 +166.398402 +20 +80.511580 +11 +167.680622 +21 +81.110703 +0 +LINE +8 +Slide2 +10 +167.680622 +20 +81.110703 +11 +168.749677 +21 +81.816408 +0 +LINE +8 +Slide2 +10 +168.749677 +20 +81.816408 +11 +169.624946 +21 +82.619007 +0 +LINE +8 +Slide2 +10 +169.624946 +20 +82.619007 +11 +170.325806 +21 +83.508809 +0 +LINE +8 +Slide2 +10 +170.325806 +20 +83.508809 +11 +170.871638 +21 +84.476126 +0 +LINE +8 +Slide2 +10 +170.871638 +20 +84.476126 +11 +171.281819 +21 +85.511269 +0 +LINE +8 +Slide2 +10 +171.281819 +20 +85.511269 +11 +171.772745 +21 +87.746271 +0 +LINE +8 +Slide2 +10 +171.772745 +20 +87.746271 +11 +171.953612 +21 +90.136303 +0 +LINE +8 +Slide2 +10 +171.953612 +20 +90.136303 +11 +171.979450 +21 +92.603850 +0 +LINE +8 +Slide2 +10 +171.979450 +20 +92.603850 +11 +172.005288 +21 +95.071397 +0 +LINE +8 +Slide2 +10 +172.005288 +20 +95.071397 +11 +172.186155 +21 +97.461429 +0 +LINE +8 +Slide2 +10 +172.186155 +20 +97.461429 +11 +172.677081 +21 +99.696431 +0 +LINE +8 +Slide2 +10 +172.677081 +20 +99.696431 +11 +173.087262 +21 +100.731574 +0 +LINE +8 +Slide2 +10 +173.087262 +20 +100.731574 +11 +173.633094 +21 +101.698891 +0 +LINE +8 +Slide2 +10 +173.633094 +20 +101.698891 +11 +174.333954 +21 +102.588693 +0 +LINE +8 +Slide2 +10 +174.333954 +20 +102.588693 +11 +175.209223 +21 +103.391292 +0 +LINE +8 +Slide2 +10 +175.209223 +20 +103.391292 +11 +176.278278 +21 +104.096997 +0 +LINE +8 +Slide2 +10 +176.278278 +20 +104.096997 +11 +177.560498 +21 +104.696120 +0 +LINE +8 +Slide2 +10 +177.560498 +20 +104.696120 +11 +179.075261 +21 +105.178971 +0 +LINE +8 +Slide2 +10 +179.075261 +20 +105.178971 +11 +180.841947 +21 +105.535861 +0 +LINE +8 +Slide2 +10 +180.841947 +20 +105.535861 +11 +182.879934 +21 +105.757100 +0 +LINE +8 +Slide2 +10 +182.879934 +20 +105.757100 +11 +185.208600 +21 +105.833000 +0 +LINE +8 +Slide2 +10 +185.208600 +20 +105.833000 +11 +187.612359 +21 +105.757100 +0 +LINE +8 +Slide2 +10 +187.612359 +20 +105.757100 +11 +189.865933 +21 +105.535861 +0 +LINE +8 +Slide2 +10 +189.865933 +20 +105.535861 +11 +191.974167 +21 +105.178971 +0 +LINE +8 +Slide2 +10 +191.974167 +20 +105.178971 +11 +193.941906 +21 +104.696120 +0 +LINE +8 +Slide2 +10 +193.941906 +20 +104.696120 +11 +197.475278 +21 +103.391292 +0 +LINE +8 +Slide2 +10 +197.475278 +20 +103.391292 +11 +200.504805 +21 +101.698891 +0 +LINE +8 +Slide2 +10 +200.504805 +20 +101.698891 +11 +203.069244 +21 +99.696431 +0 +LINE +8 +Slide2 +10 +203.069244 +20 +99.696431 +11 +205.207354 +21 +97.461429 +0 +LINE +8 +Slide2 +10 +205.207354 +20 +97.461429 +11 +206.957891 +21 +95.071397 +0 +LINE +8 +Slide2 +10 +206.957891 +20 +95.071397 +11 +208.359613 +21 +92.603850 +0 +LINE +8 +Slide2 +10 +208.359613 +20 +92.603850 +11 +209.451276 +21 +90.136303 +0 +LINE +8 +Slide2 +10 +209.451276 +20 +90.136303 +11 +210.271638 +21 +87.746271 +0 +LINE +8 +Slide2 +10 +210.271638 +20 +87.746271 +11 +210.859457 +21 +85.511269 +0 +LINE +8 +Slide2 +10 +210.859457 +20 +85.511269 +11 +211.253489 +21 +83.508809 +0 +LINE +8 +Slide2 +10 +211.253489 +20 +83.508809 +11 +211.615224 +21 +80.511580 +0 +LINE +8 +Slide2 +10 +211.615224 +20 +80.511580 +11 +211.666900 +21 +79.374700 +0 +LINE +8 +Slide2 +10 +64.778700 +20 +29.331700 +11 +52.782800 +21 +31.483940 +0 +LINE +8 +Slide2 +10 +52.782800 +20 +31.483940 +11 +44.209180 +21 +22.822150 +0 +LINE +8 +Slide2 +10 +44.209180 +20 +22.822150 +11 +42.549150 +21 +34.896050 +0 +LINE +8 +Slide2 +10 +42.549150 +20 +34.896050 +11 +31.661850 +21 +40.373400 +0 +LINE +8 +Slide2 +10 +31.661850 +20 +40.373400 +11 +42.631750 +21 +45.683210 +0 +LINE +8 +Slide2 +10 +42.631750 +20 +45.683210 +11 +44.476680 +21 +57.730210 +0 +LINE +8 +Slide2 +10 +44.476680 +20 +57.730210 +11 +52.916510 +21 +48.938000 +0 +LINE +8 +Slide2 +10 +52.916510 +20 +48.938000 +11 +64.944010 +21 +50.906090 +0 +LINE +8 +Slide2 +10 +64.944010 +20 +50.906090 +11 +59.190170 +21 +40.162390 +0 +LINE +8 +Slide2 +10 +59.190170 +20 +40.162390 +11 +64.778700 +21 +29.331700 + 0 +ENDSEC + 0 +EOF \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__--textscale__1__411__CADTextHeight__dxf.out b/share/extensions/tests/data/refs/dxf_input__--textscale__1__411__CADTextHeight__dxf.out new file mode 100644 index 0000000..88041a9 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__--textscale__1__411__CADTextHeight__dxf.out @@ -0,0 +1,2 @@ + + CADTextHeight.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual2.18427.9981.443.687Text height for L: 2.25CADText height for L: 45.0CADCAD text height 3 mm corresponds to 12 pt = 16 px in svgText written in this file:text scale factor = (240 x 25.4)/(45.0 x 96) = 1.411...180 pt = 240 px9 pt = 12 pxLL \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__CADTextHeight__dxf.out b/share/extensions/tests/data/refs/dxf_input__CADTextHeight__dxf.out new file mode 100644 index 0000000..c48c1c8 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__CADTextHeight__dxf.out @@ -0,0 +1,2 @@ + + CADTextHeight.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual2.18427.9981.443.687Text height for L: 2.25CADText height for L: 45.0CADCAD text height 3 mm corresponds to 12 pt = 16 px in svgText written in this file:text scale factor = (240 x 25.4)/(45.0 x 96) = 1.411...180 pt = 240 px9 pt = 12 pxLL \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__color__dxf.out b/share/extensions/tests/data/refs/dxf_input__color__dxf.out new file mode 100644 index 0000000..15c056a --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__color__dxf.out @@ -0,0 +1,2 @@ + + color.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__dxf_multiple_inserts__dxf.out b/share/extensions/tests/data/refs/dxf_input__dxf_multiple_inserts__dxf.out new file mode 100644 index 0000000..cb57f96 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__dxf_multiple_inserts__dxf.out @@ -0,0 +1,2 @@ + + dxf_multiple_inserts.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual33.68 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__dxf_polylines__dxf.out b/share/extensions/tests/data/refs/dxf_input__dxf_polylines__dxf.out new file mode 100644 index 0000000..f906422 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__dxf_polylines__dxf.out @@ -0,0 +1,2 @@ + + dxf_polylines.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manualŒãg  1–‡‚íÙ‚¿ \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__dxf_with_arc__dxf.out b/share/extensions/tests/data/refs/dxf_input__dxf_with_arc__dxf.out new file mode 100644 index 0000000..f145178 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__dxf_with_arc__dxf.out @@ -0,0 +1,2 @@ + + dxf_with_arc.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual199.0240.0120.0200.030.0 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__no_block_section__dxf.out b/share/extensions/tests/data/refs/dxf_input__no_block_section__dxf.out new file mode 100644 index 0000000..a75047b --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__no_block_section__dxf.out @@ -0,0 +1,2 @@ + + no_block_section.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manualF2 2.0~2.0 •¶ŽšŠÔ 1.0F3 4.0~4.0 •¶ŽšŠÔ 0.0F4 4.0~4.0 •¶ŽšŠÔ 2.0F5 6.0~6.0 •¶ŽšŠÔ 0.0F10 10~10 •¶ŽšŠÔ 5.0Pen.1 ŽÀüPen.2 “_üPen.3 “_ü(2)Pen.4 “_ü(3)Pen.5 ˆê“_½üPen.6 ˆê“_½ü(2)Pen.1 “ñ“_½üPen.1 “ñ“_½ü(2)F1 2.0~2.0 •¶ŽšŠÔ 0.0F6 6.0~6.0 •¶ŽšŠÔ 2.0F8 8.0~8.0 •¶ŽšŠÔ 4.0F7 8.0~8.0 •¶ŽšŠÔ 0.0F9 10~10 •¶ŽšŠÔ 0.0F10 10~10 •¶ŽšŠÔ 5.0F9 10~10 •¶ŽšŠÔ 0.0F7 8.0~8.0 •¶ŽšŠÔ 0.0F3 4.0~4.0 •¶ŽšŠÔ 0.0F2 2.0~2.0 •¶ŽšŠÔ 1.0F3 4.0~4.0 •¶ŽšŠÔ 0.0F2 2.0~2.0 •¶ŽšŠÔ 1.0F4 4.0~4.0 •¶ŽšŠÔ 2.0F2 2.0~2.0 •¶ŽšŠÔ 1.0F2 2.0~2.0 •¶ŽšŠÔ 1.0ƒÓ6,000R3,000ƒÓ6,000R3,0004,712.490ß3,0003,000F3 4.0~4.0 •¶ŽšŠÔ 0.04,400‘ȉ~”¼‘ȉ~6,000ƒÓ3,000ƒTƒCƒ“‹Èü2ŽŸ‹ÈüƒXƒvƒ‰ƒCƒ“‹ÈüƒxƒWƒF‹ÈüƒOƒ‹[ƒv0 ƒŒƒCƒ„0‚Ì•¶Žš—ñ1/100‚ÌŽlŠpŒ`7,5003,000ƒnƒbƒ`ƒ“ƒOŽè‘‚«ü˜A‘±‰~ŒÊ˜AüƒOƒ‹[ƒv0 ƒŒƒCƒ„0“_~5A3 1/100ƒOƒ‹[ƒv0 ƒŒƒCƒ„1 “Ç‚ÝŽæ‚è•s‰ÂƒŒƒCƒ„‚Ì•¶Žš—ñƒOƒ‹[ƒv0 ƒŒƒCƒ„2 ”ñ•\Ž¦ƒŒƒCƒ„‚Ì•¶Žš—ñ15,0006,0001/200‚ÌŽlŠpŒ`ƒOƒ‹[ƒv1 ƒŒƒCƒ„0 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__test2_r12__dxf.out b/share/extensions/tests/data/refs/dxf_input__test2_r12__dxf.out new file mode 100644 index 0000000..f368c37 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test2_r12__dxf.out @@ -0,0 +1,2 @@ + + test2_r12.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual500015005000150045‹∅4000R20002500250025002500250025002500250025002500250025002500250025002500250025002500250015005001638.2426524.29500015005000150024000<1000>700‚Qs‚̃}ƒ‹ƒ`ƒeƒLƒXƒg2s‚̃}ƒ‹ƒ`ƒeƒLƒXƒg2s‚̃}ƒ‹ƒ`ƒeƒLƒXƒg2s‚̃}ƒ‹ƒ`ƒeƒLƒXƒgƒXƒvƒ‰ƒCƒ“‹Èüƒ|ƒŠƒ‰ƒCƒ“ƒnƒbƒ`ƒ“ƒOANSI31“_(â‘Î’PˆÊ300)ƒOƒ‹[ƒv}Œ`ƒuƒƒbƒN}Œ`“h‚è‚‚Ԃµ–îˆó‹ó–îˆó•Â–îˆó•ŠÛ(‘¾)ƒeƒBƒbƒNƒeƒBƒbƒNŠJ–îˆó”’ŠÛ1”’ŠÛ2’¼Šp–îˆó30‹–îˆó¬•ŠÛ‹ó”’ŠÛ¬‹ó”’ŠÛŽlŠpŽlŠp“h‚è‚‚Ԃµƒf[ƒ^ƒ€‹ó”’ƒf[ƒ^ƒ€“h‚è‚‚Ԃµ”gŒ`‚È‚µŠOŒü‚«‚Ì–îˆó“àŒü‚«‚Ì–îˆóÀ•W¡–@ƒŠ[ƒWƒ‡ƒ“ã‘‚«¡–@’l‚ÌA3 1/100DOTByLayer(CONTINUOUS)CONTINUOUSDASHDOTDIVIDEHIDDENByLayer(White/Black)YellowƒpƒŒƒbƒg113CyanGreenRed‚l‚rƒSƒVƒbƒNã’†S•‚ðŠm”F‚l‚rƒSƒVƒbƒN‰E‰º‚l‚rƒSƒVƒbƒN‰º’†S‚l‚rƒSƒVƒbƒN¶‰º‚l‚rƒSƒVƒbƒN‰E’†‰›‚l‚rƒSƒVƒbƒN’†‰›‚l‚rƒSƒVƒbƒN¶’†‰›‚l‚rƒSƒVƒbƒN‰Eã‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg‚l‚rƒSƒVƒbƒN¶ã‚l‚rƒSƒVƒbƒN’†‰›‚l‚rƒSƒVƒbƒN‰EŠñ‚¹‚l‚rƒSƒVƒbƒNŽlŠpŒ`‚Æ’·‚³¡–@‚l‚rƒSƒVƒbƒN‰Eã‚l‚rƒSƒVƒbƒN¶’†‰›‚l‚rƒSƒVƒbƒN’†‰›‚l‚rƒSƒVƒbƒN‰E’†‰›‚l‚rƒSƒVƒbƒN¶‰º‚l‚rƒSƒVƒbƒN‰º’†S‚l‚rƒSƒVƒbƒN‰E‰º‚‚³‚ðŠm”F‚l‚rƒSƒVƒbƒN‚l‚rƒSƒVƒbƒN‰EŠñ‚¹‚l‚rƒSƒVƒbƒN’†‰›‚l‚rƒSƒVƒbƒN¶ã‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg‚l‚rƒSƒVƒbƒNã’†Stxt/bigfont‰Eãtxt/bigfont¶’†‰›txt/bigfont’†‰›txt/bigfont‰E’†‰›txt/bigfont¶‰ºtxt/bigfont‰º’†Stxt/bigfont‰E‰º‚‚³‚ðŠm”Ftxt/bigfont‰EŠñ‚¹txt/bigfont’†‰›txt/bigfont¶ãtxt/bigfontƒtƒBƒbƒgtxt/bigfontã’†Stxt/bigfonttxt/bigfont‰Eãtxt/bigfont¶‰ºtxt/bigfont‰E’†‰›txt/bigfont’†‰›txt/bigfont¶’†‰›txt/bigfontã’†Stxt/bigfontƒtƒBƒbƒgtxt/bigfont¶ãtxt/bigfont’†‰›txt/bigfont‰EŠñ‚¹txt/bigfonttxt/bigfont‰E‰ºtxt/bigfont‰º’†S•‚ðŠm”F•½s¡–@ŽlŠpŒ`‚Æ’·‚³¡–@•½s¡–@ŽlŠpŒ`‚Æ’·‚³¡–@ŽlŠpŒ`‚Æ’·‚³¡–@•½s¡–@•½s¡–@(ƒ|ƒŠƒ‰ƒCƒ“)‰_ƒ}[ƒN”ñ•\Ž¦‰æ‘w‚ɏ‘‚©‚ꂽ•¶ŽšƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš‰_ƒ}[ƒN”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶ŽšƒƒbƒN‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__test2_r13__dxf.out b/share/extensions/tests/data/refs/dxf_input__test2_r13__dxf.out new file mode 100644 index 0000000..34cdf88 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test2_r13__dxf.out @@ -0,0 +1,1599 @@ + + test2_r13.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual + + + + + + + + + + + + + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + 45‹ + + + + + + + + + + + + ∅4000 + + + + + + + + + + + R2000 + + + + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + + + 500 + + + + + + + + + + + 1638.24 + + + + + + + + + + + 26524.29 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + 24000 + + + + + + + + + + + + + + <1000> + + + + + + + + + + + 700 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ƒXƒvƒ‰ƒCƒ“‹Èü + + + + + + ƒ|ƒŠƒ‰ƒCƒ“ + + + + + ƒnƒbƒ`ƒ“ƒO + + + ANSI31 + + + + + + + + “_(â‘Î’PˆÊ300) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ƒOƒ‹[ƒv}Œ` + + + ƒuƒƒbƒN}Œ` + + + + + + + + + + + “h‚è‚‚Ԃµ + + + –îˆó + + + ‹ó–îˆó + + + + •Â–îˆó + + + + •ŠÛ + + + (‘¾) + + + + ƒeƒBƒbƒN + + + + ƒeƒBƒbƒN + + + + ŠJ–îˆó + + + + ”’ŠÛ1 + + + + ”’ŠÛ2 + + + + ’¼Šp–îˆó + + + + 30‹–îˆó + + + ¬•ŠÛ + + + + + ‹ó”’ŠÛ + + + + ¬‹ó”’ŠÛ + + + ŽlŠp + + + + ŽlŠp + + + + “h‚è‚‚Ԃµ + + + + ƒf[ƒ^ƒ€ + + + ‹ó”’ + + + ƒf[ƒ^ƒ€ + + + + “h‚è‚‚Ԃµ + + + + ”gŒ` + + + + ‚È‚µ + + + + + ŠOŒü‚«‚Ì–îˆó + + + “àŒü‚«‚Ì–îˆó + + + À•W¡–@ + + + + + + + ƒŠ[ƒWƒ‡ƒ“ + + + ã‘‚« + + + ¡–@’l‚Ì + + + + + + + A3 1/100 + + + DOT + + + + ByLayer(CONTINUOUS) + + + + CONTINUOUS + + + DASHDOT + + + + + DIVIDE + + + + + HIDDEN + + + + + ‚Qs‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + ByLayer(White/Black) + + + + + + + + + Yellow + + + ƒpƒŒƒbƒg113 + + + Cyan + + + Green + + + Red + + + ‚l‚rƒSƒVƒbƒNã’†S + + + + •‚ðŠm”F + + + + + + ‚l‚rƒSƒVƒbƒN‰E‰º + + + + + ‚l‚rƒSƒVƒbƒN‰º’†S + + + + + ‚l‚rƒSƒVƒbƒN¶‰º + + + + + ‚l‚rƒSƒVƒbƒN‰E’†‰› + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN¶’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰Eã + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + + + + + ‚l‚rƒSƒVƒbƒN¶ã + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + + + + + + ‚l‚rƒSƒVƒbƒN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + + ‚l‚rƒSƒVƒbƒN‰Eã + + + ‚l‚rƒSƒVƒbƒN¶’†‰› + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰E’†‰› + + + + + ‚l‚rƒSƒVƒbƒN¶‰º + + + + + ‚l‚rƒSƒVƒbƒN‰º’†S + + + + + ‚l‚rƒSƒVƒbƒN‰E‰º + + + + + + ‚‚³‚ðŠm”F + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ‚l‚rƒSƒVƒbƒN + + + + + + ‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + ‚l‚rƒSƒVƒbƒN¶ã + + + + + ‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + + + + + + + + + ‚l‚rƒSƒVƒbƒNã’†S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + txt/bigfont‰Eã + + + txt/bigfont¶’†‰› + + + + + + + txt/bigfont’†‰› + + + + + txt/bigfont‰E’†‰› + + + txt/bigfont¶‰º + + + + + txt/bigfont‰º’†S + + + + + txt/bigfont‰E‰º + + + + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + ‚‚³‚ðŠm”F + + + + + + + + + + + + + + + + + + + + + txt/bigfont‰EŠñ‚¹ + + + txt/bigfont’†‰› + + + + + + + txt/bigfont¶ã + + + txt/bigfontƒtƒBƒbƒg + + + + + + + + + txt/bigfontã’†S + + + txt/bigfont + + + + + + + + + + + + + + + + + + + txt/bigfont‰Eã + + + txt/bigfont¶‰º + + + txt/bigfont‰E’†‰› + + + txt/bigfont’†‰› + + + txt/bigfont¶’†‰› + + + txt/bigfontã’†S + + + txt/bigfontƒtƒBƒbƒg + + + txt/bigfont¶ã + + + + + txt/bigfont’†‰› + + + txt/bigfont‰EŠñ‚¹ + + + txt/bigfont + + + txt/bigfont‰E‰º + + + txt/bigfont‰º’†S + + + + •‚ðŠm”F + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + •½s¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + •½s¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + •½s¡–@ + + + •½s¡–@ + + + (ƒ|ƒŠƒ‰ƒCƒ“) + + + + ‰_ƒ}[ƒN + + + + + + + + + + + ”ñ•\Ž¦‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + + + ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + ‰_ƒ}[ƒN + + + + + ”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + + + ƒƒbƒN‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__test2_r14__dxf.out b/share/extensions/tests/data/refs/dxf_input__test2_r14__dxf.out new file mode 100644 index 0000000..00b4d29 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test2_r14__dxf.out @@ -0,0 +1,1587 @@ + + test2_r14.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual + + + + + + + + + + + + + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + 45‹ + + + + + + + + + + + + ∅4000 + + + + + + + + + + + R2000 + + + + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + 2500 + + + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + + + 500 + + + + + + + + + + + 1638.24 + + + + + + + + + + + 26524.29 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + + + 5000 + + + + + + + + + + + + + 1500 + + + + + + + + + + + 24000 + + + + + + + + + + + + + + <1000> + + + + + + + + + + + 700 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ƒXƒvƒ‰ƒCƒ“‹Èü + + + + + + ƒ|ƒŠƒ‰ƒCƒ“ + + + + + ƒnƒbƒ`ƒ“ƒO + + + ANSI31 + + + + + + + + “_(â‘Î’PˆÊ300) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ƒOƒ‹[ƒv}Œ` + + + ƒuƒƒbƒN}Œ` + + + + + + + + + + + “h‚è‚‚Ԃµ + + + –îˆó + + + ‹ó–îˆó + + + + •Â–îˆó + + + + •ŠÛ + + + (‘¾) + + + + ƒeƒBƒbƒN + + + + ƒeƒBƒbƒN + + + + ŠJ–îˆó + + + + ”’ŠÛ1 + + + + ”’ŠÛ2 + + + + ’¼Šp–îˆó + + + + 30‹–îˆó + + + ¬•ŠÛ + + + + + ‹ó”’ŠÛ + + + + ¬‹ó”’ŠÛ + + + ŽlŠp + + + + ŽlŠp + + + + “h‚è‚‚Ԃµ + + + + ƒf[ƒ^ƒ€ + + + ‹ó”’ + + + ƒf[ƒ^ƒ€ + + + + “h‚è‚‚Ԃµ + + + + ”gŒ` + + + + ‚È‚µ + + + + + ŠOŒü‚«‚Ì–îˆó + + + “àŒü‚«‚Ì–îˆó + + + À•W¡–@ + + + + + + + ƒŠ[ƒWƒ‡ƒ“ + + + ã‘‚« + + + ¡–@’l‚Ì + + + + + + + A3 1/100 + + + DOT + + + + ByLayer(CONTINUOUS) + + + + CONTINUOUS + + + DASHDOT + + + + + DIVIDE + + + + + HIDDEN + + + + + ‚Qs‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + ByLayer(White/Black) + + + + + + + + + Yellow + + + ƒpƒŒƒbƒg113 + + + Cyan + + + Green + + + Red + + + ‚l‚rƒSƒVƒbƒNã’†S + + + + •‚ðŠm”F + + + + + + ‚l‚rƒSƒVƒbƒN‰E‰º + + + + + ‚l‚rƒSƒVƒbƒN‰º’†S + + + + + ‚l‚rƒSƒVƒbƒN¶‰º + + + + + ‚l‚rƒSƒVƒbƒN‰E’†‰› + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN¶’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰Eã + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + + + + + ‚l‚rƒSƒVƒbƒN¶ã + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + + + + + + ‚l‚rƒSƒVƒbƒN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + + ‚l‚rƒSƒVƒbƒN‰Eã + + + ‚l‚rƒSƒVƒbƒN¶’†‰› + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + + + ‚l‚rƒSƒVƒbƒN‰E’†‰› + + + + + ‚l‚rƒSƒVƒbƒN¶‰º + + + + + ‚l‚rƒSƒVƒbƒN‰º’†S + + + + + ‚l‚rƒSƒVƒbƒN‰E‰º + + + + + + ‚‚³‚ðŠm”F + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ‚l‚rƒSƒVƒbƒN + + + + + + ‚l‚rƒSƒVƒbƒN‰EŠñ‚¹ + + + + + ‚l‚rƒSƒVƒbƒN’†‰› + + + ‚l‚rƒSƒVƒbƒN¶ã + + + + + ‚l‚rƒSƒVƒbƒNƒtƒBƒbƒg + + + + + + + + + ‚l‚rƒSƒVƒbƒNã’†S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + txt/bigfont‰Eã + + + txt/bigfont¶’†‰› + + + + + + + txt/bigfont’†‰› + + + + + txt/bigfont‰E’†‰› + + + txt/bigfont¶‰º + + + + + txt/bigfont‰º’†S + + + + + txt/bigfont‰E‰º + + + + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + ‚‚³‚ðŠm”F + + + + + + + + + + + + + + + + + + + + + txt/bigfont‰EŠñ‚¹ + + + txt/bigfont’†‰› + + + + + + + txt/bigfont¶ã + + + txt/bigfontƒtƒBƒbƒg + + + + + + + + + txt/bigfontã’†S + + + txt/bigfont + + + + + + + + + + + + + + + + + + + txt/bigfont‰Eã + + + txt/bigfont¶‰º + + + txt/bigfont‰E’†‰› + + + txt/bigfont’†‰› + + + txt/bigfont¶’†‰› + + + txt/bigfontã’†S + + + txt/bigfontƒtƒBƒbƒg + + + txt/bigfont¶ã + + + + + txt/bigfont’†‰› + + + txt/bigfont‰EŠñ‚¹ + + + txt/bigfont + + + txt/bigfont‰E‰º + + + txt/bigfont‰º’†S + + + + •‚ðŠm”F + + + + 2s‚Ì + ƒ}ƒ‹ƒ`ƒeƒLƒXƒg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + •½s¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + •½s¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + ŽlŠpŒ`‚Æ’·‚³¡–@ + + + •½s¡–@ + + + •½s¡–@ + + + (ƒ|ƒŠƒ‰ƒCƒ“) + + + + ‰_ƒ}[ƒN + + + + + + + + + + + ”ñ•\Ž¦‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + + + ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + ‰_ƒ}[ƒN + + + + + ”ñ•\Ž¦‚©‚ƒtƒŠ[ƒY‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + + + ƒƒbƒN‚³‚ꂽ‰æ‘w‚ɏ‘‚©‚ꂽ•¶Žš + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__test_extrude__dxf.out b/share/extensions/tests/data/refs/dxf_input__test_extrude__dxf.out new file mode 100644 index 0000000..6b1f4af --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test_extrude__dxf.out @@ -0,0 +1,2 @@ + + test_extrude.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manualWHviewing area71.3518.1recess73.3520.1back view1:1 for DXF exportfront viewinternal hole is the viewing area, the second outline (2mm inner) is the recess area to make the glass not fallL FUEL ROIL PRESS L VAC R VOLTS \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_input__test_r12__dxf.out b/share/extensions/tests/data/refs/dxf_input__test_r12__dxf.out new file mode 100644 index 0000000..1c5daa5 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test_r12__dxf.out @@ -0,0 +1,2 @@ + + test_r12.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual diff --git a/share/extensions/tests/data/refs/dxf_input__test_r14__dxf.out b/share/extensions/tests/data/refs/dxf_input__test_r14__dxf.out new file mode 100644 index 0000000..18f2826 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_input__test_r14__dxf.out @@ -0,0 +1,2 @@ + + test_r14.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual \ No newline at end of file diff --git a/share/extensions/tests/data/refs/dxf_outlines.out b/share/extensions/tests/data/refs/dxf_outlines.out new file mode 100644 index 0000000..3e58fcb --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_outlines.out @@ -0,0 +1,3416 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 9 +$INSUNITS + 70 + 0 + 9 +$MEASUREMENT + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +210.0 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +341.0 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +4 + 0 +LAYER + 5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +51 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide3 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +52 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide2 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +53 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide1 + 70 +0 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +100 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +646.073390 + 31 +0.0 + 0 +LINE + 5 +101 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +102 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +103 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +646.073390 + 31 +0.0 + 0 +SPLINE + 5 +104 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 10 +129.776888 + 20 +600.000000 + 30 +0.0 + 10 +111.545073 + 20 +587.817891 + 30 +0.0 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +105 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 10 +96.066973 + 20 +550.450452 + 30 +0.0 + 10 +100.344761 + 20 +528.944561 + 30 +0.0 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +106 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 10 +128.944561 + 20 +500.344761 + 30 +0.0 + 10 +150.450452 + 20 +496.066973 + 30 +0.0 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +107 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 10 +187.817891 + 20 +511.545073 + 30 +0.0 + 10 +200.000000 + 20 +529.776888 + 30 +0.0 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +108 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 10 +200.000000 + 20 +563.260824 + 30 +0.0 + 10 +194.732158 + 20 +575.978520 + 30 +0.0 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +109 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 10 +175.978520 + 20 +594.732158 + 30 +0.0 + 10 +163.260824 + 20 +600.000000 + 30 +0.0 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 0 +LINE + 5 +10a +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 11 +150.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +10b +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 10 +359.553776 + 20 +600.000000 + 30 +0.0 + 10 +323.090147 + 20 +587.817891 + 30 +0.0 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +10c +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 10 +292.133947 + 20 +550.450452 + 30 +0.0 + 10 +300.689522 + 20 +528.944561 + 30 +0.0 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +10d +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 10 +357.889121 + 20 +500.344761 + 30 +0.0 + 10 +400.900904 + 20 +496.066973 + 30 +0.0 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +10e +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 10 +475.635782 + 20 +511.545073 + 30 +0.0 + 10 +500.000000 + 20 +529.776888 + 30 +0.0 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +10f +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 10 +500.000000 + 20 +563.260824 + 30 +0.0 + 10 +489.464316 + 20 +575.978520 + 30 +0.0 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +110 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 10 +451.957040 + 20 +594.732158 + 30 +0.0 + 10 +426.521649 + 20 +600.000000 + 30 +0.0 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 0 +LINE + 5 +111 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbLine + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 11 +400.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +112 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +783.086350 + 20 +522.176190 + 30 +0.0 + 10 +758.815382 + 20 +504.056941 + 30 +0.0 + 10 +713.857171 + 20 +495.892961 + 30 +0.0 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 0 +SPLINE + 5 +113 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 10 +630.118574 + 20 +508.110580 + 30 +0.0 + 10 +600.997311 + 20 +527.082892 + 30 +0.0 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 0 +SPLINE + 5 +114 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 10 +599.052409 + 20 +570.687512 + 30 +0.0 + 10 +626.453123 + 20 +590.290091 + 30 +0.0 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 0 +SPLINE + 5 +115 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 10 +709.019129 + 20 +604.362128 + 30 +0.0 + 10 +754.660551 + 20 +597.208402 + 30 +0.0 + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 0 +LINE + 5 +116 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 11 +700.000000 + 21 +550.000000 + 31 +0.0 + 0 +LINE + 5 +117 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +700.000000 + 20 +550.000000 + 30 +0.0 + 11 +783.086350 + 21 +522.176190 + 31 +0.0 + 0 +LINE + 5 +118 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +400.000000 + 30 +0.0 + 11 +200.000000 + 21 +300.000000 + 31 +0.0 + 0 +LINE + 5 +119 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +300.000000 + 30 +0.0 + 11 +300.000000 + 21 +400.000000 + 31 +0.0 + 0 +LINE + 5 +11a +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +300.000000 + 20 +400.000000 + 30 +0.0 + 11 +400.000000 + 21 +300.000000 + 31 +0.0 + 0 +SPLINE + 5 +11b +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 0 +SPLINE + 5 +11c +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 10 +700.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +400.000000 + 30 +0.0 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 0 +SPLINE + 5 +11d +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 0 +LINE + 5 +11e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +244.833200 + 20 +110.859950 + 30 +0.0 + 11 +199.494330 + 21 +118.994410 + 31 +0.0 + 0 +LINE + 5 +11f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +199.494330 + 20 +118.994410 + 30 +0.0 + 11 +167.090050 + 21 +86.256880 + 31 +0.0 + 0 +LINE + 5 +120 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +167.090050 + 20 +86.256880 + 30 +0.0 + 11 +160.815900 + 21 +131.890400 + 31 +0.0 + 0 +LINE + 5 +121 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +160.815900 + 20 +131.890400 + 30 +0.0 + 11 +119.667180 + 21 +152.592240 + 31 +0.0 + 0 +LINE + 5 +122 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +119.667180 + 20 +152.592240 + 30 +0.0 + 11 +161.128420 + 21 +172.660850 + 31 +0.0 + 0 +LINE + 5 +123 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +161.128420 + 20 +172.660850 + 30 +0.0 + 11 +168.101390 + 21 +218.192820 + 31 +0.0 + 0 +LINE + 5 +124 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +168.101390 + 20 +218.192820 + 30 +0.0 + 11 +200.000000 + 21 +184.962380 + 31 +0.0 + 0 +LINE + 5 +125 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +200.000000 + 20 +184.962380 + 30 +0.0 + 11 +245.458240 + 21 +192.400850 + 31 +0.0 + 0 +LINE + 5 +126 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +245.458240 + 20 +192.400850 + 30 +0.0 + 11 +223.711430 + 21 +151.794700 + 31 +0.0 + 0 +LINE + 5 +127 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +223.711430 + 20 +151.794700 + 30 +0.0 + 11 +244.833200 + 21 +110.859950 + 31 +0.0 + 0 +LINE + 5 +128 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +444.833200 + 20 +107.863730 + 30 +0.0 + 11 +399.494330 + 21 +115.998190 + 31 +0.0 + 0 +LINE + 5 +129 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +399.494330 + 20 +115.998190 + 30 +0.0 + 11 +367.090050 + 21 +83.260660 + 31 +0.0 + 0 +LINE + 5 +12a +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +367.090050 + 20 +83.260660 + 30 +0.0 + 11 +360.815900 + 21 +128.894180 + 31 +0.0 + 0 +LINE + 5 +12b +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +360.815900 + 20 +128.894180 + 30 +0.0 + 11 +319.667180 + 21 +149.596020 + 31 +0.0 + 0 +LINE + 5 +12c +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +319.667180 + 20 +149.596020 + 30 +0.0 + 11 +361.128420 + 21 +169.664630 + 31 +0.0 + 0 +LINE + 5 +12d +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +361.128420 + 20 +169.664630 + 30 +0.0 + 11 +368.101390 + 21 +215.196600 + 31 +0.0 + 0 +LINE + 5 +12e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +368.101390 + 20 +215.196600 + 30 +0.0 + 11 +400.000000 + 21 +181.966160 + 31 +0.0 + 0 +LINE + 5 +12f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +400.000000 + 20 +181.966160 + 30 +0.0 + 11 +445.458240 + 21 +189.404630 + 31 +0.0 + 0 +LINE + 5 +130 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +445.458240 + 20 +189.404630 + 30 +0.0 + 11 +423.711430 + 21 +148.798480 + 31 +0.0 + 0 +LINE + 5 +131 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +423.711430 + 20 +148.798480 + 30 +0.0 + 11 +444.833200 + 21 +107.863730 + 31 +0.0 + 0 +LINE + 5 +132 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +133 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +134 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +135 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +136 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +137 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +138 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +139 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +13a +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +755.056774 + 21 +800.000000 + 31 +0.0 + 0 +SPLINE + 5 +13b +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +755.056774 + 20 +800.000000 + 30 +0.0 + 10 +766.976459 + 20 +800.000000 + 30 +0.0 + 10 +778.407944 + 20 +795.896267 + 30 +0.0 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +13c +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 10 +795.264924 + 20 +781.286884 + 30 +0.0 + 10 +800.000000 + 20 +771.379596 + 30 +0.0 + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 0 +LINE + 5 +13d +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 11 +800.000000 + 21 +738.950798 + 31 +0.0 + 0 +SPLINE + 5 +13e +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +800.000000 + 20 +738.950798 + 30 +0.0 + 10 +800.000000 + 20 +728.620404 + 30 +0.0 + 10 +795.264924 + 20 +718.713116 + 30 +0.0 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +13f +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 10 +778.407944 + 20 +704.103733 + 30 +0.0 + 10 +766.976459 + 20 +700.000000 + 30 +0.0 + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 0 +LINE + 5 +140 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 11 +644.943226 + 21 +700.000000 + 31 +0.0 + 0 +SPLINE + 5 +141 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +644.943226 + 20 +700.000000 + 30 +0.0 + 10 +633.023541 + 20 +700.000000 + 30 +0.0 + 10 +621.592056 + 20 +704.103733 + 30 +0.0 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +142 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 10 +604.735076 + 20 +718.713116 + 30 +0.0 + 10 +600.000000 + 20 +728.620404 + 30 +0.0 + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 0 +LINE + 5 +143 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 11 +600.000000 + 21 +761.049202 + 31 +0.0 + 0 +SPLINE + 5 +144 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +761.049202 + 30 +0.0 + 10 +600.000000 + 20 +771.379596 + 30 +0.0 + 10 +604.735076 + 20 +781.286884 + 30 +0.0 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +145 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 10 +621.592056 + 20 +795.896267 + 30 +0.0 + 10 +633.023541 + 20 +800.000000 + 30 +0.0 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 0 +LINE + 5 +146 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +644.943226 + 21 +800.000000 + 31 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/refs/dxf_outlines__--POLY__true.out b/share/extensions/tests/data/refs/dxf_outlines__--POLY__true.out new file mode 100644 index 0000000..e17129a --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_outlines__--POLY__true.out @@ -0,0 +1,2884 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 9 +$INSUNITS + 70 + 0 + 9 +$MEASUREMENT + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +210.0 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +341.0 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +4 + 0 +LAYER + 5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +51 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide3 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +52 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide2 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +53 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide1 + 70 +0 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +SPLINE + 5 +100 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 10 +129.776888 + 20 +600.000000 + 30 +0.0 + 10 +111.545073 + 20 +587.817891 + 30 +0.0 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +101 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 10 +96.066973 + 20 +550.450452 + 30 +0.0 + 10 +100.344761 + 20 +528.944561 + 30 +0.0 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +102 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 10 +128.944561 + 20 +500.344761 + 30 +0.0 + 10 +150.450452 + 20 +496.066973 + 30 +0.0 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +103 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 10 +187.817891 + 20 +511.545073 + 30 +0.0 + 10 +200.000000 + 20 +529.776888 + 30 +0.0 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +104 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 10 +200.000000 + 20 +563.260824 + 30 +0.0 + 10 +194.732158 + 20 +575.978520 + 30 +0.0 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +105 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 10 +175.978520 + 20 +594.732158 + 30 +0.0 + 10 +163.260824 + 20 +600.000000 + 30 +0.0 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +106 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +651.308900 + 20 +646.073390 + 30 +0.0 + 10 +900.000020 + 20 +646.073390 + 30 +0.0 + 10 +900.000020 + 20 +444.575280 + 30 +0.0 + 10 +651.308900 + 20 +444.575280 + 30 +0.0 + 0 +SPLINE + 5 +107 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 10 +359.553776 + 20 +600.000000 + 30 +0.0 + 10 +323.090147 + 20 +587.817891 + 30 +0.0 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +108 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 10 +292.133947 + 20 +550.450452 + 30 +0.0 + 10 +300.689522 + 20 +528.944561 + 30 +0.0 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +109 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 10 +357.889121 + 20 +500.344761 + 30 +0.0 + 10 +400.900904 + 20 +496.066973 + 30 +0.0 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +10a +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 10 +475.635782 + 20 +511.545073 + 30 +0.0 + 10 +500.000000 + 20 +529.776888 + 30 +0.0 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +10b +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 10 +500.000000 + 20 +563.260824 + 30 +0.0 + 10 +489.464316 + 20 +575.978520 + 30 +0.0 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +10c +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 10 +451.957040 + 20 +594.732158 + 30 +0.0 + 10 +426.521649 + 20 +600.000000 + 30 +0.0 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +10d +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbPolyline + 90 +1 + 70 +1 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 0 +SPLINE + 5 +10e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +783.086350 + 20 +522.176190 + 30 +0.0 + 10 +758.815382 + 20 +504.056941 + 30 +0.0 + 10 +713.857171 + 20 +495.892961 + 30 +0.0 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 0 +SPLINE + 5 +10f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 10 +630.118574 + 20 +508.110580 + 30 +0.0 + 10 +600.997311 + 20 +527.082892 + 30 +0.0 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 0 +SPLINE + 5 +110 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 10 +599.052409 + 20 +570.687512 + 30 +0.0 + 10 +626.453123 + 20 +590.290091 + 30 +0.0 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 0 +SPLINE + 5 +111 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 10 +709.019129 + 20 +604.362128 + 30 +0.0 + 10 +754.660551 + 20 +597.208402 + 30 +0.0 + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 0 +LWPOLYLINE + 5 +112 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbPolyline + 90 +1 + 70 +1 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +113 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbPolyline + 90 +3 + 70 +0 + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 10 +700.000000 + 20 +550.000000 + 30 +0.0 + 10 +783.086350 + 20 +522.176190 + 30 +0.0 + 0 +SPLINE + 5 +114 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 0 +SPLINE + 5 +115 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 10 +700.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +400.000000 + 30 +0.0 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 0 +SPLINE + 5 +116 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +117 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbPolyline + 90 +4 + 70 +0 + 10 +100.000000 + 20 +400.000000 + 30 +0.0 + 10 +200.000000 + 20 +300.000000 + 30 +0.0 + 10 +300.000000 + 20 +400.000000 + 30 +0.0 + 10 +400.000000 + 20 +300.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +118 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbPolyline + 90 +10 + 70 +1 + 10 +244.833200 + 20 +110.859950 + 30 +0.0 + 10 +199.494330 + 20 +118.994410 + 30 +0.0 + 10 +167.090050 + 20 +86.256880 + 30 +0.0 + 10 +160.815900 + 20 +131.890400 + 30 +0.0 + 10 +119.667180 + 20 +152.592240 + 30 +0.0 + 10 +161.128420 + 20 +172.660850 + 30 +0.0 + 10 +168.101390 + 20 +218.192820 + 30 +0.0 + 10 +200.000000 + 20 +184.962380 + 30 +0.0 + 10 +245.458240 + 20 +192.400850 + 30 +0.0 + 10 +223.711430 + 20 +151.794700 + 30 +0.0 + 0 +LWPOLYLINE + 5 +119 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbPolyline + 90 +10 + 70 +1 + 10 +444.833200 + 20 +107.863730 + 30 +0.0 + 10 +399.494330 + 20 +115.998190 + 30 +0.0 + 10 +367.090050 + 20 +83.260660 + 30 +0.0 + 10 +360.815900 + 20 +128.894180 + 30 +0.0 + 10 +319.667180 + 20 +149.596020 + 30 +0.0 + 10 +361.128420 + 20 +169.664630 + 30 +0.0 + 10 +368.101390 + 20 +215.196600 + 30 +0.0 + 10 +400.000000 + 20 +181.966160 + 30 +0.0 + 10 +445.458240 + 20 +189.404630 + 30 +0.0 + 10 +423.711430 + 20 +148.798480 + 30 +0.0 + 0 +LWPOLYLINE + 5 +11a +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +100.000000 + 20 +800.000000 + 30 +0.0 + 10 +200.000000 + 20 +800.000000 + 30 +0.0 + 10 +200.000000 + 20 +700.000000 + 30 +0.0 + 10 +100.000000 + 20 +700.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +11b +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbPolyline + 90 +4 + 70 +1 + 10 +300.000000 + 20 +800.000000 + 30 +0.0 + 10 +500.000000 + 20 +800.000000 + 30 +0.0 + 10 +500.000000 + 20 +700.000000 + 30 +0.0 + 10 +300.000000 + 20 +700.000000 + 30 +0.0 + 0 +SPLINE + 5 +11c +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +755.056774 + 20 +800.000000 + 30 +0.0 + 10 +766.976459 + 20 +800.000000 + 30 +0.0 + 10 +778.407944 + 20 +795.896267 + 30 +0.0 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +11d +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 10 +795.264924 + 20 +781.286884 + 30 +0.0 + 10 +800.000000 + 20 +771.379596 + 30 +0.0 + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 0 +LWPOLYLINE + 5 +11e +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 10 +755.056774 + 20 +800.000000 + 30 +0.0 + 0 +SPLINE + 5 +11f +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +800.000000 + 20 +738.950798 + 30 +0.0 + 10 +800.000000 + 20 +728.620404 + 30 +0.0 + 10 +795.264924 + 20 +718.713116 + 30 +0.0 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +120 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 10 +778.407944 + 20 +704.103733 + 30 +0.0 + 10 +766.976459 + 20 +700.000000 + 30 +0.0 + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +121 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 10 +800.000000 + 20 +738.950798 + 30 +0.0 + 0 +SPLINE + 5 +122 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +644.943226 + 20 +700.000000 + 30 +0.0 + 10 +633.023541 + 20 +700.000000 + 30 +0.0 + 10 +621.592056 + 20 +704.103733 + 30 +0.0 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +123 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 10 +604.735076 + 20 +718.713116 + 30 +0.0 + 10 +600.000000 + 20 +728.620404 + 30 +0.0 + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 0 +LWPOLYLINE + 5 +124 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 10 +644.943226 + 20 +700.000000 + 30 +0.0 + 0 +SPLINE + 5 +125 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +761.049202 + 30 +0.0 + 10 +600.000000 + 20 +771.379596 + 30 +0.0 + 10 +604.735076 + 20 +781.286884 + 30 +0.0 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +126 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 10 +621.592056 + 20 +795.896267 + 30 +0.0 + 10 +633.023541 + 20 +800.000000 + 30 +0.0 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 0 +LWPOLYLINE + 5 +127 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbPolyline + 90 +2 + 70 +0 + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 10 +600.000000 + 20 +761.049202 + 30 +0.0 + 0 +LWPOLYLINE + 5 +128 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbPolyline + 90 +1 + 70 +1 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/refs/dxf_outlines__--ROBO__true.out b/share/extensions/tests/data/refs/dxf_outlines__--ROBO__true.out new file mode 100644 index 0000000..03d88a7 --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_outlines__--ROBO__true.out @@ -0,0 +1,3356 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 9 +$INSUNITS + 70 + 0 + 9 +$MEASUREMENT + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +210.0 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +341.0 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +4 + 0 +LAYER + 5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +51 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide3 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +52 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide2 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +53 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide1 + 70 +0 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +100 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +646.073390 + 31 +0.0 + 0 +LINE + 5 +101 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +102 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +103 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +646.073390 + 31 +0.0 + 0 +LINE + 5 +104 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 11 +150.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +105 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +25 + 73 +21 + 74 +19 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +19.625871 + 40 +38.902259 + 40 +58.528130 + 40 +78.154001 + 40 +97.430389 + 40 +117.056260 + 40 +136.682131 + 40 +155.958519 + 40 +175.584390 + 40 +195.210261 + 40 +214.486648 + 40 +234.112520 + 40 +247.201264 + 40 +260.181694 + 40 +273.270438 + 40 +286.359182 + 40 +299.339612 + 40 +312.428356 + 40 +312.428356 + 40 +312.428356 + 40 +312.428356 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 10 +143.415803 + 20 +599.240243 + 30 +0.0 + 10 +130.364655 + 20 +597.734258 + 30 +0.0 + 10 +113.732919 + 20 +586.181639 + 30 +0.0 + 10 +102.588798 + 20 +569.663707 + 30 +0.0 + 10 +98.704676 + 20 +549.987422 + 30 +0.0 + 10 +102.607034 + 20 +530.377407 + 30 +0.0 + 10 +113.713034 + 20 +513.712559 + 30 +0.0 + 10 +130.375615 + 20 +502.607128 + 30 +0.0 + 10 +149.994036 + 20 +498.704763 + 30 +0.0 + 10 +169.638507 + 20 +502.588345 + 30 +0.0 + 10 +186.274926 + 20 +513.734630 + 30 +0.0 + 10 +197.390407 + 20 +530.358342 + 30 +0.0 + 10 +200.872204 + 20 +547.827549 + 30 +0.0 + 10 +198.848182 + 20 +563.087937 + 30 +0.0 + 10 +193.798235 + 20 +575.283599 + 30 +0.0 + 10 +185.763691 + 20 +585.774690 + 30 +0.0 + 10 +175.285793 + 20 +593.756616 + 30 +0.0 + 10 +163.090031 + 20 +599.002808 + 30 +0.0 + 10 +154.375413 + 20 +599.666683 + 30 +0.0 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 11 +150.000000 + 21 +600.000000 + 31 +0.0 + 11 +130.755523 + 21 +596.149686 + 31 +0.0 + 11 +114.727792 + 21 +585.440299 + 31 +0.0 + 11 +103.806023 + 21 +569.134172 + 31 +0.0 + 11 +99.998707 + 21 +549.881142 + 31 +0.0 + 11 +103.759344 + 21 +530.975144 + 31 +0.0 + 11 +114.644661 + 21 +514.644661 + 31 +0.0 + 11 +130.975144 + 21 +503.759344 + 31 +0.0 + 11 +149.881142 + 21 +499.998707 + 31 +0.0 + 11 +169.134172 + 21 +503.806023 + 31 +0.0 + 11 +185.440299 + 21 +514.727792 + 31 +0.0 + 11 +196.149686 + 21 +530.755523 + 31 +0.0 + 11 +200.000000 + 21 +550.000000 + 31 +0.0 + 11 +198.286974 + 21 +562.976161 + 31 +0.0 + 11 +193.319578 + 21 +574.968515 + 31 +0.0 + 11 +185.355339 + 21 +585.355339 + 31 +0.0 + 11 +174.968515 + 21 +593.319578 + 31 +0.0 + 11 +162.976161 + 21 +598.286974 + 31 +0.0 + 11 +150.000000 + 21 +600.000000 + 31 +0.0 + 0 +LINE + 5 +106 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbLine + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 11 +400.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +107 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +25 + 73 +21 + 74 +19 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +38.681062 + 40 +72.478155 + 40 +99.736731 + 40 +120.440880 + 40 +140.788024 + 40 +168.002822 + 40 +202.429975 + 40 +240.428519 + 40 +279.122346 + 40 +313.514848 + 40 +340.266521 + 40 +360.994512 + 40 +374.415339 + 40 +389.988284 + 40 +409.004133 + 40 +431.252135 + 40 +455.745832 + 40 +481.754628 + 40 +481.754628 + 40 +481.754628 + 40 +481.754628 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 10 +387.073337 + 20 +599.315580 + 30 +0.0 + 10 +362.852163 + 20 +598.033158 + 30 +0.0 + 10 +330.927645 + 20 +587.586280 + 30 +0.0 + 10 +307.470550 + 20 +572.636967 + 30 +0.0 + 10 +296.788018 + 20 +549.986036 + 30 +0.0 + 10 +307.459014 + 20 +527.437782 + 30 +0.0 + 10 +330.948722 + 20 +512.309458 + 30 +0.0 + 10 +362.870076 + 20 +502.253513 + 30 +0.0 + 10 +399.992371 + 20 +498.816530 + 30 +0.0 + 10 +437.116010 + 20 +502.228915 + 30 +0.0 + 10 +469.091414 + 20 +512.338030 + 30 +0.0 + 10 +492.528217 + 20 +527.467585 + 30 +0.0 + 10 +502.069938 + 20 +547.508756 + 30 +0.0 + 10 +497.155568 + 20 +564.213453 + 30 +0.0 + 10 +486.271731 + 20 +576.368675 + 30 +0.0 + 10 +470.038165 + 20 +586.474801 + 30 +0.0 + 10 +449.375875 + 20 +594.079369 + 30 +0.0 + 10 +425.523641 + 20 +599.057033 + 30 +0.0 + 10 +408.676356 + 20 +599.679453 + 30 +0.0 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 11 +400.000000 + 21 +600.000000 + 31 +0.0 + 11 +361.511046 + 21 +596.149686 + 31 +0.0 + 11 +329.455585 + 21 +585.440299 + 31 +0.0 + 11 +307.612047 + 21 +569.134172 + 31 +0.0 + 11 +299.997414 + 21 +549.881142 + 31 +0.0 + 11 +307.518688 + 21 +530.975144 + 31 +0.0 + 11 +329.289322 + 21 +514.644661 + 31 +0.0 + 11 +361.950289 + 21 +503.759344 + 31 +0.0 + 11 +399.762283 + 21 +499.998707 + 31 +0.0 + 11 +438.268343 + 21 +503.806023 + 31 +0.0 + 11 +470.880597 + 21 +514.727792 + 31 +0.0 + 11 +492.299372 + 21 +530.755523 + 31 +0.0 + 11 +500.000000 + 21 +550.000000 + 31 +0.0 + 11 +496.573947 + 21 +562.976161 + 31 +0.0 + 11 +486.639156 + 21 +574.968515 + 31 +0.0 + 11 +470.710678 + 21 +585.355339 + 31 +0.0 + 11 +449.937030 + 21 +593.319578 + 31 +0.0 + 11 +425.952323 + 21 +598.286974 + 31 +0.0 + 11 +400.000000 + 21 +600.000000 + 31 +0.0 + 0 +LINE + 5 +108 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 11 +700.000000 + 21 +550.000000 + 31 +0.0 + 0 +LINE + 5 +109 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +700.000000 + 20 +550.000000 + 30 +0.0 + 11 +783.086350 + 21 +522.176190 + 31 +0.0 + 0 +LINE + 5 +10a +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +400.000000 + 30 +0.0 + 11 +200.000000 + 21 +300.000000 + 31 +0.0 + 0 +LINE + 5 +10b +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +300.000000 + 30 +0.0 + 11 +300.000000 + 21 +400.000000 + 31 +0.0 + 0 +LINE + 5 +10c +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +300.000000 + 20 +400.000000 + 30 +0.0 + 11 +400.000000 + 21 +300.000000 + 31 +0.0 + 0 +SPLINE + 5 +10d +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +19 + 73 +15 + 74 +13 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +33.639343 + 40 +73.067796 + 40 +115.113299 + 40 +153.495204 + 40 +183.486047 + 40 +206.190190 + 40 +228.349920 + 40 +257.421273 + 40 +295.131997 + 40 +337.045270 + 40 +376.909657 + 40 +411.417058 + 40 +411.417058 + 40 +411.417058 + 40 +411.417058 + 10 +783.086350 + 20 +522.176190 + 30 +0.0 + 10 +773.208657 + 20 +516.704376 + 30 +0.0 + 10 +751.753383 + 20 +504.819083 + 30 +0.0 + 10 +713.098133 + 20 +499.284438 + 30 +0.0 + 10 +673.034160 + 20 +500.308125 + 30 +0.0 + 10 +637.020737 + 20 +509.602032 + 30 +0.0 + 10 +610.081625 + 20 +524.532153 + 30 +0.0 + 10 +596.200782 + 20 +548.517250 + 30 +0.0 + 10 +607.747415 + 20 +573.452917 + 30 +0.0 + 10 +633.750925 + 20 +589.052463 + 30 +0.0 + 10 +668.898119 + 20 +599.080963 + 30 +0.0 + 10 +708.852777 + 20 +600.958962 + 30 +0.0 + 10 +747.953217 + 20 +596.188820 + 30 +0.0 + 10 +770.200515 + 20 +584.890454 + 30 +0.0 + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 11 +783.086350 + 21 +522.176190 + 31 +0.0 + 11 +752.800233 + 21 +507.535272 + 31 +0.0 + 11 +714.006209 + 21 +500.490649 + 31 +0.0 + 11 +671.987870 + 21 +502.001770 + 31 +0.0 + 11 +634.938317 + 21 +512.026803 + 31 +0.0 + 11 +609.809849 + 21 +528.397835 + 31 +0.0 + 11 +600.024860 + 21 +548.885200 + 31 +0.0 + 11 +607.973432 + 21 +569.570311 + 31 +0.0 + 11 +631.617253 + 21 +586.485194 + 31 +0.0 + 11 +667.736130 + 21 +597.326110 + 31 +0.0 + 11 +709.577957 + 21 +599.772334 + 31 +0.0 + 11 +748.961517 + 21 +593.599450 + 31 +0.0 + 11 +780.522930 + 21 +579.648180 + 31 +0.0 + 0 +LINE + 5 +10e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +244.833200 + 20 +110.859950 + 30 +0.0 + 11 +199.494330 + 21 +118.994410 + 31 +0.0 + 0 +LINE + 5 +10f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +199.494330 + 20 +118.994410 + 30 +0.0 + 11 +167.090050 + 21 +86.256880 + 31 +0.0 + 0 +LINE + 5 +110 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +167.090050 + 20 +86.256880 + 30 +0.0 + 11 +160.815900 + 21 +131.890400 + 31 +0.0 + 0 +LINE + 5 +111 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +160.815900 + 20 +131.890400 + 30 +0.0 + 11 +119.667180 + 21 +152.592240 + 31 +0.0 + 0 +LINE + 5 +112 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +119.667180 + 20 +152.592240 + 30 +0.0 + 11 +161.128420 + 21 +172.660850 + 31 +0.0 + 0 +LINE + 5 +113 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +161.128420 + 20 +172.660850 + 30 +0.0 + 11 +168.101390 + 21 +218.192820 + 31 +0.0 + 0 +LINE + 5 +114 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +168.101390 + 20 +218.192820 + 30 +0.0 + 11 +200.000000 + 21 +184.962380 + 31 +0.0 + 0 +LINE + 5 +115 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +200.000000 + 20 +184.962380 + 30 +0.0 + 11 +245.458240 + 21 +192.400850 + 31 +0.0 + 0 +LINE + 5 +116 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +245.458240 + 20 +192.400850 + 30 +0.0 + 11 +223.711430 + 21 +151.794700 + 31 +0.0 + 0 +LINE + 5 +117 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +223.711430 + 20 +151.794700 + 30 +0.0 + 11 +244.833200 + 21 +110.859950 + 31 +0.0 + 0 +LINE + 5 +118 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +444.833200 + 20 +107.863730 + 30 +0.0 + 11 +399.494330 + 21 +115.998190 + 31 +0.0 + 0 +LINE + 5 +119 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +399.494330 + 20 +115.998190 + 30 +0.0 + 11 +367.090050 + 21 +83.260660 + 31 +0.0 + 0 +LINE + 5 +11a +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +367.090050 + 20 +83.260660 + 30 +0.0 + 11 +360.815900 + 21 +128.894180 + 31 +0.0 + 0 +LINE + 5 +11b +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +360.815900 + 20 +128.894180 + 30 +0.0 + 11 +319.667180 + 21 +149.596020 + 31 +0.0 + 0 +LINE + 5 +11c +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +319.667180 + 20 +149.596020 + 30 +0.0 + 11 +361.128420 + 21 +169.664630 + 31 +0.0 + 0 +LINE + 5 +11d +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +361.128420 + 20 +169.664630 + 30 +0.0 + 11 +368.101390 + 21 +215.196600 + 31 +0.0 + 0 +LINE + 5 +11e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +368.101390 + 20 +215.196600 + 30 +0.0 + 11 +400.000000 + 21 +181.966160 + 31 +0.0 + 0 +LINE + 5 +11f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +400.000000 + 20 +181.966160 + 30 +0.0 + 11 +445.458240 + 21 +189.404630 + 31 +0.0 + 0 +LINE + 5 +120 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +445.458240 + 20 +189.404630 + 30 +0.0 + 11 +423.711430 + 21 +148.798480 + 31 +0.0 + 0 +LINE + 5 +121 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +423.711430 + 20 +148.798480 + 30 +0.0 + 11 +444.833200 + 21 +107.863730 + 31 +0.0 + 0 +LINE + 5 +122 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +123 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +124 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +125 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +126 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +127 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +128 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +129 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +12a +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +755.056774 + 21 +800.000000 + 31 +0.0 + 0 +SPLINE + 5 +12b +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +16 + 73 +12 + 74 +10 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +26.189140 + 40 +80.873670 + 40 +155.867954 + 40 +210.552484 + 40 +258.842872 + 40 +313.527402 + 40 +388.521686 + 40 +443.206216 + 40 +469.395356 + 40 +469.395356 + 40 +469.395356 + 40 +469.395356 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.864870 + 20 +391.309405 + 30 +0.0 + 10 +503.535641 + 20 +364.472314 + 30 +0.0 + 10 +529.067042 + 20 +315.429903 + 30 +0.0 + 10 +590.361152 + 20 +290.246834 + 30 +0.0 + 10 +661.374661 + 20 +317.343613 + 30 +0.0 + 10 +638.625339 + 20 +382.656387 + 30 +0.0 + 10 +709.638848 + 20 +409.753166 + 30 +0.0 + 10 +770.932958 + 20 +384.570097 + 30 +0.0 + 10 +796.464359 + 20 +335.527686 + 30 +0.0 + 10 +799.135130 + 20 +308.690595 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 11 +500.000000 + 21 +400.000000 + 31 +0.0 + 11 +503.703704 + 21 +374.074074 + 31 +0.0 + 11 +529.629630 + 21 +325.925926 + 31 +0.0 + 11 +600.000000 + 21 +300.000000 + 31 +0.0 + 11 +648.148148 + 21 +325.925926 + 31 +0.0 + 11 +651.851852 + 21 +374.074074 + 31 +0.0 + 11 +700.000000 + 21 +400.000000 + 31 +0.0 + 11 +770.370370 + 21 +374.074074 + 31 +0.0 + 11 +796.296296 + 21 +325.925926 + 31 +0.0 + 11 +800.000000 + 21 +300.000000 + 31 +0.0 + 0 +LINE + 5 +12c +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 11 +800.000000 + 21 +738.950798 + 31 +0.0 + 0 +SPLINE + 5 +12d +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +13 + 73 +9 + 74 +7 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +11.739902 + 40 +23.192940 + 40 +34.402773 + 40 +45.206495 + 40 +55.560901 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 10 +755.056774 + 20 +800.000000 + 30 +0.0 + 10 +758.979025 + 20 +799.743677 + 30 +0.0 + 10 +766.727687 + 20 +799.237295 + 30 +0.0 + 10 +777.625549 + 20 +795.212321 + 30 +0.0 + 10 +787.055959 + 20 +789.053297 + 30 +0.0 + 10 +794.283125 + 20 +780.902144 + 30 +0.0 + 10 +799.081762 + 20 +771.355296 + 30 +0.0 + 10 +799.695204 + 20 +764.470162 + 30 +0.0 + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 11 +755.056774 + 21 +800.000000 + 31 +0.0 + 11 +766.720585 + 21 +798.665525 + 31 +0.0 + 11 +777.500086 + 21 +794.795845 + 31 +0.0 + 11 +786.836434 + 21 +788.591575 + 31 +0.0 + 11 +793.995206 + 21 +780.500074 + 31 +0.0 + 11 +798.460221 + 21 +771.157839 + 31 +0.0 + 11 +800.000000 + 21 +761.049202 + 31 +0.0 + 0 +LINE + 5 +12e +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 11 +644.943226 + 21 +700.000000 + 31 +0.0 + 0 +SPLINE + 5 +12f +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +13 + 73 +9 + 74 +7 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +10.225236 + 40 +20.579642 + 40 +31.383364 + 40 +42.593197 + 40 +54.046234 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 10 +800.000000 + 20 +738.950798 + 30 +0.0 + 10 +799.695204 + 20 +735.529838 + 30 +0.0 + 10 +799.081762 + 20 +728.644704 + 30 +0.0 + 10 +794.283125 + 20 +719.097856 + 30 +0.0 + 10 +787.055959 + 20 +710.946703 + 30 +0.0 + 10 +777.625549 + 20 +704.787679 + 30 +0.0 + 10 +766.727687 + 20 +700.762705 + 30 +0.0 + 10 +758.979025 + 20 +700.256323 + 30 +0.0 + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 11 +800.000000 + 21 +738.950798 + 31 +0.0 + 11 +798.460221 + 21 +728.842161 + 31 +0.0 + 11 +793.995206 + 21 +719.499926 + 31 +0.0 + 11 +786.836434 + 21 +711.408425 + 31 +0.0 + 11 +777.500086 + 21 +705.204155 + 31 +0.0 + 11 +766.720585 + 21 +701.334475 + 31 +0.0 + 11 +755.056774 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +130 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 11 +600.000000 + 21 +761.049202 + 31 +0.0 + 0 +SPLINE + 5 +131 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +13 + 73 +9 + 74 +7 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +11.739902 + 40 +23.192940 + 40 +34.402773 + 40 +45.206495 + 40 +55.560901 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 10 +644.943226 + 20 +700.000000 + 30 +0.0 + 10 +641.020975 + 20 +700.256323 + 30 +0.0 + 10 +633.272313 + 20 +700.762705 + 30 +0.0 + 10 +622.374451 + 20 +704.787679 + 30 +0.0 + 10 +612.944041 + 20 +710.946703 + 30 +0.0 + 10 +605.716875 + 20 +719.097856 + 30 +0.0 + 10 +600.918238 + 20 +728.644704 + 30 +0.0 + 10 +600.304796 + 20 +735.529838 + 30 +0.0 + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 11 +644.943226 + 21 +700.000000 + 31 +0.0 + 11 +633.279415 + 21 +701.334475 + 31 +0.0 + 11 +622.499914 + 21 +705.204155 + 31 +0.0 + 11 +613.163566 + 21 +711.408425 + 31 +0.0 + 11 +606.004794 + 21 +719.499926 + 31 +0.0 + 11 +601.539779 + 21 +728.842161 + 31 +0.0 + 11 +600.000000 + 21 +738.950798 + 31 +0.0 + 0 +LINE + 5 +132 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +644.943226 + 21 +800.000000 + 31 +0.0 + 0 +SPLINE + 5 +133 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +0 + 71 +3 + 72 +13 + 73 +9 + 74 +7 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +0.000000 + 40 +10.225236 + 40 +20.579642 + 40 +31.383364 + 40 +42.593197 + 40 +54.046234 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 40 +65.786137 + 10 +600.000000 + 20 +761.049202 + 30 +0.0 + 10 +600.304796 + 20 +764.470162 + 30 +0.0 + 10 +600.918238 + 20 +771.355296 + 30 +0.0 + 10 +605.716875 + 20 +780.902144 + 30 +0.0 + 10 +612.944041 + 20 +789.053297 + 30 +0.0 + 10 +622.374451 + 20 +795.212321 + 30 +0.0 + 10 +633.272313 + 20 +799.237295 + 30 +0.0 + 10 +641.020975 + 20 +799.743677 + 30 +0.0 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +600.000000 + 21 +761.049202 + 31 +0.0 + 11 +601.539779 + 21 +771.157839 + 31 +0.0 + 11 +606.004794 + 21 +780.500074 + 31 +0.0 + 11 +613.163566 + 21 +788.591575 + 31 +0.0 + 11 +622.499914 + 21 +794.795845 + 31 +0.0 + 11 +633.279415 + 21 +798.665525 + 31 +0.0 + 11 +644.943226 + 21 +800.000000 + 31 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/refs/dxf_outlines__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/dxf_outlines__--id__p1__--id__r3.out new file mode 100644 index 0000000..3e58fcb --- /dev/null +++ b/share/extensions/tests/data/refs/dxf_outlines__--id__p1__--id__r3.out @@ -0,0 +1,3416 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1014 + 9 +$HANDSEED + 5 +FFFF + 9 +$INSUNITS + 70 + 0 + 9 +$MEASUREMENT + 70 + 1 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +VPORT + 5 +2E +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +210.0 + 22 +148.5 + 13 +0.0 + 23 +0.0 + 14 +10.0 + 24 +10.0 + 15 +10.0 + 25 +10.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 40 +341.0 + 41 +1.24 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYBLOCK + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BYLAYER + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CONTINUOUS + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +100 +AcDbSymbolTable + 70 +4 + 0 +LAYER + 5 +50 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +51 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide3 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +52 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide2 + 70 +0 + 6 +CONTINUOUS + 0 +LAYER + 5 +53 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Slide1 + 70 +0 + 6 +CONTINUOUS + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +STANDARD + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +2.5 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +ISO-25 + 70 + 0 + 3 + + 4 + + 5 + + 6 + + 7 + + 40 +1.0 + 41 +2.5 + 42 +0.625 + 43 +3.75 + 44 +1.25 + 45 +0.0 + 46 +0.0 + 47 +0.0 + 48 +0.0 +140 +2.5 +141 +2.5 +142 +0.0 +143 +0.03937007874016 +144 +1.0 +145 +0.0 +146 +1.0 +147 +0.625 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 0 + 75 + 0 + 76 + 0 + 77 + 1 + 78 + 8 +170 + 0 +171 + 3 +172 + 1 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +270 + 2 +271 + 2 +272 + 2 +273 + 2 +274 + 3 +340 +11 +275 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 0 +284 + 8 +285 + 0 +286 + 0 +287 + 3 +288 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*MODEL_SPACE + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*PAPER_SPACE + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*MODEL_SPACE + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*MODEL_SPACE + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*PAPER_SPACE + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +100 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +646.073390 + 31 +0.0 + 0 +LINE + 5 +101 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +646.073390 + 30 +0.0 + 11 +900.000020 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +102 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +900.000020 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +444.575280 + 31 +0.0 + 0 +LINE + 5 +103 +100 +AcDbEntity + 8 +Slide3 + 62 +7 +100 +AcDbLine + 10 +651.308900 + 20 +444.575280 + 30 +0.0 + 11 +651.308900 + 21 +646.073390 + 31 +0.0 + 0 +SPLINE + 5 +104 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 10 +129.776888 + 20 +600.000000 + 30 +0.0 + 10 +111.545073 + 20 +587.817891 + 30 +0.0 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +105 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +103.806023 + 20 +569.134172 + 30 +0.0 + 10 +96.066973 + 20 +550.450452 + 30 +0.0 + 10 +100.344761 + 20 +528.944561 + 30 +0.0 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +106 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +114.644661 + 20 +514.644661 + 30 +0.0 + 10 +128.944561 + 20 +500.344761 + 30 +0.0 + 10 +150.450452 + 20 +496.066973 + 30 +0.0 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +107 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +169.134172 + 20 +503.806023 + 30 +0.0 + 10 +187.817891 + 20 +511.545073 + 30 +0.0 + 10 +200.000000 + 20 +529.776888 + 30 +0.0 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +108 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +200.000000 + 20 +550.000000 + 30 +0.0 + 10 +200.000000 + 20 +563.260824 + 30 +0.0 + 10 +194.732158 + 20 +575.978520 + 30 +0.0 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +109 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +185.355339 + 20 +585.355339 + 30 +0.0 + 10 +175.978520 + 20 +594.732158 + 30 +0.0 + 10 +163.260824 + 20 +600.000000 + 30 +0.0 + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 0 +LINE + 5 +10a +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +150.000000 + 20 +600.000000 + 30 +0.0 + 11 +150.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +10b +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 10 +359.553776 + 20 +600.000000 + 30 +0.0 + 10 +323.090147 + 20 +587.817891 + 30 +0.0 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 0 +SPLINE + 5 +10c +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +307.612047 + 20 +569.134172 + 30 +0.0 + 10 +292.133947 + 20 +550.450452 + 30 +0.0 + 10 +300.689522 + 20 +528.944561 + 30 +0.0 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 0 +SPLINE + 5 +10d +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +329.289322 + 20 +514.644661 + 30 +0.0 + 10 +357.889121 + 20 +500.344761 + 30 +0.0 + 10 +400.900904 + 20 +496.066973 + 30 +0.0 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 0 +SPLINE + 5 +10e +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +438.268343 + 20 +503.806023 + 30 +0.0 + 10 +475.635782 + 20 +511.545073 + 30 +0.0 + 10 +500.000000 + 20 +529.776888 + 30 +0.0 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 0 +SPLINE + 5 +10f +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +550.000000 + 30 +0.0 + 10 +500.000000 + 20 +563.260824 + 30 +0.0 + 10 +489.464316 + 20 +575.978520 + 30 +0.0 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 0 +SPLINE + 5 +110 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +470.710678 + 20 +585.355339 + 30 +0.0 + 10 +451.957040 + 20 +594.732158 + 30 +0.0 + 10 +426.521649 + 20 +600.000000 + 30 +0.0 + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 0 +LINE + 5 +111 +100 +AcDbEntity + 8 +Slide2 + 62 +1 +100 +AcDbLine + 10 +400.000000 + 20 +600.000000 + 30 +0.0 + 11 +400.000000 + 21 +600.000000 + 31 +0.0 + 0 +SPLINE + 5 +112 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +783.086350 + 20 +522.176190 + 30 +0.0 + 10 +758.815382 + 20 +504.056941 + 30 +0.0 + 10 +713.857171 + 20 +495.892961 + 30 +0.0 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 0 +SPLINE + 5 +113 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +671.987870 + 20 +502.001770 + 30 +0.0 + 10 +630.118574 + 20 +508.110580 + 30 +0.0 + 10 +600.997311 + 20 +527.082892 + 30 +0.0 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 0 +SPLINE + 5 +114 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.024860 + 20 +548.885200 + 30 +0.0 + 10 +599.052409 + 20 +570.687512 + 30 +0.0 + 10 +626.453123 + 20 +590.290091 + 30 +0.0 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 0 +SPLINE + 5 +115 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +667.736130 + 20 +597.326110 + 30 +0.0 + 10 +709.019129 + 20 +604.362128 + 30 +0.0 + 10 +754.660551 + 20 +597.208402 + 30 +0.0 + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 0 +LINE + 5 +116 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +780.522930 + 20 +579.648180 + 30 +0.0 + 11 +700.000000 + 21 +550.000000 + 31 +0.0 + 0 +LINE + 5 +117 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +700.000000 + 20 +550.000000 + 30 +0.0 + 11 +783.086350 + 21 +522.176190 + 31 +0.0 + 0 +LINE + 5 +118 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +400.000000 + 30 +0.0 + 11 +200.000000 + 21 +300.000000 + 31 +0.0 + 0 +LINE + 5 +119 +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +300.000000 + 30 +0.0 + 11 +300.000000 + 21 +400.000000 + 31 +0.0 + 0 +LINE + 5 +11a +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbLine + 10 +300.000000 + 20 +400.000000 + 30 +0.0 + 11 +400.000000 + 21 +300.000000 + 31 +0.0 + 0 +SPLINE + 5 +11b +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +400.000000 + 30 +0.0 + 10 +500.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 0 +SPLINE + 5 +11c +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +300.000000 + 30 +0.0 + 10 +700.000000 + 20 +300.000000 + 30 +0.0 + 10 +600.000000 + 20 +400.000000 + 30 +0.0 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 0 +SPLINE + 5 +11d +100 +AcDbEntity + 8 +Slide2 + 62 +7 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +700.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +400.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 10 +800.000000 + 20 +300.000000 + 30 +0.0 + 0 +LINE + 5 +11e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +244.833200 + 20 +110.859950 + 30 +0.0 + 11 +199.494330 + 21 +118.994410 + 31 +0.0 + 0 +LINE + 5 +11f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +199.494330 + 20 +118.994410 + 30 +0.0 + 11 +167.090050 + 21 +86.256880 + 31 +0.0 + 0 +LINE + 5 +120 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +167.090050 + 20 +86.256880 + 30 +0.0 + 11 +160.815900 + 21 +131.890400 + 31 +0.0 + 0 +LINE + 5 +121 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +160.815900 + 20 +131.890400 + 30 +0.0 + 11 +119.667180 + 21 +152.592240 + 31 +0.0 + 0 +LINE + 5 +122 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +119.667180 + 20 +152.592240 + 30 +0.0 + 11 +161.128420 + 21 +172.660850 + 31 +0.0 + 0 +LINE + 5 +123 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +161.128420 + 20 +172.660850 + 30 +0.0 + 11 +168.101390 + 21 +218.192820 + 31 +0.0 + 0 +LINE + 5 +124 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +168.101390 + 20 +218.192820 + 30 +0.0 + 11 +200.000000 + 21 +184.962380 + 31 +0.0 + 0 +LINE + 5 +125 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +200.000000 + 20 +184.962380 + 30 +0.0 + 11 +245.458240 + 21 +192.400850 + 31 +0.0 + 0 +LINE + 5 +126 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +245.458240 + 20 +192.400850 + 30 +0.0 + 11 +223.711430 + 21 +151.794700 + 31 +0.0 + 0 +LINE + 5 +127 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +223.711430 + 20 +151.794700 + 30 +0.0 + 11 +244.833200 + 21 +110.859950 + 31 +0.0 + 0 +LINE + 5 +128 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +444.833200 + 20 +107.863730 + 30 +0.0 + 11 +399.494330 + 21 +115.998190 + 31 +0.0 + 0 +LINE + 5 +129 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +399.494330 + 20 +115.998190 + 30 +0.0 + 11 +367.090050 + 21 +83.260660 + 31 +0.0 + 0 +LINE + 5 +12a +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +367.090050 + 20 +83.260660 + 30 +0.0 + 11 +360.815900 + 21 +128.894180 + 31 +0.0 + 0 +LINE + 5 +12b +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +360.815900 + 20 +128.894180 + 30 +0.0 + 11 +319.667180 + 21 +149.596020 + 31 +0.0 + 0 +LINE + 5 +12c +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +319.667180 + 20 +149.596020 + 30 +0.0 + 11 +361.128420 + 21 +169.664630 + 31 +0.0 + 0 +LINE + 5 +12d +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +361.128420 + 20 +169.664630 + 30 +0.0 + 11 +368.101390 + 21 +215.196600 + 31 +0.0 + 0 +LINE + 5 +12e +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +368.101390 + 20 +215.196600 + 30 +0.0 + 11 +400.000000 + 21 +181.966160 + 31 +0.0 + 0 +LINE + 5 +12f +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +400.000000 + 20 +181.966160 + 30 +0.0 + 11 +445.458240 + 21 +189.404630 + 31 +0.0 + 0 +LINE + 5 +130 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +445.458240 + 20 +189.404630 + 30 +0.0 + 11 +423.711430 + 21 +148.798480 + 31 +0.0 + 0 +LINE + 5 +131 +100 +AcDbEntity + 8 +Slide2 + 62 +3 +100 +AcDbLine + 10 +423.711430 + 20 +148.798480 + 30 +0.0 + 11 +444.833200 + 21 +107.863730 + 31 +0.0 + 0 +LINE + 5 +132 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +133 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +800.000000 + 30 +0.0 + 11 +200.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +134 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +200.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +135 +100 +AcDbEntity + 8 +Slide1 + 62 +7 +100 +AcDbLine + 10 +100.000000 + 20 +700.000000 + 30 +0.0 + 11 +100.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +136 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +137 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +800.000000 + 30 +0.0 + 11 +500.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +138 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +500.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +700.000000 + 31 +0.0 + 0 +LINE + 5 +139 +100 +AcDbEntity + 8 +Slide1 + 62 +1 +100 +AcDbLine + 10 +300.000000 + 20 +700.000000 + 30 +0.0 + 11 +300.000000 + 21 +800.000000 + 31 +0.0 + 0 +LINE + 5 +13a +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +755.056774 + 21 +800.000000 + 31 +0.0 + 0 +SPLINE + 5 +13b +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +755.056774 + 20 +800.000000 + 30 +0.0 + 10 +766.976459 + 20 +800.000000 + 30 +0.0 + 10 +778.407944 + 20 +795.896267 + 30 +0.0 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +13c +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +788.591575 + 30 +0.0 + 10 +795.264924 + 20 +781.286884 + 30 +0.0 + 10 +800.000000 + 20 +771.379596 + 30 +0.0 + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 0 +LINE + 5 +13d +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +800.000000 + 20 +761.049202 + 30 +0.0 + 11 +800.000000 + 21 +738.950798 + 31 +0.0 + 0 +SPLINE + 5 +13e +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +800.000000 + 20 +738.950798 + 30 +0.0 + 10 +800.000000 + 20 +728.620404 + 30 +0.0 + 10 +795.264924 + 20 +718.713116 + 30 +0.0 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +13f +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +786.836434 + 20 +711.408425 + 30 +0.0 + 10 +778.407944 + 20 +704.103733 + 30 +0.0 + 10 +766.976459 + 20 +700.000000 + 30 +0.0 + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 0 +LINE + 5 +140 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +755.056774 + 20 +700.000000 + 30 +0.0 + 11 +644.943226 + 21 +700.000000 + 31 +0.0 + 0 +SPLINE + 5 +141 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +644.943226 + 20 +700.000000 + 30 +0.0 + 10 +633.023541 + 20 +700.000000 + 30 +0.0 + 10 +621.592056 + 20 +704.103733 + 30 +0.0 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 0 +SPLINE + 5 +142 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +711.408425 + 30 +0.0 + 10 +604.735076 + 20 +718.713116 + 30 +0.0 + 10 +600.000000 + 20 +728.620404 + 30 +0.0 + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 0 +LINE + 5 +143 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +600.000000 + 20 +738.950798 + 30 +0.0 + 11 +600.000000 + 21 +761.049202 + 31 +0.0 + 0 +SPLINE + 5 +144 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +600.000000 + 20 +761.049202 + 30 +0.0 + 10 +600.000000 + 20 +771.379596 + 30 +0.0 + 10 +604.735076 + 20 +781.286884 + 30 +0.0 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 0 +SPLINE + 5 +145 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbSpline + 70 +8 + 71 +3 + 72 +8 + 73 +4 + 74 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +0 + 40 +1 + 40 +1 + 40 +1 + 40 +1 + 10 +613.163566 + 20 +788.591575 + 30 +0.0 + 10 +621.592056 + 20 +795.896267 + 30 +0.0 + 10 +633.023541 + 20 +800.000000 + 30 +0.0 + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 0 +LINE + 5 +146 +100 +AcDbEntity + 8 +Slide1 + 62 +3 +100 +AcDbLine + 10 +644.943226 + 20 +800.000000 + 30 +0.0 + 11 +644.943226 + 21 +800.000000 + 31 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary + 3 +ACAD_GROUP +350 +D + 3 +ACAD_MLINESTYLE +350 +17 + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +1A +330 +C +100 +AcDbDictionary + 0 +DICTIONARY + 5 +17 +330 +C +100 +AcDbDictionary + 3 +STANDARD +350 +18 + 0 +DICTIONARY + 5 +19 +330 +C +100 +AcDbDictionary + 0 +ENDSEC + 0 +EOF diff --git a/share/extensions/tests/data/refs/edge3d__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/edge3d__--id__p1__--id__r3.out new file mode 100644 index 0000000..2bc2862 --- /dev/null +++ b/share/extensions/tests/data/refs/edge3d__--id__p1__--id__r3.out @@ -0,0 +1,44 @@ + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/export_gimp_palette.out b/share/extensions/tests/data/refs/export_gimp_palette.out new file mode 100644 index 0000000..c8c5d29 --- /dev/null +++ b/share/extensions/tests/data/refs/export_gimp_palette.out @@ -0,0 +1,13 @@ +GIMP Palette +Name: +# + 0 0 0 #000000 + 0 0 255 BLUE + 18 52 86 ColorName + 46 52 54 #2E3436 + 52 101 164 #3465A4 + 92 53 102 #5C3566 +114 159 207 #729FCF +117 80 123 #75507B +204 0 0 #CC0000 +255 0 0 RED diff --git a/share/extensions/tests/data/refs/export_gimp_palette__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/export_gimp_palette__--id__p1__--id__r3.out new file mode 100644 index 0000000..17b677f --- /dev/null +++ b/share/extensions/tests/data/refs/export_gimp_palette__--id__p1__--id__r3.out @@ -0,0 +1,6 @@ +GIMP Palette +Name: +# + 46 52 54 #2E3436 +204 0 0 #CC0000 +255 0 0 RED diff --git a/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2.out b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2.out new file mode 100644 index 0000000..29df6a5 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__polygons.out b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__polygons.out new file mode 100644 index 0000000..61c7eb3 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__polygons.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__snug.out b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__snug.out new file mode 100644 index 0000000..0821c94 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__c1__--id__c2__-m__snug.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2.out b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2.out new file mode 100644 index 0000000..22f3370 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__lines.out b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__lines.out new file mode 100644 index 0000000..228b186 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__lines.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__snug.out b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__snug.out new file mode 100644 index 0000000..a63008b --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p1__--id__p2__-m__snug.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__lines.out b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__lines.out new file mode 100644 index 0000000..1deed37 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__lines.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__polygons.out b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__polygons.out new file mode 100644 index 0000000..dc2a62e --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__polygons.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__snug.out b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__snug.out new file mode 100644 index 0000000..902f98c --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__p3__--id__p4__-m__snug.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2.out b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2.out new file mode 100644 index 0000000..dd88ce7 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-m__snug.out b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-m__snug.out new file mode 100644 index 0000000..2a94677 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-m__snug.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-s__False.out b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-s__False.out new file mode 100644 index 0000000..207e071 --- /dev/null +++ b/share/extensions/tests/data/refs/extrude__--id__r1__--id__r2__-s__False.out @@ -0,0 +1,18 @@ + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/fig_input.out b/share/extensions/tests/data/refs/fig_input.out new file mode 100644 index 0000000..8200ef9 --- /dev/null +++ b/share/extensions/tests/data/refs/fig_input.out @@ -0,0 +1,22 @@ + + + + + + + + + + + + + +Hello Inkscape + + diff --git a/share/extensions/tests/data/refs/flatten.out b/share/extensions/tests/data/refs/flatten.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/flatten__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/flatten__--id__p1__--id__r3.out new file mode 100644 index 0000000..f05ae54 --- /dev/null +++ b/share/extensions/tests/data/refs/flatten__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/foldablebox__--proportion__0__5__--guide__true__--unit__cm.out b/share/extensions/tests/data/refs/foldablebox__--proportion__0__5__--guide__true__--unit__cm.out new file mode 100644 index 0000000..34f61cd --- /dev/null +++ b/share/extensions/tests/data/refs/foldablebox__--proportion__0__5__--guide__true__--unit__cm.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/foldablebox__--width__20__--height__20__--depth__2__2__--unit__cm.out b/share/extensions/tests/data/refs/foldablebox__--width__20__--height__20__--depth__2__2__--unit__cm.out new file mode 100644 index 0000000..e4872bc --- /dev/null +++ b/share/extensions/tests/data/refs/foldablebox__--width__20__--height__20__--depth__2__2__--unit__cm.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/fractalize__--id__p1__--id__p2.out b/share/extensions/tests/data/refs/fractalize__--id__p1__--id__p2.out new file mode 100644 index 0000000..ec00e57 --- /dev/null +++ b/share/extensions/tests/data/refs/fractalize__--id__p1__--id__p2.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_absolute__20__--fill_color____AAA__--stroke_color____F00__--z_position__split.out b/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_absolute__20__--fill_color____AAA__--stroke_color____F00__--z_position__split.out new file mode 100644 index 0000000..de88a3c --- /dev/null +++ b/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_absolute__20__--fill_color____AAA__--stroke_color____F00__--z_position__split.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out b/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out new file mode 100644 index 0000000..face894 --- /dev/null +++ b/share/extensions/tests/data/refs/frame__--id__c2__--id__c1__--type__ellipse__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/frame__--id__t3__--type__rect__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out b/share/extensions/tests/data/refs/frame__--id__t3__--type__rect__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out new file mode 100644 index 0000000..a5b0351 --- /dev/null +++ b/share/extensions/tests/data/refs/frame__--id__t3__--type__rect__--offset_relative__10__--fill_color____AAA__--stroke_color____F00__--z_position__split.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/frame__--id__u1__--fill_color____AAA__--stroke_color____F00__--clip__True.out b/share/extensions/tests/data/refs/frame__--id__u1__--fill_color____AAA__--stroke_color____F00__--clip__True.out new file mode 100644 index 0000000..aed8eaf --- /dev/null +++ b/share/extensions/tests/data/refs/frame__--id__u1__--fill_color____AAA__--stroke_color____F00__--clip__True.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/frame__663c52a8114abe50f0559d9ccefab2e9.out b/share/extensions/tests/data/refs/frame__663c52a8114abe50f0559d9ccefab2e9.out new file mode 100644 index 0000000..6739f50 --- /dev/null +++ b/share/extensions/tests/data/refs/frame__663c52a8114abe50f0559d9ccefab2e9.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/funcplot__--id__p1__--id__r3__--times2pi__True__--ybottom__-1__0__--drawaxis__True.out b/share/extensions/tests/data/refs/funcplot__--id__p1__--id__r3__--times2pi__True__--ybottom__-1__0__--drawaxis__True.out new file mode 100644 index 0000000..b0e5bd5 --- /dev/null +++ b/share/extensions/tests/data/refs/funcplot__--id__p1__--id__r3__--times2pi__True__--ybottom__-1__0__--drawaxis__True.out @@ -0,0 +1,40 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/generate_voronoi__--id__r3__--id__p1.out b/share/extensions/tests/data/refs/generate_voronoi__--id__r3__--id__p1.out new file mode 100644 index 0000000..700fba3 --- /dev/null +++ b/share/extensions/tests/data/refs/generate_voronoi__--id__r3__--id__p1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/gimp_xcf.out b/share/extensions/tests/data/refs/gimp_xcf.out new file mode 100644 index 0000000..9438924 Binary files /dev/null and b/share/extensions/tests/data/refs/gimp_xcf.out differ diff --git a/share/extensions/tests/data/refs/gimp_xcf__-d__true__-r__true.out b/share/extensions/tests/data/refs/gimp_xcf__-d__true__-r__true.out new file mode 100644 index 0000000..183fb9b Binary files /dev/null and b/share/extensions/tests/data/refs/gimp_xcf__-d__true__-r__true.out differ diff --git a/share/extensions/tests/data/refs/grid_cartesian__154bd7ce1662209647ba2825e6d83cbc.out b/share/extensions/tests/data/refs/grid_cartesian__154bd7ce1662209647ba2825e6d83cbc.out new file mode 100644 index 0000000..1e79428 --- /dev/null +++ b/share/extensions/tests/data/refs/grid_cartesian__154bd7ce1662209647ba2825e6d83cbc.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/grid_cartesian__841ec156c192e3f468b6774927a90789.out b/share/extensions/tests/data/refs/grid_cartesian__841ec156c192e3f468b6774927a90789.out new file mode 100644 index 0000000..1e79428 --- /dev/null +++ b/share/extensions/tests/data/refs/grid_cartesian__841ec156c192e3f468b6774927a90789.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/grid_isometric__--dx__10__0__--subdivs_th__1__--subsubdivs_th__0__3.out b/share/extensions/tests/data/refs/grid_isometric__--dx__10__0__--subdivs_th__1__--subsubdivs_th__0__3.out new file mode 100644 index 0000000..6d4b675 --- /dev/null +++ b/share/extensions/tests/data/refs/grid_isometric__--dx__10__0__--subdivs_th__1__--subsubdivs_th__0__3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/grid_polar__--a_subdivs_cent__1__--a_labels__deg.out b/share/extensions/tests/data/refs/grid_polar__--a_subdivs_cent__1__--a_labels__deg.out new file mode 100644 index 0000000..7b5037d --- /dev/null +++ b/share/extensions/tests/data/refs/grid_polar__--a_subdivs_cent__1__--a_labels__deg.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + 0.015.030.045.060.075.090.0105.0120.0135.0150.0165.0180.0195.0210.0225.0240.0255.0270.0285.0300.0315.0330.0345.0 + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/grid_polar__--id__p1__--id__r3__--a_subdivs_cent__1__--a_labels__deg.out b/share/extensions/tests/data/refs/grid_polar__--id__p1__--id__r3__--a_subdivs_cent__1__--a_labels__deg.out new file mode 100644 index 0000000..7b5037d --- /dev/null +++ b/share/extensions/tests/data/refs/grid_polar__--id__p1__--id__r3__--a_subdivs_cent__1__--a_labels__deg.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + 0.015.030.045.060.075.090.0105.0120.0135.0150.0165.0180.0195.0210.0225.0240.0255.0270.0285.0300.0315.0330.0345.0 + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator.out b/share/extensions/tests/data/refs/guides_creator.out new file mode 100644 index 0000000..6749fa0 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__False__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out b/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__False__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out new file mode 100644 index 0000000..e166c8a --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__False__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__True__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out b/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__True__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out new file mode 100644 index 0000000..4c75674 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__diagonal_guides__--nodup__True__--pages__1-3__--ul__True__--ur__True__--ll__True__--lr__True.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_alternating_right.out b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_alternating_right.out new file mode 100644 index 0000000..baf03de --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_alternating_right.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_right__--vert__3__--horz__2.out b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_right__--vert__3__--horz__2.out new file mode 100644 index 0000000..704fd5a --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__False__--margins_preset__book_right__--vert__3__--horz__2.out @@ -0,0 +1,35 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__True__--margins_preset__book_alternating_left.out b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__True__--margins_preset__book_alternating_left.out new file mode 100644 index 0000000..5e46848 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__margins__--start_from_edges__True__--margins_preset__book_alternating_left.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__custom__--vertical_guides__4__--horizontal_guides__5.out b/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__custom__--vertical_guides__4__--horizontal_guides__5.out new file mode 100644 index 0000000..26a2492 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__custom__--vertical_guides__4__--horizontal_guides__5.out @@ -0,0 +1,35 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__golden.out b/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__golden.out new file mode 100644 index 0000000..a6f8e49 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--tab__regular_guides__--start_from_edges__True__--guides_preset__golden.out @@ -0,0 +1,35 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--vertical_guides__4__--horizontal_guides__3__--pages__1____3-7__12.out b/share/extensions/tests/data/refs/guides_creator__--vertical_guides__4__--horizontal_guides__3__--pages__1____3-7__12.out new file mode 100644 index 0000000..cf50565 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--vertical_guides__4__--horizontal_guides__3__--pages__1____3-7__12.out @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__--vertical_guides__6__--horizontal_guides__8.out b/share/extensions/tests/data/refs/guides_creator__--vertical_guides__6__--horizontal_guides__8.out new file mode 100644 index 0000000..3a61a20 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__--vertical_guides__6__--horizontal_guides__8.out @@ -0,0 +1,34 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__0cec5b2a62929d8e2c1469e6e5047e77.out b/share/extensions/tests/data/refs/guides_creator__0cec5b2a62929d8e2c1469e6e5047e77.out new file mode 100644 index 0000000..51cee7d --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__0cec5b2a62929d8e2c1469e6e5047e77.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__19bbe6630a0a22a9d7a6a65b25eb1c9f.out b/share/extensions/tests/data/refs/guides_creator__19bbe6630a0a22a9d7a6a65b25eb1c9f.out new file mode 100644 index 0000000..1218e33 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__19bbe6630a0a22a9d7a6a65b25eb1c9f.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__251d15df598c899ffbdc546ced9e2faa.out b/share/extensions/tests/data/refs/guides_creator__251d15df598c899ffbdc546ced9e2faa.out new file mode 100644 index 0000000..50293ea --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__251d15df598c899ffbdc546ced9e2faa.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__3b35068c24255b2144616d98c2a077bd.out b/share/extensions/tests/data/refs/guides_creator__3b35068c24255b2144616d98c2a077bd.out new file mode 100644 index 0000000..d4155f4 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__3b35068c24255b2144616d98c2a077bd.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__8f473fd113caab10b556f9cfe804e05e.out b/share/extensions/tests/data/refs/guides_creator__8f473fd113caab10b556f9cfe804e05e.out new file mode 100644 index 0000000..2f3669a --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__8f473fd113caab10b556f9cfe804e05e.out @@ -0,0 +1,34 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__92c07724de24b2568187779e17d89f83.out b/share/extensions/tests/data/refs/guides_creator__92c07724de24b2568187779e17d89f83.out new file mode 100644 index 0000000..7fd0af8 --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__92c07724de24b2568187779e17d89f83.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guides_creator__ca9cfba4b80367070f0d70d13c501131.out b/share/extensions/tests/data/refs/guides_creator__ca9cfba4b80367070f0d70d13c501131.out new file mode 100644 index 0000000..67d930a --- /dev/null +++ b/share/extensions/tests/data/refs/guides_creator__ca9cfba4b80367070f0d70d13c501131.out @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/guillotine__--ignore__true__--directory__TMP_DIR__img__.out b/share/extensions/tests/data/refs/guillotine__--ignore__true__--directory__TMP_DIR__img__.out new file mode 100644 index 0000000..f7bcbef Binary files /dev/null and b/share/extensions/tests/data/refs/guillotine__--ignore__true__--directory__TMP_DIR__img__.out differ diff --git a/share/extensions/tests/data/refs/guillotine__--image__f____oo__--directory__TMP_DIR__img__.out b/share/extensions/tests/data/refs/guillotine__--image__f____oo__--directory__TMP_DIR__img__.out new file mode 100644 index 0000000..fc02093 Binary files /dev/null and b/share/extensions/tests/data/refs/guillotine__--image__f____oo__--directory__TMP_DIR__img__.out differ diff --git a/share/extensions/tests/data/refs/guillotine__--image__output__--directory__TMP_DIR__img__.out b/share/extensions/tests/data/refs/guillotine__--image__output__--directory__TMP_DIR__img__.out new file mode 100644 index 0000000..db737cf Binary files /dev/null and b/share/extensions/tests/data/refs/guillotine__--image__output__--directory__TMP_DIR__img__.out differ diff --git a/share/extensions/tests/data/refs/handles__--id__curve__--id__quad.out b/share/extensions/tests/data/refs/handles__--id__curve__--id__quad.out new file mode 100644 index 0000000..48f9e0e --- /dev/null +++ b/share/extensions/tests/data/refs/handles__--id__curve__--id__quad.out @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey.out b/share/extensions/tests/data/refs/hershey.out new file mode 100644 index 0000000..a6b2290 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey.out @@ -0,0 +1,52 @@ + + + + + + + + image/svg+xml + + + + + + +     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_encoding.out b/share/extensions/tests/data/refs/hershey_encoding.out new file mode 100755 index 0000000..92979a0 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_encoding.out @@ -0,0 +1,13 @@ + + + + + + + image/svg+xml + + + + + EMSAllureEMSElfinEMSFelixEMSNixishEMSNixishItalicEMSOsmotronEMSReadabilityEMSReadabilityItalicEMSTechHersheyGothEnglishHersheySans1HersheySansMedHersheyScript1HersheyScriptMedHersheySerifBoldHersheySerifBoldItalicHersheySerifMedHersheySerifMedItalic + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_fonttable.out b/share/extensions/tests/data/refs/hershey_fonttable.out new file mode 100755 index 0000000..35ed814 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_fonttable.out @@ -0,0 +1,13 @@ + + + + + + + image/svg+xml + + + + + EMSAllureEMSElfinEMSFelixEMSNixishEMSNixishItalicEMSOsmotronEMSReadabilityEMSReadabilityItalicEMSTechHersheyGothEnglishHersheySans1HersheySansMedHersheyScript1HersheyScriptMedHersheySerifBoldHersheySerifBoldItalicHersheySerifMedHersheySerifMedItalic + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_glyphtable.out b/share/extensions/tests/data/refs/hershey_glyphtable.out new file mode 100755 index 0000000..cfb0ecc --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_glyphtable.out @@ -0,0 +1,13 @@ + + + + + + + image/svg+xml + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_loadfont.out b/share/extensions/tests/data/refs/hershey_loadfont.out new file mode 100755 index 0000000..003e932 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_loadfont.out @@ -0,0 +1,17 @@ + + + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_partialselection.out b/share/extensions/tests/data/refs/hershey_partialselection.out new file mode 100755 index 0000000..21324f9 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_partialselection.out @@ -0,0 +1,22 @@ + + + + + + + + image/svg+xml + + + + + + + + + + Text + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hershey_preservetext.out b/share/extensions/tests/data/refs/hershey_preservetext.out new file mode 100755 index 0000000..b566766 --- /dev/null +++ b/share/extensions/tests/data/refs/hershey_preservetext.out @@ -0,0 +1,22 @@ + + + + + + + + image/svg+xml + + + + + + + + + + Flow Text + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hpgl_input.out b/share/extensions/tests/data/refs/hpgl_input.out new file mode 100644 index 0000000..b00d209 --- /dev/null +++ b/share/extensions/tests/data/refs/hpgl_input.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__hpgl_multipen__svg.out b/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__hpgl_multipen__svg.out new file mode 100644 index 0000000..d0f4221 --- /dev/null +++ b/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__hpgl_multipen__svg.out @@ -0,0 +1 @@ +IN;PU;SP1;VS20;FS24;PU0,0;PD0,90;PU855,1988;PD860,1986,864,1983,865,1977,863,1972,859,1969,855,1968,855,1170,850,1172,846,1176,845,1180,0,1180,2,1185,5,1189,10,1190,10,1988,15,1986,19,1983,20,1978,865,1978,863,1973,860,1969,855,1968,855,1928;PU;SP2;PU855,798;PD855,798,855,0,850,2,846,6,845,10,0,10,2,16,5,19,10,20,10,818,15,817,19,813,20,808,865,808,863,803,860,799,855,798,855,758;PU;SP3;PU855,3108;PD855,3108,855,2310,850,2311,846,2315,845,2320,0,2320,2,2325,5,2329,10,2330,10,3128,15,3126,19,3122,20,3118,865,3118,863,3112,860,3109,855,3108,855,3068;SP0;PU0,0;IN; \ No newline at end of file diff --git a/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__shapes__svg.out b/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__shapes__svg.out new file mode 100644 index 0000000..f6f0529 --- /dev/null +++ b/share/extensions/tests/data/refs/hpgl_output__--force__24__--speed__20__--orientation__90__shapes__svg.out @@ -0,0 +1 @@ +IN;PU;SP1;VS20;FS24;PU0,0;PD0,90;PU5966,2652;PD5971,2651,5975,2647,5976,2641,5975,2636,5971,2633,5966,2632,5966,0,5961,1,5957,5,5956,10,3824,10,3825,15,3829,19,3834,20,3834,2652,3839,2651,3843,2647,3844,2642,5976,2642,5975,2637,5971,2633,5966,2632,5966,2592;PU5479,7938;PD5474,7939,5470,7943,5469,7948,5470,7953,5474,7957,5478,7957,5477,7997,5476,7997,5472,8037,5471,8036,5464,8075,5463,8075,5453,8112,5452,8112,5439,8149,5439,8148,5423,8184,5405,8218,5404,8217,5384,8250,5361,8281,5361,8280,5336,8310,5335,8309,5308,8337,5308,8336,5279,8362,5248,8385,5247,8385,5214,8406,5214,8405,5180,8425,5179,8424,5143,8441,5143,8440,5105,8454,5105,8453,5067,8464,5067,8463,5029,8471,5028,8470,4990,8476,4990,8475,4951,8477,4951,8476,4913,8476,4913,8475,4874,8472,4874,8471,4836,8465,4837,8464,4799,8455,4763,8443,4763,8442,4727,8428,4727,8427,4692,8411,4693,8410,4659,8390,4660,8390,4627,8368,4628,8367,4597,8343,4597,8342,4568,8315,4569,8314,4541,8285,4542,8285,4517,8254,4518,8253,4496,8221,4497,8221,4477,8187,4478,8187,4461,8152,4461,8151,4447,8116,4448,8115,4436,8079,4437,8078,4428,8041,4429,8041,4423,8003,4420,7964,4421,7964,4420,7926,4421,7926,4423,7887,4424,7887,4429,7849,4430,7849,4438,7811,4439,7811,4450,7773,4464,7736,4465,7736,4481,7700,4482,7700,4501,7665,4502,7666,4523,7633,4524,7633,4548,7603,4574,7574,4574,7575,4602,7548,4603,7548,4632,7524,4664,7502,4697,7482,4697,7483,4731,7465,4732,7466,4767,7450,4767,7451,4804,7438,4804,7439,4842,7429,4842,7430,4880,7422,4880,7423,4920,7419,4959,7418,4959,7419,5014,7422,5013,7423,5066,7431,5066,7432,5117,7445,5116,7446,5165,7463,5164,7464,5211,7487,5210,7487,5254,7514,5253,7515,5294,7545,5293,7546,5331,7580,5330,7581,5365,7618,5364,7619,5394,7660,5393,7660,5420,7704,5419,7704,5441,7751,5458,7800,5457,7800,5470,7851,5469,7851,5477,7903,5476,7903,5479,7957,5478,7957,5477,7997,5476,7997;PU5478,5312;PD5478,5312,5477,5391,5472,5470,5465,5547,5464,5547,5454,5622,5441,5695,5425,5766,5407,5834,5387,5899,5386,5899,5364,5961,5363,5961,5338,6020,5311,6075,5310,6075,5282,6126,5281,6126,5250,6173,5217,6216,5216,6215,5182,6254,5181,6253,5145,6286,5144,6285,5107,6313,5106,6312,5068,6334,5067,6333,5029,6349,5029,6348,4990,6358,4990,6356,4951,6361,4951,6359,4913,6358,4913,6357,4874,6350,4875,6349,4837,6337,4837,6335,4800,6318,4800,6317,4764,6293,4728,6264,4729,6263,4694,6230,4695,6229,4661,6190,4662,6190,4630,6145,4599,6096,4600,6095,4571,6041,4544,5982,4520,5920,4498,5856,4499,5855,4479,5788,4480,5788,4463,5718,4449,5647,4449,5646,4438,5573,4429,5498,4430,5498,4424,5422,4421,5346,4420,5268,4421,5268,4423,5191,4428,5114,4429,5114,4437,5037,4448,4962,4449,4962,4462,4887,4463,4887,4479,4814,4480,4815,4499,4745,4499,4746,4521,4680,4545,4618,4546,4619,4571,4561,4572,4561,4599,4507,4600,4508,4629,4458,4630,4458,4661,4413,4662,4414,4695,4374,4729,4339,4730,4339,4765,4309,4766,4310,4803,4284,4803,4285,4841,4265,4841,4266,4880,4252,4880,4253,4919,4244,4920,4246,4959,4243,4959,4244,4987,4245,4987,4246,5013,4250,5013,4251,5040,4258,5040,4259,5066,4268,5065,4269,5091,4281,5090,4282,5116,4296,5115,4297,5140,4313,5139,4314,5163,4333,5186,4354,5186,4355,5209,4378,5208,4379,5230,4404,5252,4432,5251,4432,5292,4493,5291,4494,5328,4562,5362,4638,5361,4638,5392,4719,5391,4720,5418,4807,5417,4807,5439,4899,5439,4900,5457,4997,5456,4997,5469,5098,5477,5203,5476,5203,5479,5312,5478,5312,5478,5352;PU4655,1257;PD4650,1256,4649,1256,4615,1306,4615,1307,4583,1362,4584,1362,4554,1422,4555,1422,4528,1486,4528,1487,4504,1554,4505,1554,4483,1625,4484,1625,4465,1699,4466,1699,4450,1775,4451,1775,4438,1854,4429,1934,4423,2016,4420,2099,4421,2099,4421,2182,4425,2266,4432,2350,4443,2433,4457,2514,4474,2592,4494,2667,4495,2667,4517,2737,4542,2803,4543,2803,4570,2865,4571,2865,4600,2922,4601,2922,4632,2975,4633,2974,4667,3022,4667,3021,4703,3064,4703,3063,4741,3100,4741,3099,4780,3130,4780,3129,4820,3154,4821,3153,4862,3171,4862,3170,4904,3182,4905,3181,4948,3186,4948,3184,4991,3183,4990,3181,5033,3173,5032,3171,5074,3156,5073,3155,5114,3134,5113,3133,5152,3105,5151,3104,5189,3071,5188,3070,5225,3031,5224,3031,5259,2986,5258,2986,5291,2936,5290,2936,5321,2881,5349,2821,5375,2757,5375,2756,5398,2688,5419,2615,5437,2539,5437,2538,5452,2458,5464,2376,5472,2293,5477,2209,5479,2126,5477,2043,5472,1961,5464,1880,5453,1800,5439,1723,5438,1723,5422,1647,5421,1648,5401,1575,5378,1505,5378,1506,5352,1439,5352,1440,5324,1377,5323,1378,5292,1319,5292,1320,5258,1266,5254,1270,5253,1275,5255,1280,5259,1284,5260,1284,4946,2136,4942,2133,4940,2128,4940,2123,4944,2119,4946,2117,4652,1238,4647,1241,4645,1246,4646,1251,4649,1255,4649,1256,4627,1289;PU3356,8485;PD3353,8481,3352,8476,3354,8471,3355,8470,2297,7411,2301,7409,2307,7409,2311,7411,3369,6353,3364,6350,3359,6350,3355,6353,2297,5295;PU3355,4236;PD3352,4241,3352,4243,3307,4241,3307,4240,3254,4235,3187,4225,3107,4209,3107,4208,3017,4185,3018,4184,2970,4169,2971,4169,2922,4151,2873,4130,2824,4107,2824,4106,2774,4080,2775,4079,2726,4050,2726,4049,2678,4016,2631,3979,2631,3978,2585,3938,2586,3937,2542,3892,2543,3892,2501,3843,2502,3842,2463,3789,2464,3788,2428,3730,2429,3730,2397,3667,2398,3666,2369,3598,2370,3598,2346,3525,2347,3525,2327,3446,2328,3446,2314,3361,2315,3361,2306,3271,2303,3175,2304,3175,2307,3082,2308,3082,2317,3000,2324,2964,2332,2930,2333,2930,2342,2899,2352,2870,2353,2870,2364,2843,2365,2843,2378,2819,2392,2797,2393,2797,2407,2777,2408,2777,2423,2759,2424,2760,2440,2743,2441,2744,2458,2729,2459,2729,2477,2716,2478,2717,2516,2695,2517,2696,2558,2680,2559,2681,2603,2669,2603,2670,2648,2662,2648,2663,2696,2658,2696,2659,2744,2656,2744,2657,2843,2656,2942,2655,2942,2654,2990,2652,2990,2651,3037,2647,3037,2646,3083,2638,3082,2637,3126,2625,3126,2624,3167,2608,3167,2607,3205,2585,3205,2584,3223,2571,3222,2570,3240,2555,3239,2555,3256,2538,3255,2537,3271,2519,3270,2519,3285,2498,3284,2498,3298,2475,3297,2475,3310,2450,3309,2450,3320,2423,3330,2394,3339,2362,3338,2362,3346,2328,3345,2328,3352,2291,3351,2291,3360,2210,3359,2210,3362,2117,3359,2021,3358,2021,3349,1930,3348,1931,3334,1846,3333,1846,3314,1768,3313,1768,3289,1695,3261,1627,3260,1627,3228,1564,3227,1564,3191,1506,3191,1507,3152,1453,3151,1454,3110,1405,3066,1360,3065,1361,3020,1320,3019,1321,2972,1284,2923,1251,2923,1252,2874,1222,2824,1196,2774,1173,2774,1174,2725,1153,2725,1154,2676,1136,2629,1121,2629,1122,2539,1098,2539,1099,2459,1083,2391,1074,2339,1069,2339,1070,2294,1068;PU292,6943;PD293,6949,297,6952,302,6954,304,6954,390,7434,384,7433,381,7431,34,7774,39,7776,44,7776,49,7773,51,7769,51,7768,534,7834,532,7839,529,7842,748,8277,752,8274,754,8269,752,8264,749,8260,748,8260,960,7821,964,7824,966,7828,1448,7754,1446,7750,1441,7746,1436,7746,1431,7749,1079,7411,1084,7409,1088,7408,1167,6927,1161,6928,1157,6931,1155,6936,1156,6941,1156,6942,726,7172,725,7167,726,7163,293,6939,292,6944,294,6950,298,6953,303,6954,304,6954,311,6993;PU272,4837;PD272,4837,358,5317,353,5316,349,5314,3,5657,7,5660,13,5660,17,5657,20,5652,20,5651,503,5718,501,5723,497,5725,716,6161,720,6157,722,6152,721,6147,717,6143,716,6143,929,5704,933,5708,934,5712,1416,5638,1414,5633,1409,5630,1404,5629,1399,5632,1047,5295,1052,5292,1056,5292,1135,4811,1130,4811,1125,4814,1123,4819,1124,4825,695,5055,693,5050,695,5046,261,4823,260,4828,262,4833,266,4836,271,4837,272,4837,279,4876;PU8793,5312;PD8798,5309,8801,5305,8801,5299,8798,5295,8794,5292,8791,5292,8791,4551,8786,4552,8782,4556,8781,4561,8047,4561,8048,4566,8052,4570,8057,4571,8057,5312,8062,5310,8066,5306,8067,5302,8801,5302,8800,5297,8796,5293,8791,5292,8791,5252;PU7595,8467;PD7595,8467,7595,7408,7590,7410,7587,7414,7585,7418,6527,7418,6528,7423,6532,7427,6537,7428,6537,8487,6542,8485,6546,8481,6547,8477,7605,8477,7604,8472,7600,8468,7595,8467,7595,8427;PU7595,6350;PD7595,6350,7595,4233,7590,4235,7587,4239,7585,4243,6527,4243,6528,4248,6532,4252,6537,4253,6537,6370,6542,6369,6546,6365,6547,6360,7605,6360,7604,6355,7600,6351,7595,6350,7595,6310;PU7595,2699;PD7595,2699,7595,1534,7593,1487,7592,1487,7586,1441,7585,1441,7575,1396,7561,1352,7560,1353,7543,1311,7542,1311,7521,1271,7521,1272,7497,1234,7496,1235,7468,1200,7437,1169,7437,1170,7404,1142,7404,1143,7369,1119,7368,1120,7332,1100,7332,1101,7294,1085,7293,1086,7254,1075,7254,1076,7214,1069,7214,1070,7173,1068,6939,1068,6939,1069,6899,1071,6899,1072,6859,1079,6859,1080,6820,1092,6820,1093,6782,1108,6783,1109,6746,1129,6747,1130,6712,1154,6713,1155,6680,1183,6681,1183,6651,1215,6652,1216,6624,1250,6625,1251,6601,1289,6602,1289,6581,1329,6582,1329,6565,1371,6565,1372,6552,1415,6553,1415,6543,1461,6544,1461,6538,1507,6539,1507,6537,1554,6537,2719,6539,2766,6540,2766,6546,2812,6547,2812,6557,2857,6558,2857,6571,2901,6572,2901,6589,2943,6590,2942,6611,2982,6612,2982,6636,3019,6637,3019,6664,3054,6665,3053,6695,3085,6696,3084,6728,3112,6729,3111,6763,3135,6764,3134,6800,3154,6801,3153,6839,3168,6839,3167,6878,3179,6878,3177,6918,3184,6918,3183,6959,3186,6959,3185,7193,3185,7193,3184,7234,3182,7234,3181,7274,3174,7274,3173,7313,3162,7312,3161,7350,3145,7350,3144,7386,3124,7385,3123,7420,3099,7419,3099,7452,3071,7451,3070,7482,3038,7481,3038,7508,3003,7507,3002,7531,2965,7531,2964,7551,2924,7568,2882,7567,2882,7580,2838,7589,2793,7595,2746,7594,2746,7596,2699,7595,2699,7595,2659;SP0;PU0,0;IN; \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_attributes.out b/share/extensions/tests/data/refs/image_attributes.out new file mode 100644 index 0000000..90f335e --- /dev/null +++ b/share/extensions/tests/data/refs/image_attributes.out @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_attributes__--id__embeded_image01__--image_rendering__optimizeSpeed__--tab____tab_image_rendering__.out b/share/extensions/tests/data/refs/image_attributes__--id__embeded_image01__--image_rendering__optimizeSpeed__--tab____tab_image_rendering__.out new file mode 100644 index 0000000..9dbd633 --- /dev/null +++ b/share/extensions/tests/data/refs/image_attributes__--id__embeded_image01__--image_rendering__optimizeSpeed__--tab____tab_image_rendering__.out @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_attributes__--id__image174__--aspect_ratio__xMinYMin__--tab____tab_aspect_ratio__.out b/share/extensions/tests/data/refs/image_attributes__--id__image174__--aspect_ratio__xMinYMin__--tab____tab_aspect_ratio__.out new file mode 100644 index 0000000..2553d2b --- /dev/null +++ b/share/extensions/tests/data/refs/image_attributes__--id__image174__--aspect_ratio__xMinYMin__--tab____tab_aspect_ratio__.out @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_embed.out b/share/extensions/tests/data/refs/image_embed.out new file mode 100644 index 0000000..4c24140 --- /dev/null +++ b/share/extensions/tests/data/refs/image_embed.out @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_embed__--id__image174__--selectedonly__True.out b/share/extensions/tests/data/refs/image_embed__--id__image174__--selectedonly__True.out new file mode 100644 index 0000000..4c24140 --- /dev/null +++ b/share/extensions/tests/data/refs/image_embed__--id__image174__--selectedonly__True.out @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/image_extract__--selectedonly__False__--filepath__TMP_DIR__.out b/share/extensions/tests/data/refs/image_extract__--selectedonly__False__--filepath__TMP_DIR__.out new file mode 100644 index 0000000..3bc0a06 Binary files /dev/null and b/share/extensions/tests/data/refs/image_extract__--selectedonly__False__--filepath__TMP_DIR__.out differ diff --git a/share/extensions/tests/data/refs/image_extract__--selectedonly__True__--id__embeded_image01__--filepath__TMP_DIR__.out b/share/extensions/tests/data/refs/image_extract__--selectedonly__True__--id__embeded_image01__--filepath__TMP_DIR__.out new file mode 100644 index 0000000..3bc0a06 Binary files /dev/null and b/share/extensions/tests/data/refs/image_extract__--selectedonly__True__--id__embeded_image01__--filepath__TMP_DIR__.out differ diff --git a/share/extensions/tests/data/refs/ink2canvas.out b/share/extensions/tests/data/refs/ink2canvas.out new file mode 100644 index 0000000..c6bc3c0 --- /dev/null +++ b/share/extensions/tests/data/refs/ink2canvas.out @@ -0,0 +1,162 @@ + + + + + Inkscape Output + + + + + + diff --git a/share/extensions/tests/data/refs/ink2canvas__--id__alpha.out b/share/extensions/tests/data/refs/ink2canvas__--id__alpha.out new file mode 100644 index 0000000..717d6d0 --- /dev/null +++ b/share/extensions/tests/data/refs/ink2canvas__--id__alpha.out @@ -0,0 +1,288 @@ + + + + + Inkscape Output + + + + + + diff --git a/share/extensions/tests/data/refs/ink2canvas__--id__path31.out b/share/extensions/tests/data/refs/ink2canvas__--id__path31.out new file mode 100644 index 0000000..30951b1 --- /dev/null +++ b/share/extensions/tests/data/refs/ink2canvas__--id__path31.out @@ -0,0 +1,49 @@ + + + + + Inkscape Output + + + + + + diff --git a/share/extensions/tests/data/refs/ink2canvas__--id__rect3898.out b/share/extensions/tests/data/refs/ink2canvas__--id__rect3898.out new file mode 100644 index 0000000..c0c8c13 --- /dev/null +++ b/share/extensions/tests/data/refs/ink2canvas__--id__rect3898.out @@ -0,0 +1,124 @@ + + + + + Inkscape Output + + + + + + diff --git a/share/extensions/tests/data/refs/inkex_extensions_color.out b/share/extensions/tests/data/refs/inkex_extensions_color.out new file mode 100644 index 0000000..f2d7ded --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__color_svg.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__color_svg.out new file mode 100644 index 0000000..f2d7ded --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__color_svg.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1.out new file mode 100644 index 0000000..2a106d1 --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1__--id__r2.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1__--id__r2.out new file mode 100644 index 0000000..176992b --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r1__--id__r2.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__r2.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r2.out new file mode 100644 index 0000000..430e485 --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r2.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__r3.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r3.out new file mode 100644 index 0000000..f663d51 --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r3.out @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkex_extensions_color__--id__r4.out b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r4.out new file mode 100644 index 0000000..9c93172 --- /dev/null +++ b/share/extensions/tests/data/refs/inkex_extensions_color__--id__r4.out @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/inkscape_follow_link.out b/share/extensions/tests/data/refs/inkscape_follow_link.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/inkscape_follow_link__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/inkscape_follow_link__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/interp__3ed855778ec06e18dc5f0d8329e9d085.out b/share/extensions/tests/data/refs/interp__3ed855778ec06e18dc5f0d8329e9d085.out new file mode 100644 index 0000000..e947e70 --- /dev/null +++ b/share/extensions/tests/data/refs/interp__3ed855778ec06e18dc5f0d8329e9d085.out @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp__bf1a5fd7b7c87a9e06cf0b9659d389ed.out b/share/extensions/tests/data/refs/interp__bf1a5fd7b7c87a9e06cf0b9659d389ed.out new file mode 100644 index 0000000..c139806 --- /dev/null +++ b/share/extensions/tests/data/refs/interp__bf1a5fd7b7c87a9e06cf0b9659d389ed.out @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__c1__--id__c2__--id__c3__--att__style__fill.out b/share/extensions/tests/data/refs/interp_att_g__--id__c1__--id__c2__--id__c3__--att__style__fill.out new file mode 100644 index 0000000..9d7b9e9 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__c1__--id__c2__--id__c3__--att__style__fill.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__other__--att-other__width__--start-val__5__--end-val__10__--att-other-type__ValueInterpolator.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__other__--att-other__width__--start-val__5__--end-val__10__--att-other-type__ValueInterpolator.out new file mode 100644 index 0000000..55062d3 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__other__--att-other__width__--start-val__5__--end-val__10__--att-other-type__ValueInterpolator.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____050505__--end-val____000000.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____050505__--end-val____000000.out new file mode 100644 index 0000000..272230f --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____050505__--end-val____000000.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____181818__--end-val____000000.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____181818__--end-val____000000.out new file mode 100644 index 0000000..8b968a3 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__style__fill__--start-val____181818__--end-val____000000.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__scale__--start-val__0__2__--end-val__0__9.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__scale__--start-val__0__2__--end-val__0__9.out new file mode 100644 index 0000000..09bb63a --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__scale__--start-val__0__2__--end-val__0__9.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__trans-x__--start-val__0__--end-val__20.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__trans-x__--start-val__0__--end-val__20.out new file mode 100644 index 0000000..4581433 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__transform__trans-x__--start-val__0__--end-val__20.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__width__--start-val__0__02__--end-val__0__1__--unit__mm.out b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__width__--start-val__0__02__--end-val__0__1__--unit__mm.out new file mode 100644 index 0000000..7828cf3 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__g53__--att__width__--start-val__0__02__--end-val__0__1__--unit__mm.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__--id__layer1__--att__style__fill.out b/share/extensions/tests/data/refs/interp_att_g__--id__layer1__--att__style__fill.out new file mode 100644 index 0000000..14044d2 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__--id__layer1__--att__style__fill.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/interp_att_g__e692b471578dc63d4bf1ba375b8b650c.out b/share/extensions/tests/data/refs/interp_att_g__e692b471578dc63d4bf1ba375b8b650c.out new file mode 100644 index 0000000..5d405f1 --- /dev/null +++ b/share/extensions/tests/data/refs/interp_att_g__e692b471578dc63d4bf1ba375b8b650c.out @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_autotexts__--autoText__slideTitle__--id__t1.out b/share/extensions/tests/data/refs/jessyink_autotexts__--autoText__slideTitle__--id__t1.out new file mode 100644 index 0000000..acc2010 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_autotexts__--autoText__slideTitle__--id__t1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_effects__--id__p1__--effectIn__fade__--effectOut__pop__--effectOutOrder__2.out b/share/extensions/tests/data/refs/jessyink_effects__--id__p1__--effectIn__fade__--effectOut__pop__--effectOutOrder__2.out new file mode 100644 index 0000000..e101ee3 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_effects__--id__p1__--effectIn__fade__--effectOut__pop__--effectOutOrder__2.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/jessyink_effects__--id__p1__--id__r3__--effectOutOrder__2.out b/share/extensions/tests/data/refs/jessyink_effects__--id__p1__--id__r3__--effectOutOrder__2.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/jessyink_export__--resolution__1__--type__png.out b/share/extensions/tests/data/refs/jessyink_export__--resolution__1__--type__png.out new file mode 100644 index 0000000..b9168de Binary files /dev/null and b/share/extensions/tests/data/refs/jessyink_export__--resolution__1__--type__png.out differ diff --git a/share/extensions/tests/data/refs/jessyink_install.out b/share/extensions/tests/data/refs/jessyink_install.out new file mode 100644 index 0000000..f9d81b7 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_install.out @@ -0,0 +1,2766 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + // Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Set onload event handler. +window.onload = jessyInkInit; + +// Creating a namespace dictionary. The standard Inkscape namespaces are taken from inkex.py. +var NSS = new Object(); +NSS['sodipodi']='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'; +NSS['cc']='http://web.resource.org/cc/'; +NSS['svg']='http://www.w3.org/2000/svg'; +NSS['dc']='http://purl.org/dc/elements/1.1/'; +NSS['rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#'; +NSS['inkscape']='http://www.inkscape.org/namespaces/inkscape'; +NSS['xlink']='http://www.w3.org/1999/xlink'; +NSS['xml']='http://www.w3.org/XML/1998/namespace'; +NSS['jessyink']='https://launchpad.net/jessyink'; + +// Keycodes. +var LEFT_KEY = 37; // cursor left keycode +var UP_KEY = 38; // cursor up keycode +var RIGHT_KEY = 39; // cursor right keycode +var DOWN_KEY = 40; // cursor down keycode +var PAGE_UP_KEY = 33; // page up keycode +var PAGE_DOWN_KEY = 34; // page down keycode +var HOME_KEY = 36; // home keycode +var END_KEY = 35; // end keycode +var ENTER_KEY = 13; // next slide +var SPACE_KEY = 32; +var ESCAPE_KEY = 27; + +// Presentation modes. +var SLIDE_MODE = 1; +var INDEX_MODE = 2; +var DRAWING_MODE = 3; + +// Mouse handler actions. +var MOUSE_UP = 1; +var MOUSE_DOWN = 2; +var MOUSE_MOVE = 3; +var MOUSE_WHEEL = 4; + +// Parameters. +var ROOT_NODE = document.getElementsByTagNameNS(NSS["svg"], "svg")[0]; +var HEIGHT = 0; +var WIDTH = 0; +var INDEX_COLUMNS_DEFAULT = 4; +var INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; +var INDEX_OFFSET = 0; +var STATE_START = -1; +var STATE_END = -2; +var BACKGROUND_COLOR = null; +var slides = new Array(); + +// Initialisation. +var currentMode = SLIDE_MODE; +var masterSlide = null; +var activeSlide = 0; +var activeEffect = 0; +var timeStep = 30; // 40 ms equal 25 frames per second. +var lastFrameTime = null; +var processingEffect = false; +var transCounter = 0; +var effectArray = 0; +var defaultTransitionInDict = new Object(); +defaultTransitionInDict["name"] = "appear"; +var defaultTransitionOutDict = new Object(); +defaultTransitionOutDict["name"] = "appear"; +var jessyInkInitialised = false; + +// Initialise char and key code dictionaries. +var charCodeDictionary = getDefaultCharCodeDictionary(); +var keyCodeDictionary = getDefaultKeyCodeDictionary(); + +// Initialise mouse handler dictionary. +var mouseHandlerDictionary = getDefaultMouseHandlerDictionary(); + +var progress_bar_visible = false; +var timer_elapsed = 0; +var timer_start = timer_elapsed; +var timer_duration = 15; // 15 minutes + +var history_counter = 0; +var history_original_elements = new Array(); +var history_presentation_elements = new Array(); + +var mouse_original_path = null; +var mouse_presentation_path = null; +var mouse_last_x = -1; +var mouse_last_y = -1; +var mouse_min_dist_sqr = 3 * 3; +var path_colour = "red"; +var path_width_default = 3; +var path_width = path_width_default; +var path_paint_width = path_width; + +var number_of_added_slides = 0; + +/** Initialisation function. + * The whole presentation is set-up in this function. + */ +function jessyInkInit() +{ + // Make sure we only execute this code once. Double execution can occur if the onload event handler is set + // in the main svg tag as well (as was recommended in earlier versions). Executing this function twice does + // not lead to any problems, but it takes more time. + if (jessyInkInitialised) + return; + + // Making the presentation scalable. + var VIEWBOX = ROOT_NODE.getAttribute("viewBox"); + + if (VIEWBOX) + { + WIDTH = ROOT_NODE.viewBox.animVal.width; + HEIGHT = ROOT_NODE.viewBox.animVal.height; + } + else + { + HEIGHT = parseFloat(ROOT_NODE.getAttribute("height")); + WIDTH = parseFloat(ROOT_NODE.getAttribute("width")); + ROOT_NODE.setAttribute("viewBox", "0 0 " + WIDTH + " " + HEIGHT); + } + + ROOT_NODE.setAttribute("width", "100%"); + ROOT_NODE.setAttribute("height", "100%"); + + // Setting the background color. + var namedViews = document.getElementsByTagNameNS(NSS["sodipodi"], "namedview"); + + for (var counter = 0; counter < namedViews.length; counter++) + { + if (namedViews[counter].hasAttribute("id") && namedViews[counter].hasAttribute("pagecolor")) + { + if (namedViews[counter].getAttribute("id") == "base") + { + BACKGROUND_COLOR = namedViews[counter].getAttribute("pagecolor"); + var newAttribute = "background-color:" + BACKGROUND_COLOR + ";"; + + if (ROOT_NODE.hasAttribute("style")) + newAttribute += ROOT_NODE.getAttribute("style"); + + ROOT_NODE.setAttribute("style", newAttribute); + } + } + } + + // Defining clip-path. + var defsNodes = document.getElementsByTagNameNS(NSS["svg"], "defs"); + + if (defsNodes.length > 0) + { + var existingClipPath = document.getElementById("jessyInkSlideClipPath"); + + if (!existingClipPath) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + var clipPath = document.createElementNS(NSS["svg"], "clipPath"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + + clipPath.setAttribute("id", "jessyInkSlideClipPath"); + clipPath.setAttribute("clipPathUnits", "userSpaceOnUse"); + + clipPath.appendChild(rectNode); + defsNodes[0].appendChild(clipPath); + } + } + + // Making a list of the slide and finding the master slide. + var nodes = document.getElementsByTagNameNS(NSS["svg"], "g"); + var tempSlides = new Array(); + var existingJessyInkPresentationLayer = null; + + for (var counter = 0; counter < nodes.length; counter++) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") && (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") == "layer")) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "masterSlide") == "masterSlide") + masterSlide = nodes[counter]; + else if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "presentationLayer") == "presentationLayer") + existingJessyInkPresentationLayer = nodes[counter]; + else + tempSlides.push(nodes[counter].getAttribute("id")); + } + else if (nodes[counter].getAttributeNS(NSS['jessyink'], 'element')) + { + handleElement(nodes[counter]); + } + } + + // Hide master slide set default transitions. + if (masterSlide) + { + masterSlide.style.display = "none"; + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionIn")) + defaultTransitionInDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionIn")); + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionOut")) + defaultTransitionOutDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionOut")); + } + + if (existingJessyInkPresentationLayer != null) + { + existingJessyInkPresentationLayer.parentNode.removeChild(existingJessyInkPresentationLayer); + } + + // Set start slide. + var hashObj = new LocationHash(window.location.hash); + + activeSlide = hashObj.slideNumber; + activeEffect = hashObj.effectNumber; + + if (activeSlide < 0) + activeSlide = 0; + else if (activeSlide >= tempSlides.length) + activeSlide = tempSlides.length - 1; + + var originalNode = document.getElementById(tempSlides[counter]); + + var JessyInkPresentationLayer = document.createElementNS(NSS["svg"], "g"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "label", "JessyInk Presentation Layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["jessyink"], "presentationLayer", "presentationLayer"); + JessyInkPresentationLayer.setAttribute("id", "jessyink_presentation_layer"); + JessyInkPresentationLayer.style.display = "inherit"; + ROOT_NODE.appendChild(JessyInkPresentationLayer); + + // Gathering all the information about the transitions and effects of the slides, set the background + // from the master slide and substitute the auto-texts. + for (var counter = 0; counter < tempSlides.length; counter++) + { + var originalNode = document.getElementById(tempSlides[counter]); + originalNode.style.display = "none"; + var node = suffixNodeIds(originalNode.cloneNode(true), "_" + counter); + JessyInkPresentationLayer.appendChild(node); + slides[counter] = new Object(); + slides[counter]["original_element"] = originalNode; + slides[counter]["element"] = node; + + // Set build in transition. + slides[counter]["transitionIn"] = new Object(); + + var dict; + + if (node.hasAttributeNS(NSS["jessyink"], "transitionIn")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionIn")); + else + dict = defaultTransitionInDict; + + slides[counter]["transitionIn"]["name"] = dict["name"]; + slides[counter]["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + slides[counter]["transitionOut"] = new Object(); + + if (node.hasAttributeNS(NSS["jessyink"], "transitionOut")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionOut")); + else + dict = defaultTransitionOutDict; + + slides[counter]["transitionOut"]["name"] = dict["name"]; + slides[counter]["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + counter); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + node.insertBefore(clonedNode, node.firstChild); + } + + // Setting clip path. + node.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + + // Substitute auto texts. + substituteAutoTexts(node, node.getAttributeNS(NSS["inkscape"], "label"), counter + 1, tempSlides.length); + + node.removeAttributeNS(NSS["inkscape"], "groupmode"); + node.removeAttributeNS(NSS["inkscape"], "label"); + + // Set effects. + var tempEffects = new Array(); + var groups = new Object(); + + for (var IOCounter = 0; IOCounter <= 1; IOCounter++) + { + var propName = ""; + var dir = 0; + + if (IOCounter == 0) + { + propName = "effectIn"; + dir = 1; + } + else if (IOCounter == 1) + { + propName = "effectOut"; + dir = -1; + } + + var effects = getElementsByPropertyNS(node, NSS["jessyink"], propName); + + for (var effectCounter = 0; effectCounter < effects.length; effectCounter++) + { + var element = document.getElementById(effects[effectCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], propName)); + + // Put every element that has an effect associated with it, into its own group. + // Unless of course, we already put it into its own group. + if (!(groups[element.id])) + { + var newGroup = document.createElementNS(NSS["svg"], "g"); + + element.parentNode.insertBefore(newGroup, element); + newGroup.appendChild(element.parentNode.removeChild(element)); + groups[element.id] = newGroup; + } + + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = dir; + effectDict["element"] = groups[element.id]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + if (!tempEffects[dict["order"]]) + tempEffects[dict["order"]] = new Array(); + + tempEffects[dict["order"]][tempEffects[dict["order"]].length] = effectDict; + } + } + + // Make invisible, but keep in rendering tree to ensure that bounding box can be calculated. + node.setAttribute("opacity",0); + node.style.display = "inherit"; + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (node.firstChild) + transformGroup.appendChild(node.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (node.getAttribute("transform")) + { + transformGroup.setAttribute("transform", node.getAttribute("transform")); + node.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + slides[counter]["viewGroup"] = node.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + counter); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + slides[counter]["viewGroup"].insertBefore(rectNode, slides[counter]["viewGroup"].firstChild); + } + + // Set views. + var tempViews = new Array(); + var views = getElementsByPropertyNS(node, NSS["jessyink"], "view"); + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + // Set initial view even if there are no other views. + slides[counter]["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + slides[counter].initialView = matrixOld.toAttribute(); + + for (var viewCounter = 0; viewCounter < views.length; viewCounter++) + { + var element = document.getElementById(views[viewCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], "view")); + + if (dict["order"] == 0) + { + matrixOld = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + slides[counter].initialView = matrixOld.toAttribute(); + } + else + { + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = 1; + effectDict["element"] = slides[counter]["viewGroup"]; + effectDict["order"] = dict["order"]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + effectDict["options"]["matrixNew"] = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + + tempViews[dict["order"]] = effectDict; + } + + // Remove element. + element.parentNode.removeChild(element); + } + + // Consolidate view array and append it to the effect array. + if (tempViews.length > 0) + { + for (var viewCounter = 0; viewCounter < tempViews.length; viewCounter++) + { + if (tempViews[viewCounter]) + { + tempViews[viewCounter]["options"]["matrixOld"] = matrixOld; + matrixOld = tempViews[viewCounter]["options"]["matrixNew"]; + + if (!tempEffects[tempViews[viewCounter]["order"]]) + tempEffects[tempViews[viewCounter]["order"]] = new Array(); + + tempEffects[tempViews[viewCounter]["order"]][tempEffects[tempViews[viewCounter]["order"]].length] = tempViews[viewCounter]; + } + } + } + + // Set consolidated effect array. + if (tempEffects.length > 0) + { + slides[counter]["effects"] = new Array(); + + for (var effectCounter = 0; effectCounter < tempEffects.length; effectCounter++) + { + if (tempEffects[effectCounter]) + slides[counter]["effects"][slides[counter]["effects"].length] = tempEffects[effectCounter]; + } + } + + node.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + + // Set visibility for initial state. + if (counter == activeSlide) + { + node.style.display = "inherit"; + node.setAttribute("opacity",1); + } + else + { + node.style.display = "none"; + node.setAttribute("opacity",0); + } + } + + // Set key handler. + var jessyInkObjects = document.getElementsByTagNameNS(NSS["svg"], "g"); + + for (var counter = 0; counter < jessyInkObjects.length; counter++) + { + var elem = jessyInkObjects[counter]; + + if (elem.getAttributeNS(NSS["jessyink"], "customKeyBindings")) + { + if (elem.getCustomKeyBindings != undefined) + keyCodeDictionary = elem.getCustomKeyBindings(); + + if (elem.getCustomCharBindings != undefined) + charCodeDictionary = elem.getCustomCharBindings(); + } + } + + // Set mouse handler. + var jessyInkMouseHandler = document.getElementsByTagNameNS(NSS["jessyink"], "mousehandler"); + + for (var counter = 0; counter < jessyInkMouseHandler.length; counter++) + { + var elem = jessyInkMouseHandler[counter]; + + if (elem.getMouseHandler != undefined) + { + var tempDict = elem.getMouseHandler(); + + for (mode in tempDict) + { + if (!mouseHandlerDictionary[mode]) + mouseHandlerDictionary[mode] = new Object(); + + for (handler in tempDict[mode]) + mouseHandlerDictionary[mode][handler] = tempDict[mode][handler]; + } + } + } + + // Check effect number. + if ((activeEffect < 0) || (!slides[activeSlide].effects)) + { + activeEffect = 0; + } + else if (activeEffect > slides[activeSlide].effects.length) + { + activeEffect = slides[activeSlide].effects.length; + } + + createProgressBar(JessyInkPresentationLayer); + hideProgressBar(); + setProgressBarValue(activeSlide); + setTimeIndicatorValue(0); + setInterval("updateTimer()", 1000); + setSlideToState(activeSlide, activeEffect); + jessyInkInitialised = true; +} + +/** Function to substitute the auto-texts. + * + * @param node the node + * @param slideName name of the slide the node is on + * @param slideNumber number of the slide the node is on + * @param numberOfSlides number of slides in the presentation + */ +function substituteAutoTexts(node, slideName, slideNumber, numberOfSlides) +{ + var texts = node.getElementsByTagNameNS(NSS["svg"], "tspan"); + + for (var textCounter = 0; textCounter < texts.length; textCounter++) + { + if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideNumber") + texts[textCounter].firstChild.nodeValue = slideNumber; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "numberOfSlides") + texts[textCounter].firstChild.nodeValue = numberOfSlides; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideTitle") + texts[textCounter].firstChild.nodeValue = slideName; + } +} + +/** Convenience function to get an element depending on whether it has a property with a particular name. + * This function emulates some dearly missed XPath functionality. + * + * @param node the node + * @param namespace namespace of the attribute + * @param name attribute name + */ +function getElementsByPropertyNS(node, namespace, name) +{ + var elems = new Array(); + + if (node.getAttributeNS(namespace, name)) + elems.push(node.getAttribute("id")); + + for (var counter = 0; counter < node.childNodes.length; counter++) + { + if (node.childNodes[counter].nodeType == 1) + elems = elems.concat(getElementsByPropertyNS(node.childNodes[counter], namespace, name)); + } + + return elems; +} + +/** Function to dispatch the next effect, if there is none left, change the slide. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function dispatchEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (dir == 1) + { + effectArray = slides[activeSlide]["effects"][activeEffect]; + activeEffect += dir; + } + else if (dir == -1) + { + activeEffect += dir; + effectArray = slides[activeSlide]["effects"][activeEffect]; + } + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to skip effects and directly either put the slide into start or end state or change slides. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function skipEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (slides[activeSlide]["effects"] && (dir == 1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == 1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + processingEffect = false; + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to change between slides. + * + * @param dir direction (1 = forwards, -1 = backwards) + */ +function changeSlide(dir) +{ + processingEffect = true; + effectArray = new Array(); + + effectArray[0] = new Object(); + if (dir == 1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[0]["dir"] = -1; + } + else if (dir == -1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[0]["dir"] = 1; + } + effectArray[0]["element"] = slides[activeSlide]["element"]; + + activeSlide += dir; + setProgressBarValue(activeSlide); + + effectArray[1] = new Object(); + + if (dir == 1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[1]["dir"] = 1; + } + else if (dir == -1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[1]["dir"] = -1; + } + + effectArray[1]["element"] = slides[activeSlide]["element"]; + + if (slides[activeSlide]["effects"] && (dir == -1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == -1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); +} + +/** Function to toggle between index and slide mode. +*/ +function toggleSlideIndex() +{ + var suspendHandle = ROOT_NODE.suspendRedraw(500); + + if (currentMode == SLIDE_MODE) + { + hideProgressBar(); + INDEX_OFFSET = -1; + indexSetPageSlide(activeSlide); + currentMode = INDEX_MODE; + } + else if (currentMode == INDEX_MODE) + { + for (var counter = 0; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("transform","scale(1)"); + + if (counter == activeSlide) + { + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",1); + activeEffect = 0; + } + else + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + } + currentMode = SLIDE_MODE; + setSlideToState(activeSlide, STATE_START); + setProgressBarValue(activeSlide); + + if (progress_bar_visible) + { + showProgressBar(); + } + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to run an effect. + * + * @param dir direction in which to play the effect (1 = forwards, -1 = backwards) + */ +function effect(dir) +{ + var done = true; + + var suspendHandle = ROOT_NODE.suspendRedraw(200); + + for (var counter = 0; counter < effectArray.length; counter++) + { + if (effectArray[counter]["effect"] == "fade") + done &= fade(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "appear") + done &= appear(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "pop") + done &= pop(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "view") + done &= view(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); + + if (!done) + { + var currentTime = (new Date()).getTime(); + var timeDiff = 1; + + transCounter = currentTime - startTime; + + if (lastFrameTime != null) + { + timeDiff = timeStep - (currentTime - lastFrameTime); + + if (timeDiff <= 0) + timeDiff = 1; + } + + lastFrameTime = currentTime; + + window.setTimeout("effect(" + dir + ")", timeDiff); + } + else + { + window.location.hash = (activeSlide + 1) + '_' + activeEffect; + processingEffect = false; + } +} + +/** Function to display the index sheet. + * + * @param offsetNumber offset number + */ +function displayIndex(offsetNumber) +{ + var offsetX = 0; + var offsetY = 0; + + if (offsetNumber < 0) + offsetNumber = 0; + else if (offsetNumber >= slides.length) + offsetNumber = slides.length - 1; + + for (var counter = 0; counter < slides.length; counter++) + { + if ((counter < offsetNumber) || (counter > offsetNumber + INDEX_COLUMNS * INDEX_COLUMNS - 1)) + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + else + { + offsetX = ((counter - offsetNumber) % INDEX_COLUMNS) * WIDTH; + offsetY = Math.floor((counter - offsetNumber) / INDEX_COLUMNS) * HEIGHT; + + slides[counter]["element"].setAttribute("transform","scale("+1/INDEX_COLUMNS+") translate("+offsetX+","+offsetY+")"); + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",0.5); + } + + setSlideToState(counter, STATE_END); + } + + //do we need to save the current offset? + if (INDEX_OFFSET != offsetNumber) + INDEX_OFFSET = offsetNumber; +} + +/** Function to set the active slide in the slide view. + * + * @param nbr index of the active slide + */ +function slideSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0); + slides[activeSlide]["element"].style.display = "none"; + + activeSlide = parseInt(nbr); + + setSlideToState(activeSlide, STATE_START); + slides[activeSlide]["element"].style.display = "inherit"; + slides[activeSlide]["element"].setAttribute("opacity",1); + + activeEffect = 0; + setProgressBarValue(nbr); +} + +/** Function to set the active slide in the index view. + * + * @param nbr index of the active slide + */ +function indexSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0.5); + + activeSlide = parseInt(nbr); + window.location.hash = (activeSlide + 1) + '_0'; + + slides[activeSlide]["element"].setAttribute("opacity",1); +} + +/** Function to set the page and active slide in index view. + * + * @param nbr index of the active slide + * + * NOTE: To force a redraw, + * set INDEX_OFFSET to -1 before calling indexSetPageSlide(). + * + * This is necessary for zooming (otherwise the index might not + * get redrawn) and when switching to index mode. + * + * INDEX_OFFSET = -1 + * indexSetPageSlide(activeSlide); + */ +function indexSetPageSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + //calculate the offset + var offset = nbr - nbr % (INDEX_COLUMNS * INDEX_COLUMNS); + + if (offset < 0) + offset = 0; + + //if different from kept offset, then record and change the page + if (offset != INDEX_OFFSET) + { + INDEX_OFFSET = offset; + displayIndex(INDEX_OFFSET); + } + + //set the active slide + indexSetActiveSlide(nbr); +} + +/** Event handler for key press. + * + * @param e the event + */ +function keydown(e) +{ + if (!e) + e = window.event; + + code = e.keyCode || e.charCode; + + if (!processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code]) + return keyCodeDictionary[currentMode][code](); + else + document.onkeypress = keypress; +} +// Set event handler for key down. +document.onkeydown = keydown; + +/** Event handler for key press. + * + * @param e the event + */ +function keypress(e) +{ + document.onkeypress = null; + + if (!e) + e = window.event; + + str = String.fromCharCode(e.keyCode || e.charCode); + + if (!processingEffect && charCodeDictionary[currentMode] && charCodeDictionary[currentMode][str]) + return charCodeDictionary[currentMode][str](); +} + +/** Function to supply the default char code dictionary. + * + * @returns default char code dictionary + */ +function getDefaultCharCodeDictionary() +{ + var charCodeDict = new Object(); + + charCodeDict[SLIDE_MODE] = new Object(); + charCodeDict[INDEX_MODE] = new Object(); + charCodeDict[DRAWING_MODE] = new Object(); + + charCodeDict[SLIDE_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[SLIDE_MODE]["d"] = function () { return slideSwitchToDrawingMode(); }; + charCodeDict[SLIDE_MODE]["D"] = function () { return slideQueryDuration(); }; + charCodeDict[SLIDE_MODE]["n"] = function () { return slideAddSlide(activeSlide); }; + charCodeDict[SLIDE_MODE]["p"] = function () { return slideToggleProgressBarVisibility(); }; + charCodeDict[SLIDE_MODE]["t"] = function () { return slideResetTimer(); }; + charCodeDict[SLIDE_MODE]["e"] = function () { return slideUpdateExportLayer(); }; + + charCodeDict[DRAWING_MODE]["d"] = function () { return drawingSwitchToSlideMode(); }; + charCodeDict[DRAWING_MODE]["0"] = function () { return drawingResetPathWidth(); }; + charCodeDict[DRAWING_MODE]["1"] = function () { return drawingSetPathWidth(1.0); }; + charCodeDict[DRAWING_MODE]["3"] = function () { return drawingSetPathWidth(3.0); }; + charCodeDict[DRAWING_MODE]["5"] = function () { return drawingSetPathWidth(5.0); }; + charCodeDict[DRAWING_MODE]["7"] = function () { return drawingSetPathWidth(7.0); }; + charCodeDict[DRAWING_MODE]["9"] = function () { return drawingSetPathWidth(9.0); }; + charCodeDict[DRAWING_MODE]["b"] = function () { return drawingSetPathColour("blue"); }; + charCodeDict[DRAWING_MODE]["c"] = function () { return drawingSetPathColour("cyan"); }; + charCodeDict[DRAWING_MODE]["g"] = function () { return drawingSetPathColour("green"); }; + charCodeDict[DRAWING_MODE]["k"] = function () { return drawingSetPathColour("black"); }; + charCodeDict[DRAWING_MODE]["m"] = function () { return drawingSetPathColour("magenta"); }; + charCodeDict[DRAWING_MODE]["o"] = function () { return drawingSetPathColour("orange"); }; + charCodeDict[DRAWING_MODE]["r"] = function () { return drawingSetPathColour("red"); }; + charCodeDict[DRAWING_MODE]["w"] = function () { return drawingSetPathColour("white"); }; + charCodeDict[DRAWING_MODE]["y"] = function () { return drawingSetPathColour("yellow"); }; + charCodeDict[DRAWING_MODE]["z"] = function () { return drawingUndo(); }; + + charCodeDict[INDEX_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[INDEX_MODE]["-"] = function () { return indexDecreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["="] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["+"] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["0"] = function () { return indexResetNumberOfColumns(); }; + + return charCodeDict; +} + +/** Function to supply the default key code dictionary. + * + * @returns default key code dictionary + */ +function getDefaultKeyCodeDictionary() +{ + var keyCodeDict = new Object(); + + keyCodeDict[SLIDE_MODE] = new Object(); + keyCodeDict[INDEX_MODE] = new Object(); + keyCodeDict[DRAWING_MODE] = new Object(); + + keyCodeDict[SLIDE_MODE][LEFT_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][RIGHT_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][UP_KEY] = function() { return skipEffects(-1); }; + keyCodeDict[SLIDE_MODE][DOWN_KEY] = function() { return skipEffects(1); }; + keyCodeDict[SLIDE_MODE][PAGE_UP_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][HOME_KEY] = function() { return slideSetActiveSlide(0); }; + keyCodeDict[SLIDE_MODE][END_KEY] = function() { return slideSetActiveSlide(slides.length - 1); }; + keyCodeDict[SLIDE_MODE][SPACE_KEY] = function() { return dispatchEffects(1); }; + + keyCodeDict[INDEX_MODE][LEFT_KEY] = function() { return indexSetPageSlide(activeSlide - 1); }; + keyCodeDict[INDEX_MODE][RIGHT_KEY] = function() { return indexSetPageSlide(activeSlide + 1); }; + keyCodeDict[INDEX_MODE][UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][HOME_KEY] = function() { return indexSetPageSlide(0); }; + keyCodeDict[INDEX_MODE][END_KEY] = function() { return indexSetPageSlide(slides.length - 1); }; + keyCodeDict[INDEX_MODE][ENTER_KEY] = function() { return toggleSlideIndex(); }; + + keyCodeDict[DRAWING_MODE][ESCAPE_KEY] = function () { return drawingSwitchToSlideMode(); }; + + return keyCodeDict; +} + +/** Function to handle all mouse events. + * + * @param evnt event + * @param action type of event (e.g. mouse up, mouse wheel) + */ +function mouseHandlerDispatch(evnt, action) +{ + if (!evnt) + evnt = window.event; + + var retVal = true; + + if (!processingEffect && mouseHandlerDictionary[currentMode] && mouseHandlerDictionary[currentMode][action]) + { + var subRetVal = mouseHandlerDictionary[currentMode][action](evnt); + + if (subRetVal != null && subRetVal != undefined) + retVal = subRetVal; + } + + if (evnt.preventDefault && !retVal) + evnt.preventDefault(); + + evnt.returnValue = retVal; + + return retVal; +} + +// Set mouse event handler. +document.onmousedown = function(e) { return mouseHandlerDispatch(e, MOUSE_DOWN); }; +document.onmouseup = function(e) { return mouseHandlerDispatch(e, MOUSE_UP); }; +document.onmousemove = function(e) { return mouseHandlerDispatch(e, MOUSE_MOVE); }; + +// Moz +if (window.addEventListener) +{ + window.addEventListener('DOMMouseScroll', function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }, false); +} + +// Opera Safari OK - may not work in IE +window.onmousewheel = function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }; + +/** Function to supply the default mouse handler dictionary. + * + * @returns default mouse handler dictionary + */ +function getDefaultMouseHandlerDictionary() +{ + var mouseHandlerDict = new Object(); + + mouseHandlerDict[SLIDE_MODE] = new Object(); + mouseHandlerDict[INDEX_MODE] = new Object(); + mouseHandlerDict[DRAWING_MODE] = new Object(); + + mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN] = function(evnt) { return dispatchEffects(1); }; + mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL] = function(evnt) { return slideMousewheel(evnt); }; + + mouseHandlerDict[INDEX_MODE][MOUSE_DOWN] = function(evnt) { return toggleSlideIndex(); }; + + mouseHandlerDict[DRAWING_MODE][MOUSE_DOWN] = function(evnt) { return drawingMousedown(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_UP] = function(evnt) { return drawingMouseup(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_MOVE] = function(evnt) { return drawingMousemove(evnt); }; + + return mouseHandlerDict; +} + +/** Function to switch from slide mode to drawing mode. +*/ +function slideSwitchToDrawingMode() +{ + currentMode = DRAWING_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "crosshair"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to switch from drawing mode to slide mode. +*/ +function drawingSwitchToSlideMode() +{ + currentMode = SLIDE_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "auto"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to decrease the number of columns in index mode. +*/ +function indexDecreaseNumberOfColumns() +{ + if (INDEX_COLUMNS >= 3) + { + INDEX_COLUMNS -= 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to increase the number of columns in index mode. +*/ +function indexIncreaseNumberOfColumns() +{ + if (INDEX_COLUMNS < 7) + { + INDEX_COLUMNS += 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset the number of columns in index mode. +*/ +function indexResetNumberOfColumns() +{ + if (INDEX_COLUMNS != INDEX_COLUMNS_DEFAULT) + { + INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset path width in drawing mode. +*/ +function drawingResetPathWidth() +{ + path_width = path_width_default; + set_path_paint_width(); +} + +/** Function to set path width in drawing mode. + * + * @param width new path width + */ +function drawingSetPathWidth(width) +{ + path_width = width; + set_path_paint_width(); +} + +/** Function to set path colour in drawing mode. + * + * @param colour new path colour + */ +function drawingSetPathColour(colour) +{ + path_colour = colour; +} + +/** Function to query the duration of the presentation from the user in slide mode. +*/ +function slideQueryDuration() +{ + var new_duration = prompt("Length of presentation in minutes?", timer_duration); + + if ((new_duration != null) && (new_duration != '')) + { + timer_duration = new_duration; + } + + updateTimer(); +} + +/** Function to add new slide in slide mode. + * + * @param afterSlide after which slide to insert the new one + */ +function slideAddSlide(afterSlide) +{ + addSlide(afterSlide); + slideSetActiveSlide(afterSlide + 1); + updateTimer(); +} + +/** Function to toggle the visibility of the progress bar in slide mode. +*/ +function slideToggleProgressBarVisibility() +{ + if (progress_bar_visible) + { + progress_bar_visible = false; + hideProgressBar(); + } + else + { + progress_bar_visible = true; + showProgressBar(); + } +} + +/** Function to reset the timer in slide mode. +*/ +function slideResetTimer() +{ + timer_start = timer_elapsed; + updateTimer(); +} + +/** Convenience function to pad a string with zero in front up to a certain length. + */ +function padString(str, len) +{ + var outStr = str; + + while (outStr.length < len) + { + outStr = '0' + outStr; + } + + return outStr; +} + +/** Function to update the export layer. + */ +function slideUpdateExportLayer() +{ + // Suspend redraw since we are going to mess with the slides. + var suspendHandle = ROOT_NODE.suspendRedraw(2000); + + var tmpActiveSlide = activeSlide; + var tmpActiveEffect = activeEffect; + var exportedLayers = new Array(); + + for (var counterSlides = 0; counterSlides < slides.length; counterSlides++) + { + var exportNode; + + setSlideToState(counterSlides, STATE_START); + + var maxEffect = 0; + + if (slides[counterSlides].effects) + { + maxEffect = slides[counterSlides].effects.length; + } + + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString("0", maxEffect.toString().length)); + + exportedLayers.push(exportNode); + + if (slides[counterSlides]["effects"]) + { + for (var counter = 0; counter < slides[counterSlides]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[counterSlides]["effects"][counter].length; subCounter++) + { + var effect = slides[counterSlides]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + } + + var layerName = "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString((counter + 1).toString(), maxEffect.toString().length); + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", layerName); + exportNode.setAttribute("id", layerName); + + exportedLayers.push(exportNode); + } + } + } + + activeSlide = tmpActiveSlide; + activeEffect = tmpActiveEffect; + setSlideToState(activeSlide, activeEffect); + + // Copy image. + var newDoc = document.documentElement.cloneNode(true); + + // Delete viewbox form new imag and set width and height. + newDoc.removeAttribute('viewbox'); + newDoc.setAttribute('width', WIDTH); + newDoc.setAttribute('height', HEIGHT); + + // Delete all layers and script elements. + var nodesToBeRemoved = new Array(); + + for (var childCounter = 0; childCounter < newDoc.childNodes.length; childCounter++) + { + var child = newDoc.childNodes[childCounter]; + + if (child.nodeType == 1) + { + if ((child.nodeName.toUpperCase() == 'G') || (child.nodeName.toUpperCase() == 'SCRIPT')) + { + nodesToBeRemoved.push(child); + } + } + } + + for (var ndCounter = 0; ndCounter < nodesToBeRemoved.length; ndCounter++) + { + var nd = nodesToBeRemoved[ndCounter]; + + // Before removing the node, check whether it contains any definitions. + var defs = nd.getElementsByTagNameNS(NSS["svg"], "defs"); + + for (var defsCounter = 0; defsCounter < defs.length; defsCounter++) + { + if (defs[defsCounter].id) + { + newDoc.appendChild(defs[defsCounter].cloneNode(true)); + } + } + + // Remove node. + nd.parentNode.removeChild(nd); + } + + // Set current layer. + if (exportedLayers[0]) + { + var namedView; + + for (var nodeCounter = 0; nodeCounter < newDoc.childNodes.length; nodeCounter++) + { + if ((newDoc.childNodes[nodeCounter].nodeType == 1) && (newDoc.childNodes[nodeCounter].getAttribute('id') == 'base')) + { + namedView = newDoc.childNodes[nodeCounter]; + } + } + + if (namedView) + { + namedView.setAttributeNS(NSS['inkscape'], 'current-layer', exportedLayers[0].getAttributeNS(NSS['inkscape'], 'label')); + } + } + + // Add exported layers. + while (exportedLayers.length > 0) + { + var nd = exportedLayers.pop(); + + nd.setAttribute("opacity",1); + nd.style.display = "inherit"; + + newDoc.appendChild(nd); + } + + // Serialise the new document. + window.location = 'data:application/svg+xml;base64;charset=utf-8,' + window.btoa(unescape(encodeURIComponent((new XMLSerializer()).serializeToString(newDoc)))); + + // Unsuspend redraw. + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to undo last drawing operation. +*/ +function drawingUndo() +{ + mouse_presentation_path = null; + mouse_original_path = null; + + if (history_presentation_elements.length > 0) + { + var p = history_presentation_elements.pop(); + var parent = p.parentNode.removeChild(p); + + p = history_original_elements.pop(); + parent = p.parentNode.removeChild(p); + } +} + +/** Event handler for mouse down in drawing mode. + * + * @param e the event + */ +function drawingMousedown(e) +{ + var value = 0; + + if (e.button) + value = e.button; + else if (e.which) + value = e.which; + + if (value == 1) + { + history_counter++; + + var p = calcCoord(e); + + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + mouse_original_path = document.createElementNS(NSS["svg"], "path"); + mouse_original_path.setAttribute("stroke", path_colour); + mouse_original_path.setAttribute("stroke-width", path_paint_width); + mouse_original_path.setAttribute("fill", "none"); + mouse_original_path.setAttribute("id", "path " + Date()); + mouse_original_path.setAttribute("d", "M" + p.x + "," + p.y); + slides[activeSlide]["original_element"].appendChild(mouse_original_path); + history_original_elements.push(mouse_original_path); + + mouse_presentation_path = document.createElementNS(NSS["svg"], "path"); + mouse_presentation_path.setAttribute("stroke", path_colour); + mouse_presentation_path.setAttribute("stroke-width", path_paint_width); + mouse_presentation_path.setAttribute("fill", "none"); + mouse_presentation_path.setAttribute("id", "path " + Date() + " presentation copy"); + mouse_presentation_path.setAttribute("d", "M" + p.x + "," + p.y); + + if (slides[activeSlide]["viewGroup"]) + slides[activeSlide]["viewGroup"].appendChild(mouse_presentation_path); + else + slides[activeSlide]["element"].appendChild(mouse_presentation_path); + + history_presentation_elements.push(mouse_presentation_path); + + return false; + } + + return true; +} + +/** Event handler for mouse up in drawing mode. + * + * @param e the event + */ +function drawingMouseup(e) +{ + if(!e) + e = window.event; + + if (mouse_presentation_path != null) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_presentation_path = null; + mouse_original_path.setAttribute("d", d); + mouse_original_path = null; + + return false; + } + + return true; +} + +/** Event handler for mouse move in drawing mode. + * + * @param e the event + */ +function drawingMousemove(e) +{ + if(!e) + e = window.event; + + var dist = (mouse_last_x - e.clientX) * (mouse_last_x - e.clientX) + (mouse_last_y - e.clientY) * (mouse_last_y - e.clientY); + + if (mouse_presentation_path == null) + { + return true; + } + + if (dist >= mouse_min_dist_sqr) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_original_path.setAttribute("d", d); + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + } + + return false; +} + +/** Event handler for mouse wheel events in slide mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function slideMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + skipEffects(-1); + else if (delta < 0) + skipEffects(1); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Event handler for mouse wheel events in index mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function indexMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); + else if (delta < 0) + indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Function to set the path paint width. +*/ +function set_path_paint_width() +{ + var svgPoint1 = document.documentElement.createSVGPoint(); + var svgPoint2 = document.documentElement.createSVGPoint(); + + svgPoint1.x = 0.0; + svgPoint1.y = 0.0; + svgPoint2.x = 1.0; + svgPoint2.y = 0.0; + + var matrix = slides[activeSlide]["element"].getTransformToElement(ROOT_NODE); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getTransformToElement(ROOT_NODE); + + svgPoint1 = svgPoint1.matrixTransform(matrix); + svgPoint2 = svgPoint2.matrixTransform(matrix); + + path_paint_width = path_width / Math.sqrt((svgPoint2.x - svgPoint1.x) * (svgPoint2.x - svgPoint1.x) + (svgPoint2.y - svgPoint1.y) * (svgPoint2.y - svgPoint1.y)); +} + +/** The view effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect); for the view effect the options need to contain the old and the new matrix. + */ +function view(dir, element, time, options) +{ + var length = 250; + var fraction; + + if (!options["matrixInitial"]) + { + var tempString = slides[activeSlide]["viewGroup"].getAttribute("transform"); + + if (tempString) + options["matrixInitial"] = (new matrixSVG()).fromAttribute(tempString); + else + options["matrixInitial"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0); + } + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixNew"].toAttribute()); + + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixNew"], fraction).toAttribute()); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixOld"].toAttribute()); + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixOld"], fraction).toAttribute()); + } + } + + return false; +} + +/** The fade effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function fade(dir, element, time, options) +{ + var length = 250; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.style.display = "none"; + element.setAttribute("opacity", 0); + } + else if (fraction >= 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", fraction); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.style.display = "none"; + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1 - fraction); + } + } + return false; +} + +/** The appear effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function appear(dir, element, time, options) +{ + if (dir == 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity",1); + } + else if (dir == -1) + { + element.style.display = "none"; + element.setAttribute("opacity",0); + } + return true; +} + +/** The pop effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function pop(dir, element, time, options) +{ + var length = 500; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 0); + element.setAttribute("transform", "scale(0)"); + element.style.display = "none"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 1); + element.removeAttribute("transform"); + element.style.display = "inherit"; + return true; + } + else + { + element.style.display = "inherit"; + var opacityFraction = fraction * 3; + if (opacityFraction > 1) + opacityFraction = 1; + element.setAttribute("opacity", opacityFraction); + var offsetX = WIDTH * (1.0 - fraction) / 2.0; + var offsetY = HEIGHT * (1.0 - fraction) / 2.0; + element.setAttribute("transform", "translate(" + offsetX + "," + offsetY + ") scale(" + fraction + ")"); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 1); + element.setAttribute("transform", "scale(1)"); + element.style.display = "inherit"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.removeAttribute("transform"); + element.style.display = "none"; + return true; + } + else + { + element.setAttribute("opacity", 1 - fraction); + element.setAttribute("transform", "scale(" + 1 - fraction + ")"); + element.style.display = "inherit"; + } + } + return false; +} + +/** Function to set a slide either to the start or the end state. + * + * @param slide the slide to use + * @param state the state into which the slide should be set + */ +function setSlideToState(slide, state) +{ + slides[slide]["viewGroup"].setAttribute("transform", slides[slide].initialView); + + if (slides[slide]["effects"]) + { + if (state == STATE_END) + { + for (var counter = 0; counter < slides[slide]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + else if (state == STATE_START) + { + for (var counter = slides[slide]["effects"].length - 1; counter >= 0; counter--) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + } + } + } + else + { + setSlideToState(slide, STATE_START); + + for (var counter = 0; counter < slides[slide]["effects"].length && counter < state; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + } + + window.location.hash = (activeSlide + 1) + '_' + activeEffect; +} + +/** Convenience function to translate a attribute string into a dictionary. + * + * @param str the attribute string + * @return a dictionary + * @see dictToPropStr + */ +function propStrToDict(str) +{ + var list = str.split(";"); + var obj = new Object(); + + for (var counter = 0; counter < list.length; counter++) + { + var subStr = list[counter]; + var subList = subStr.split(":"); + if (subList.length == 2) + { + obj[subList[0]] = subList[1]; + } + } + + return obj; +} + +/** Convenience function to translate a dictionary into a string that can be used as an attribute. + * + * @param dict the dictionary to convert + * @return a string that can be used as an attribute + * @see propStrToDict + */ +function dictToPropStr(dict) +{ + var str = ""; + + for (var key in dict) + { + str += key + ":" + dict[key] + ";"; + } + + return str; +} + +/** Sub-function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @param replace dictionary of replaced ids + * @see suffixNodeIds + */ +function suffixNoneIds_sub(node, suffix, replace) +{ + if (node.nodeType == 1) + { + if (node.getAttribute("id")) + { + var id = node.getAttribute("id") + replace["#" + id] = id + suffix; + node.setAttribute("id", id + suffix); + } + + if ((node.nodeName == "use") && (node.getAttributeNS(NSS["xlink"], "href")) && (replace[node.getAttribute(NSS["xlink"], "href")])) + node.setAttribute(NSS["xlink"], "href", node.getAttribute(NSS["xlink"], "href") + suffix); + + if (node.childNodes) + { + for (var counter = 0; counter < node.childNodes.length; counter++) + suffixNoneIds_sub(node.childNodes[counter], suffix, replace); + } + } +} + +/** Function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @return the changed node + * @see suffixNodeIds_sub + */ +function suffixNodeIds(node, suffix) +{ + var replace = new Object(); + + suffixNoneIds_sub(node, suffix, replace); + + return node; +} + +/** Function to build a progress bar. + * + * @param parent node to attach the progress bar to + */ +function createProgressBar(parent_node) +{ + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "layer_progress_bar"); + g.setAttribute("style", "display: none;"); + + var rect_progress_bar = document.createElementNS(NSS["svg"], "rect"); + rect_progress_bar.setAttribute("style", "marker: none; fill: rgb(128, 128, 128); stroke: none;"); + rect_progress_bar.setAttribute("id", "rect_progress_bar"); + rect_progress_bar.setAttribute("x", 0); + rect_progress_bar.setAttribute("y", 0.99 * HEIGHT); + rect_progress_bar.setAttribute("width", 0); + rect_progress_bar.setAttribute("height", 0.01 * HEIGHT); + g.appendChild(rect_progress_bar); + + var circle_timer_indicator = document.createElementNS(NSS["svg"], "circle"); + circle_timer_indicator.setAttribute("style", "marker: none; fill: rgb(255, 0, 0); stroke: none;"); + circle_timer_indicator.setAttribute("id", "circle_timer_indicator"); + circle_timer_indicator.setAttribute("cx", 0.005 * HEIGHT); + circle_timer_indicator.setAttribute("cy", 0.995 * HEIGHT); + circle_timer_indicator.setAttribute("r", 0.005 * HEIGHT); + g.appendChild(circle_timer_indicator); + + parent_node.appendChild(g); +} + +/** Function to hide the progress bar. + * + */ +function hideProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: none;"); +} + +/** Function to show the progress bar. + * + */ +function showProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: inherit;"); +} + +/** Set progress bar value. + * + * @param value the current slide number + * + */ +function setProgressBarValue(value) +{ + var rect_progress_bar = document.getElementById("rect_progress_bar"); + + if (!rect_progress_bar) + { + return; + } + + if (value < 1) + { + // First slide, assumed to be the title of the presentation + var x = 0; + var w = 0.01 * HEIGHT; + } + else if (value >= slides.length - 1) + { + // Last slide, assumed to be the end of the presentation + var x = WIDTH - 0.01 * HEIGHT; + var w = 0.01 * HEIGHT; + } + else + { + value -= 1; + value /= (slides.length - 2); + + var x = WIDTH * value; + var w = WIDTH / (slides.length - 2); + } + + rect_progress_bar.setAttribute("x", x); + rect_progress_bar.setAttribute("width", w); +} + +/** Set time indicator. + * + * @param value the percentage of time elapse so far between 0.0 and 1.0 + * + */ +function setTimeIndicatorValue(value) +{ + var circle_timer_indicator = document.getElementById("circle_timer_indicator"); + + if (!circle_timer_indicator) + { + return; + } + + if (value < 0.0) + { + value = 0.0; + } + + if (value > 1.0) + { + value = 1.0; + } + + var cx = (WIDTH - 0.01 * HEIGHT) * value + 0.005 * HEIGHT; + circle_timer_indicator.setAttribute("cx", cx); +} + +/** Update timer. + * + */ +function updateTimer() +{ + timer_elapsed += 1; + setTimeIndicatorValue((timer_elapsed - timer_start) / (60 * timer_duration)); +} + +/** Convert screen coordinates to document coordinates. + * + * @param e event with screen coordinates + * + * @return coordinates in SVG file coordinate system + */ +function calcCoord(e) +{ + var svgPoint = document.documentElement.createSVGPoint(); + svgPoint.x = e.clientX + window.pageXOffset; + svgPoint.y = e.clientY + window.pageYOffset; + + var matrix = slides[activeSlide]["element"].getScreenCTM(); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getScreenCTM(); + + svgPoint = svgPoint.matrixTransform(matrix.inverse()); + return svgPoint; +} + +/** Add slide. + * + * @param after_slide after which slide the new slide should be inserted into the presentation + */ +function addSlide(after_slide) +{ + number_of_added_slides++; + + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date() + " presentation copy"); + g.setAttribute("style", "display: none;"); + + var new_slide = new Object(); + new_slide["element"] = g; + + // Set build in transition. + new_slide["transitionIn"] = new Object(); + var dict = defaultTransitionInDict; + new_slide["transitionIn"]["name"] = dict["name"]; + new_slide["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + new_slide["transitionOut"] = new Object(); + dict = defaultTransitionOutDict; + new_slide["transitionOut"]["name"] = dict["name"]; + new_slide["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + Date() + " presentation_copy"); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + g.appendChild(clonedNode); + } + + // Substitute auto texts. + substituteAutoTexts(g, "Whiteboard " + number_of_added_slides, "W" + number_of_added_slides, slides.length); + + g.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + (after_slide + 1) + ")) { indexSetActiveSlide(" + (after_slide + 1) + "); };"); + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (g.firstChild) + transformGroup.appendChild(g.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (g.getAttribute("transform")) + { + transformGroup.setAttribute("transform", g.getAttribute("transform")); + g.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + new_slide["viewGroup"] = g.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + Date()); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + new_slide["viewGroup"].insertBefore(rectNode, new_slide["viewGroup"].firstChild); + } + + // Set initial view even if there are no other views. + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + new_slide["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + new_slide.initialView = matrixOld.toAttribute(); + + // Insert slide + var node = slides[after_slide]["element"]; + var next_node = node.nextSibling; + var parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + g = document.createElementNS(NSS["svg"], "g"); + g.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + g.setAttributeNS(NSS["inkscape"], "label", "Whiteboard " + number_of_added_slides); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date()); + g.setAttribute("style", "display: none;"); + + new_slide["original_element"] = g; + + node = slides[after_slide]["original_element"]; + next_node = node.nextSibling; + parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + before_new_slide = slides.slice(0, after_slide + 1); + after_new_slide = slides.slice(after_slide + 1); + slides = before_new_slide.concat(new_slide, after_new_slide); + + //resetting the counter attributes on the slides that follow the new slide... + for (var counter = after_slide+2; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + } +} + +/** Convenience function to obtain a transformation matrix from a point matrix. + * + * @param mPoints Point matrix. + * @return A transformation matrix. + */ +function pointMatrixToTransformation(mPoints) +{ + mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1); + + return mPointsOld.mult(mPoints.inv()); +} + +/** Convenience function to obtain a matrix with three corners of a rectangle. + * + * @param rect an svg rectangle + * @return a matrixSVG containing three corners of the rectangle + */ +function rectToMatrix(rect) +{ + rectWidth = rect.getBBox().width; + rectHeight = rect.getBBox().height; + rectX = rect.getBBox().x; + rectY = rect.getBBox().y; + rectXcorr = 0; + rectYcorr = 0; + + scaleX = WIDTH / rectWidth; + scaleY = HEIGHT / rectHeight; + + if (scaleX > scaleY) + { + scaleX = scaleY; + rectXcorr -= (WIDTH / scaleX - rectWidth) / 2; + rectWidth = WIDTH / scaleX; + } + else + { + scaleY = scaleX; + rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2; + rectHeight = HEIGHT / scaleY; + } + + if (rect.transform.baseVal.numberOfItems < 1) + { + mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix); + } + + newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1); + newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0); + + return mRectTrans.mult(newBasePoints.add(newVectors)); +} + +/** Function to handle JessyInk elements. + * + * @param node Element node. + */ +function handleElement(node) +{ + if (node.getAttributeNS(NSS['jessyink'], 'element') == 'core.video') + { + var url; + var width; + var height; + var x; + var y; + var transform; + + var tspans = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "tspan"); + + for (var tspanCounter = 0; tspanCounter < tspans.length; tspanCounter++) + { + if (tspans[tspanCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "url") + { + url = tspans[tspanCounter].firstChild.nodeValue; + } + } + + var rects = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "rect"); + + for (var rectCounter = 0; rectCounter < rects.length; rectCounter++) + { + if (rects[rectCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "rect") + { + x = rects[rectCounter].getAttribute("x"); + y = rects[rectCounter].getAttribute("y"); + width = rects[rectCounter].getAttribute("width"); + height = rects[rectCounter].getAttribute("height"); + transform = rects[rectCounter].getAttribute("transform"); + } + } + + for (var childCounter = 0; childCounter < node.childNodes.length; childCounter++) + { + if (node.childNodes[childCounter].nodeType == 1) + { + if (node.childNodes[childCounter].style) + { + node.childNodes[childCounter].style.display = 'none'; + } + else + { + node.childNodes[childCounter].setAttribute("style", "display: none;"); + } + } + } + + var foreignNode = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"); + foreignNode.setAttribute("x", x); + foreignNode.setAttribute("y", y); + foreignNode.setAttribute("width", width); + foreignNode.setAttribute("height", height); + foreignNode.setAttribute("transform", transform); + + var videoNode = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); + videoNode.setAttribute("src", url); + + foreignNode.appendChild(videoNode); + node.appendChild(foreignNode); + } +} + +/** Class processing the location hash. + * + * @param str location hash + */ +function LocationHash(str) +{ + this.slideNumber = 0; + this.effectNumber = 0; + + str = str.substr(1, str.length - 1); + + var parts = str.split('_'); + + // Try to extract slide number. + if (parts.length >= 1) + { + try + { + var slideNumber = parseInt(parts[0]); + + if (!isNaN(slideNumber)) + { + this.slideNumber = slideNumber - 1; + } + } + catch (e) + { + } + } + + // Try to extract effect number. + if (parts.length >= 2) + { + try + { + var effectNumber = parseInt(parts[1]); + + if (!isNaN(effectNumber)) + { + this.effectNumber = effectNumber; + } + } + catch (e) + { + } + } +} + +/** Class representing an svg matrix. +*/ +function matrixSVG() +{ + this.e11 = 0; // a + this.e12 = 0; // c + this.e13 = 0; // e + this.e21 = 0; // b + this.e22 = 0; // d + this.e23 = 0; // f + this.e31 = 0; + this.e32 = 0; + this.e33 = 0; +} + +/** Constructor function. + * + * @param a element a (i.e. 1, 1) as described in the svg standard. + * @param b element b (i.e. 2, 1) as described in the svg standard. + * @param c element c (i.e. 1, 2) as described in the svg standard. + * @param d element d (i.e. 2, 2) as described in the svg standard. + * @param e element e (i.e. 1, 3) as described in the svg standard. + * @param f element f (i.e. 2, 3) as described in the svg standard. + */ +matrixSVG.prototype.fromSVGElements = function(a, b, c, d, e, f) +{ + this.e11 = a; + this.e12 = c; + this.e13 = e; + this.e21 = b; + this.e22 = d; + this.e23 = f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param matrix an svg matrix as described in the svg standard. + */ +matrixSVG.prototype.fromSVGMatrix = function(m) +{ + this.e11 = m.a; + this.e12 = m.c; + this.e13 = m.e; + this.e21 = m.b; + this.e22 = m.d; + this.e23 = m.f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param e11 element 1, 1 of the matrix. + * @param e12 element 1, 2 of the matrix. + * @param e13 element 1, 3 of the matrix. + * @param e21 element 2, 1 of the matrix. + * @param e22 element 2, 2 of the matrix. + * @param e23 element 2, 3 of the matrix. + * @param e31 element 3, 1 of the matrix. + * @param e32 element 3, 2 of the matrix. + * @param e33 element 3, 3 of the matrix. + */ +matrixSVG.prototype.fromElements = function(e11, e12, e13, e21, e22, e23, e31, e32, e33) +{ + this.e11 = e11; + this.e12 = e12; + this.e13 = e13; + this.e21 = e21; + this.e22 = e22; + this.e23 = e23; + this.e31 = e31; + this.e32 = e32; + this.e33 = e33; + + return this; +} + +/** Constructor function. + * + * @param attrString string value of the "transform" attribute (currently only "matrix" is accepted) + */ +matrixSVG.prototype.fromAttribute = function(attrString) +{ + str = attrString.substr(7, attrString.length - 8); + + str = str.trim(); + + strArray = str.split(","); + + // Opera does not use commas to separate the values of the matrix, only spaces. + if (strArray.length != 6) + strArray = str.split(" "); + + this.e11 = parseFloat(strArray[0]); + this.e21 = parseFloat(strArray[1]); + this.e31 = 0; + this.e12 = parseFloat(strArray[2]); + this.e22 = parseFloat(strArray[3]); + this.e32 = 0; + this.e13 = parseFloat(strArray[4]); + this.e23 = parseFloat(strArray[5]); + this.e33 = 1; + + return this; +} + +/** Output function + * + * @return a string that can be used as the "transform" attribute. + */ +matrixSVG.prototype.toAttribute = function() +{ + return "matrix(" + this.e11 + ", " + this.e21 + ", " + this.e12 + ", " + this.e22 + ", " + this.e13 + ", " + this.e23 + ")"; +} + +/** Matrix nversion. + * + * @return the inverse of the matrix + */ +matrixSVG.prototype.inv = function() +{ + out = new matrixSVG(); + + det = this.e11 * (this.e33 * this.e22 - this.e32 * this.e23) - this.e21 * (this.e33 * this.e12 - this.e32 * this.e13) + this.e31 * (this.e23 * this.e12 - this.e22 * this.e13); + + out.e11 = (this.e33 * this.e22 - this.e32 * this.e23) / det; + out.e12 = -(this.e33 * this.e12 - this.e32 * this.e13) / det; + out.e13 = (this.e23 * this.e12 - this.e22 * this.e13) / det; + out.e21 = -(this.e33 * this.e21 - this.e31 * this.e23) / det; + out.e22 = (this.e33 * this.e11 - this.e31 * this.e13) / det; + out.e23 = -(this.e23 * this.e11 - this.e21 * this.e13) / det; + out.e31 = (this.e32 * this.e21 - this.e31 * this.e22) / det; + out.e32 = -(this.e32 * this.e11 - this.e31 * this.e12) / det; + out.e33 = (this.e22 * this.e11 - this.e21 * this.e12) / det; + + return out; +} + +/** Matrix multiplication. + * + * @param op another svg matrix + * @return this * op + */ +matrixSVG.prototype.mult = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 * op.e11 + this.e12 * op.e21 + this.e13 * op.e31; + out.e12 = this.e11 * op.e12 + this.e12 * op.e22 + this.e13 * op.e32; + out.e13 = this.e11 * op.e13 + this.e12 * op.e23 + this.e13 * op.e33; + out.e21 = this.e21 * op.e11 + this.e22 * op.e21 + this.e23 * op.e31; + out.e22 = this.e21 * op.e12 + this.e22 * op.e22 + this.e23 * op.e32; + out.e23 = this.e21 * op.e13 + this.e22 * op.e23 + this.e23 * op.e33; + out.e31 = this.e31 * op.e11 + this.e32 * op.e21 + this.e33 * op.e31; + out.e32 = this.e31 * op.e12 + this.e32 * op.e22 + this.e33 * op.e32; + out.e33 = this.e31 * op.e13 + this.e32 * op.e23 + this.e33 * op.e33; + + return out; +} + +/** Matrix addition. + * + * @param op another svg matrix + * @return this + op + */ +matrixSVG.prototype.add = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 + op.e11; + out.e12 = this.e12 + op.e12; + out.e13 = this.e13 + op.e13; + out.e21 = this.e21 + op.e21; + out.e22 = this.e22 + op.e22; + out.e23 = this.e23 + op.e23; + out.e31 = this.e31 + op.e31; + out.e32 = this.e32 + op.e32; + out.e33 = this.e33 + op.e33; + + return out; +} + +/** Matrix mixing. + * + * @param op another svg matrix + * @parma contribOp contribution of the other matrix (0 <= contribOp <= 1) + * @return (1 - contribOp) * this + contribOp * op + */ +matrixSVG.prototype.mix = function(op, contribOp) +{ + contribThis = 1.0 - contribOp; + out = new matrixSVG(); + + out.e11 = contribThis * this.e11 + contribOp * op.e11; + out.e12 = contribThis * this.e12 + contribOp * op.e12; + out.e13 = contribThis * this.e13 + contribOp * op.e13; + out.e21 = contribThis * this.e21 + contribOp * op.e21; + out.e22 = contribThis * this.e22 + contribOp * op.e22; + out.e23 = contribThis * this.e23 + contribOp * op.e23; + out.e31 = contribThis * this.e31 + contribOp * op.e31; + out.e32 = contribThis * this.e32 + contribOp * op.e32; + out.e33 = contribThis * this.e33 + contribOp * op.e33; + + return out; +} + +/** Trimming function for strings. +*/ +String.prototype.trim = function() +{ + return this.replace(/^\s+|\s+$/g, ''); +} + +/** SVGElement.getTransformToElement polyfill */ +SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) { + return elem.getScreenCTM().inverse().multiply(this.getScreenCTM()); +}; + diff --git a/share/extensions/tests/data/refs/jessyink_install__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/jessyink_install__--id__p1__--id__r3.out new file mode 100644 index 0000000..5a819a7 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_install__--id__p1__--id__r3.out @@ -0,0 +1,2766 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + // Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Set onload event handler. +window.onload = jessyInkInit; + +// Creating a namespace dictionary. The standard Inkscape namespaces are taken from inkex.py. +var NSS = new Object(); +NSS['sodipodi']='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'; +NSS['cc']='http://web.resource.org/cc/'; +NSS['svg']='http://www.w3.org/2000/svg'; +NSS['dc']='http://purl.org/dc/elements/1.1/'; +NSS['rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#'; +NSS['inkscape']='http://www.inkscape.org/namespaces/inkscape'; +NSS['xlink']='http://www.w3.org/1999/xlink'; +NSS['xml']='http://www.w3.org/XML/1998/namespace'; +NSS['jessyink']='https://launchpad.net/jessyink'; + +// Keycodes. +var LEFT_KEY = 37; // cursor left keycode +var UP_KEY = 38; // cursor up keycode +var RIGHT_KEY = 39; // cursor right keycode +var DOWN_KEY = 40; // cursor down keycode +var PAGE_UP_KEY = 33; // page up keycode +var PAGE_DOWN_KEY = 34; // page down keycode +var HOME_KEY = 36; // home keycode +var END_KEY = 35; // end keycode +var ENTER_KEY = 13; // next slide +var SPACE_KEY = 32; +var ESCAPE_KEY = 27; + +// Presentation modes. +var SLIDE_MODE = 1; +var INDEX_MODE = 2; +var DRAWING_MODE = 3; + +// Mouse handler actions. +var MOUSE_UP = 1; +var MOUSE_DOWN = 2; +var MOUSE_MOVE = 3; +var MOUSE_WHEEL = 4; + +// Parameters. +var ROOT_NODE = document.getElementsByTagNameNS(NSS["svg"], "svg")[0]; +var HEIGHT = 0; +var WIDTH = 0; +var INDEX_COLUMNS_DEFAULT = 4; +var INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; +var INDEX_OFFSET = 0; +var STATE_START = -1; +var STATE_END = -2; +var BACKGROUND_COLOR = null; +var slides = new Array(); + +// Initialisation. +var currentMode = SLIDE_MODE; +var masterSlide = null; +var activeSlide = 0; +var activeEffect = 0; +var timeStep = 30; // 40 ms equal 25 frames per second. +var lastFrameTime = null; +var processingEffect = false; +var transCounter = 0; +var effectArray = 0; +var defaultTransitionInDict = new Object(); +defaultTransitionInDict["name"] = "appear"; +var defaultTransitionOutDict = new Object(); +defaultTransitionOutDict["name"] = "appear"; +var jessyInkInitialised = false; + +// Initialise char and key code dictionaries. +var charCodeDictionary = getDefaultCharCodeDictionary(); +var keyCodeDictionary = getDefaultKeyCodeDictionary(); + +// Initialise mouse handler dictionary. +var mouseHandlerDictionary = getDefaultMouseHandlerDictionary(); + +var progress_bar_visible = false; +var timer_elapsed = 0; +var timer_start = timer_elapsed; +var timer_duration = 15; // 15 minutes + +var history_counter = 0; +var history_original_elements = new Array(); +var history_presentation_elements = new Array(); + +var mouse_original_path = null; +var mouse_presentation_path = null; +var mouse_last_x = -1; +var mouse_last_y = -1; +var mouse_min_dist_sqr = 3 * 3; +var path_colour = "red"; +var path_width_default = 3; +var path_width = path_width_default; +var path_paint_width = path_width; + +var number_of_added_slides = 0; + +/** Initialisation function. + * The whole presentation is set-up in this function. + */ +function jessyInkInit() +{ + // Make sure we only execute this code once. Double execution can occur if the onload event handler is set + // in the main svg tag as well (as was recommended in earlier versions). Executing this function twice does + // not lead to any problems, but it takes more time. + if (jessyInkInitialised) + return; + + // Making the presentation scalable. + var VIEWBOX = ROOT_NODE.getAttribute("viewBox"); + + if (VIEWBOX) + { + WIDTH = ROOT_NODE.viewBox.animVal.width; + HEIGHT = ROOT_NODE.viewBox.animVal.height; + } + else + { + HEIGHT = parseFloat(ROOT_NODE.getAttribute("height")); + WIDTH = parseFloat(ROOT_NODE.getAttribute("width")); + ROOT_NODE.setAttribute("viewBox", "0 0 " + WIDTH + " " + HEIGHT); + } + + ROOT_NODE.setAttribute("width", "100%"); + ROOT_NODE.setAttribute("height", "100%"); + + // Setting the background color. + var namedViews = document.getElementsByTagNameNS(NSS["sodipodi"], "namedview"); + + for (var counter = 0; counter < namedViews.length; counter++) + { + if (namedViews[counter].hasAttribute("id") && namedViews[counter].hasAttribute("pagecolor")) + { + if (namedViews[counter].getAttribute("id") == "base") + { + BACKGROUND_COLOR = namedViews[counter].getAttribute("pagecolor"); + var newAttribute = "background-color:" + BACKGROUND_COLOR + ";"; + + if (ROOT_NODE.hasAttribute("style")) + newAttribute += ROOT_NODE.getAttribute("style"); + + ROOT_NODE.setAttribute("style", newAttribute); + } + } + } + + // Defining clip-path. + var defsNodes = document.getElementsByTagNameNS(NSS["svg"], "defs"); + + if (defsNodes.length > 0) + { + var existingClipPath = document.getElementById("jessyInkSlideClipPath"); + + if (!existingClipPath) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + var clipPath = document.createElementNS(NSS["svg"], "clipPath"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + + clipPath.setAttribute("id", "jessyInkSlideClipPath"); + clipPath.setAttribute("clipPathUnits", "userSpaceOnUse"); + + clipPath.appendChild(rectNode); + defsNodes[0].appendChild(clipPath); + } + } + + // Making a list of the slide and finding the master slide. + var nodes = document.getElementsByTagNameNS(NSS["svg"], "g"); + var tempSlides = new Array(); + var existingJessyInkPresentationLayer = null; + + for (var counter = 0; counter < nodes.length; counter++) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") && (nodes[counter].getAttributeNS(NSS["inkscape"], "groupmode") == "layer")) + { + if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "masterSlide") == "masterSlide") + masterSlide = nodes[counter]; + else if (nodes[counter].getAttributeNS(NSS["inkscape"], "label") && nodes[counter].getAttributeNS(NSS["jessyink"], "presentationLayer") == "presentationLayer") + existingJessyInkPresentationLayer = nodes[counter]; + else + tempSlides.push(nodes[counter].getAttribute("id")); + } + else if (nodes[counter].getAttributeNS(NSS['jessyink'], 'element')) + { + handleElement(nodes[counter]); + } + } + + // Hide master slide set default transitions. + if (masterSlide) + { + masterSlide.style.display = "none"; + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionIn")) + defaultTransitionInDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionIn")); + + if (masterSlide.hasAttributeNS(NSS["jessyink"], "transitionOut")) + defaultTransitionOutDict = propStrToDict(masterSlide.getAttributeNS(NSS["jessyink"], "transitionOut")); + } + + if (existingJessyInkPresentationLayer != null) + { + existingJessyInkPresentationLayer.parentNode.removeChild(existingJessyInkPresentationLayer); + } + + // Set start slide. + var hashObj = new LocationHash(window.location.hash); + + activeSlide = hashObj.slideNumber; + activeEffect = hashObj.effectNumber; + + if (activeSlide < 0) + activeSlide = 0; + else if (activeSlide >= tempSlides.length) + activeSlide = tempSlides.length - 1; + + var originalNode = document.getElementById(tempSlides[counter]); + + var JessyInkPresentationLayer = document.createElementNS(NSS["svg"], "g"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["inkscape"], "label", "JessyInk Presentation Layer"); + JessyInkPresentationLayer.setAttributeNS(NSS["jessyink"], "presentationLayer", "presentationLayer"); + JessyInkPresentationLayer.setAttribute("id", "jessyink_presentation_layer"); + JessyInkPresentationLayer.style.display = "inherit"; + ROOT_NODE.appendChild(JessyInkPresentationLayer); + + // Gathering all the information about the transitions and effects of the slides, set the background + // from the master slide and substitute the auto-texts. + for (var counter = 0; counter < tempSlides.length; counter++) + { + var originalNode = document.getElementById(tempSlides[counter]); + originalNode.style.display = "none"; + var node = suffixNodeIds(originalNode.cloneNode(true), "_" + counter); + JessyInkPresentationLayer.appendChild(node); + slides[counter] = new Object(); + slides[counter]["original_element"] = originalNode; + slides[counter]["element"] = node; + + // Set build in transition. + slides[counter]["transitionIn"] = new Object(); + + var dict; + + if (node.hasAttributeNS(NSS["jessyink"], "transitionIn")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionIn")); + else + dict = defaultTransitionInDict; + + slides[counter]["transitionIn"]["name"] = dict["name"]; + slides[counter]["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + slides[counter]["transitionOut"] = new Object(); + + if (node.hasAttributeNS(NSS["jessyink"], "transitionOut")) + dict = propStrToDict(node.getAttributeNS(NSS["jessyink"], "transitionOut")); + else + dict = defaultTransitionOutDict; + + slides[counter]["transitionOut"]["name"] = dict["name"]; + slides[counter]["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + slides[counter]["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + counter); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + node.insertBefore(clonedNode, node.firstChild); + } + + // Setting clip path. + node.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + + // Substitute auto texts. + substituteAutoTexts(node, node.getAttributeNS(NSS["inkscape"], "label"), counter + 1, tempSlides.length); + + node.removeAttributeNS(NSS["inkscape"], "groupmode"); + node.removeAttributeNS(NSS["inkscape"], "label"); + + // Set effects. + var tempEffects = new Array(); + var groups = new Object(); + + for (var IOCounter = 0; IOCounter <= 1; IOCounter++) + { + var propName = ""; + var dir = 0; + + if (IOCounter == 0) + { + propName = "effectIn"; + dir = 1; + } + else if (IOCounter == 1) + { + propName = "effectOut"; + dir = -1; + } + + var effects = getElementsByPropertyNS(node, NSS["jessyink"], propName); + + for (var effectCounter = 0; effectCounter < effects.length; effectCounter++) + { + var element = document.getElementById(effects[effectCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], propName)); + + // Put every element that has an effect associated with it, into its own group. + // Unless of course, we already put it into its own group. + if (!(groups[element.id])) + { + var newGroup = document.createElementNS(NSS["svg"], "g"); + + element.parentNode.insertBefore(newGroup, element); + newGroup.appendChild(element.parentNode.removeChild(element)); + groups[element.id] = newGroup; + } + + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = dir; + effectDict["element"] = groups[element.id]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + if (!tempEffects[dict["order"]]) + tempEffects[dict["order"]] = new Array(); + + tempEffects[dict["order"]][tempEffects[dict["order"]].length] = effectDict; + } + } + + // Make invisible, but keep in rendering tree to ensure that bounding box can be calculated. + node.setAttribute("opacity",0); + node.style.display = "inherit"; + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (node.firstChild) + transformGroup.appendChild(node.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (node.getAttribute("transform")) + { + transformGroup.setAttribute("transform", node.getAttribute("transform")); + node.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + slides[counter]["viewGroup"] = node.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + counter); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + slides[counter]["viewGroup"].insertBefore(rectNode, slides[counter]["viewGroup"].firstChild); + } + + // Set views. + var tempViews = new Array(); + var views = getElementsByPropertyNS(node, NSS["jessyink"], "view"); + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + // Set initial view even if there are no other views. + slides[counter]["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + slides[counter].initialView = matrixOld.toAttribute(); + + for (var viewCounter = 0; viewCounter < views.length; viewCounter++) + { + var element = document.getElementById(views[viewCounter]); + var dict = propStrToDict(element.getAttributeNS(NSS["jessyink"], "view")); + + if (dict["order"] == 0) + { + matrixOld = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + slides[counter].initialView = matrixOld.toAttribute(); + } + else + { + var effectDict = new Object(); + + effectDict["effect"] = dict["name"]; + effectDict["dir"] = 1; + effectDict["element"] = slides[counter]["viewGroup"]; + effectDict["order"] = dict["order"]; + + for (var option in dict) + { + if ((option != "name") && (option != "order")) + { + if (!effectDict["options"]) + effectDict["options"] = new Object(); + + effectDict["options"][option] = dict[option]; + } + } + + effectDict["options"]["matrixNew"] = pointMatrixToTransformation(rectToMatrix(element)).mult((new matrixSVG()).fromSVGMatrix(slides[counter].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(element.parentNode.getScreenCTM())).inv()); + + tempViews[dict["order"]] = effectDict; + } + + // Remove element. + element.parentNode.removeChild(element); + } + + // Consolidate view array and append it to the effect array. + if (tempViews.length > 0) + { + for (var viewCounter = 0; viewCounter < tempViews.length; viewCounter++) + { + if (tempViews[viewCounter]) + { + tempViews[viewCounter]["options"]["matrixOld"] = matrixOld; + matrixOld = tempViews[viewCounter]["options"]["matrixNew"]; + + if (!tempEffects[tempViews[viewCounter]["order"]]) + tempEffects[tempViews[viewCounter]["order"]] = new Array(); + + tempEffects[tempViews[viewCounter]["order"]][tempEffects[tempViews[viewCounter]["order"]].length] = tempViews[viewCounter]; + } + } + } + + // Set consolidated effect array. + if (tempEffects.length > 0) + { + slides[counter]["effects"] = new Array(); + + for (var effectCounter = 0; effectCounter < tempEffects.length; effectCounter++) + { + if (tempEffects[effectCounter]) + slides[counter]["effects"][slides[counter]["effects"].length] = tempEffects[effectCounter]; + } + } + + node.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + + // Set visibility for initial state. + if (counter == activeSlide) + { + node.style.display = "inherit"; + node.setAttribute("opacity",1); + } + else + { + node.style.display = "none"; + node.setAttribute("opacity",0); + } + } + + // Set key handler. + var jessyInkObjects = document.getElementsByTagNameNS(NSS["svg"], "g"); + + for (var counter = 0; counter < jessyInkObjects.length; counter++) + { + var elem = jessyInkObjects[counter]; + + if (elem.getAttributeNS(NSS["jessyink"], "customKeyBindings")) + { + if (elem.getCustomKeyBindings != undefined) + keyCodeDictionary = elem.getCustomKeyBindings(); + + if (elem.getCustomCharBindings != undefined) + charCodeDictionary = elem.getCustomCharBindings(); + } + } + + // Set mouse handler. + var jessyInkMouseHandler = document.getElementsByTagNameNS(NSS["jessyink"], "mousehandler"); + + for (var counter = 0; counter < jessyInkMouseHandler.length; counter++) + { + var elem = jessyInkMouseHandler[counter]; + + if (elem.getMouseHandler != undefined) + { + var tempDict = elem.getMouseHandler(); + + for (mode in tempDict) + { + if (!mouseHandlerDictionary[mode]) + mouseHandlerDictionary[mode] = new Object(); + + for (handler in tempDict[mode]) + mouseHandlerDictionary[mode][handler] = tempDict[mode][handler]; + } + } + } + + // Check effect number. + if ((activeEffect < 0) || (!slides[activeSlide].effects)) + { + activeEffect = 0; + } + else if (activeEffect > slides[activeSlide].effects.length) + { + activeEffect = slides[activeSlide].effects.length; + } + + createProgressBar(JessyInkPresentationLayer); + hideProgressBar(); + setProgressBarValue(activeSlide); + setTimeIndicatorValue(0); + setInterval("updateTimer()", 1000); + setSlideToState(activeSlide, activeEffect); + jessyInkInitialised = true; +} + +/** Function to substitute the auto-texts. + * + * @param node the node + * @param slideName name of the slide the node is on + * @param slideNumber number of the slide the node is on + * @param numberOfSlides number of slides in the presentation + */ +function substituteAutoTexts(node, slideName, slideNumber, numberOfSlides) +{ + var texts = node.getElementsByTagNameNS(NSS["svg"], "tspan"); + + for (var textCounter = 0; textCounter < texts.length; textCounter++) + { + if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideNumber") + texts[textCounter].firstChild.nodeValue = slideNumber; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "numberOfSlides") + texts[textCounter].firstChild.nodeValue = numberOfSlides; + else if (texts[textCounter].getAttributeNS(NSS["jessyink"], "autoText") == "slideTitle") + texts[textCounter].firstChild.nodeValue = slideName; + } +} + +/** Convenience function to get an element depending on whether it has a property with a particular name. + * This function emulates some dearly missed XPath functionality. + * + * @param node the node + * @param namespace namespace of the attribute + * @param name attribute name + */ +function getElementsByPropertyNS(node, namespace, name) +{ + var elems = new Array(); + + if (node.getAttributeNS(namespace, name)) + elems.push(node.getAttribute("id")); + + for (var counter = 0; counter < node.childNodes.length; counter++) + { + if (node.childNodes[counter].nodeType == 1) + elems = elems.concat(getElementsByPropertyNS(node.childNodes[counter], namespace, name)); + } + + return elems; +} + +/** Function to dispatch the next effect, if there is none left, change the slide. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function dispatchEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (dir == 1) + { + effectArray = slides[activeSlide]["effects"][activeEffect]; + activeEffect += dir; + } + else if (dir == -1) + { + activeEffect += dir; + effectArray = slides[activeSlide]["effects"][activeEffect]; + } + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to skip effects and directly either put the slide into start or end state or change slides. + * + * @param dir direction of the change (1 = forwards, -1 = backwards) + */ +function skipEffects(dir) +{ + if (slides[activeSlide]["effects"] && (((dir == 1) && (activeEffect < slides[activeSlide]["effects"].length)) || ((dir == -1) && (activeEffect > 0)))) + { + processingEffect = true; + + if (slides[activeSlide]["effects"] && (dir == 1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == 1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + processingEffect = false; + } + else if (((dir == 1) && (activeSlide < (slides.length - 1))) || (((dir == -1) && (activeSlide > 0)))) + { + changeSlide(dir); + } +} + +/** Function to change between slides. + * + * @param dir direction (1 = forwards, -1 = backwards) + */ +function changeSlide(dir) +{ + processingEffect = true; + effectArray = new Array(); + + effectArray[0] = new Object(); + if (dir == 1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[0]["dir"] = -1; + } + else if (dir == -1) + { + effectArray[0]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[0]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[0]["dir"] = 1; + } + effectArray[0]["element"] = slides[activeSlide]["element"]; + + activeSlide += dir; + setProgressBarValue(activeSlide); + + effectArray[1] = new Object(); + + if (dir == 1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionIn"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionIn"]["options"]; + effectArray[1]["dir"] = 1; + } + else if (dir == -1) + { + effectArray[1]["effect"] = slides[activeSlide]["transitionOut"]["name"]; + effectArray[1]["options"] = slides[activeSlide]["transitionOut"]["options"]; + effectArray[1]["dir"] = -1; + } + + effectArray[1]["element"] = slides[activeSlide]["element"]; + + if (slides[activeSlide]["effects"] && (dir == -1)) + activeEffect = slides[activeSlide]["effects"].length; + else + activeEffect = 0; + + if (dir == -1) + setSlideToState(activeSlide, STATE_END); + else + setSlideToState(activeSlide, STATE_START); + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(dir); +} + +/** Function to toggle between index and slide mode. +*/ +function toggleSlideIndex() +{ + var suspendHandle = ROOT_NODE.suspendRedraw(500); + + if (currentMode == SLIDE_MODE) + { + hideProgressBar(); + INDEX_OFFSET = -1; + indexSetPageSlide(activeSlide); + currentMode = INDEX_MODE; + } + else if (currentMode == INDEX_MODE) + { + for (var counter = 0; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("transform","scale(1)"); + + if (counter == activeSlide) + { + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",1); + activeEffect = 0; + } + else + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + } + currentMode = SLIDE_MODE; + setSlideToState(activeSlide, STATE_START); + setProgressBarValue(activeSlide); + + if (progress_bar_visible) + { + showProgressBar(); + } + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to run an effect. + * + * @param dir direction in which to play the effect (1 = forwards, -1 = backwards) + */ +function effect(dir) +{ + var done = true; + + var suspendHandle = ROOT_NODE.suspendRedraw(200); + + for (var counter = 0; counter < effectArray.length; counter++) + { + if (effectArray[counter]["effect"] == "fade") + done &= fade(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "appear") + done &= appear(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "pop") + done &= pop(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + else if (effectArray[counter]["effect"] == "view") + done &= view(parseInt(effectArray[counter]["dir"]) * dir, effectArray[counter]["element"], transCounter, effectArray[counter]["options"]); + } + + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); + + if (!done) + { + var currentTime = (new Date()).getTime(); + var timeDiff = 1; + + transCounter = currentTime - startTime; + + if (lastFrameTime != null) + { + timeDiff = timeStep - (currentTime - lastFrameTime); + + if (timeDiff <= 0) + timeDiff = 1; + } + + lastFrameTime = currentTime; + + window.setTimeout("effect(" + dir + ")", timeDiff); + } + else + { + window.location.hash = (activeSlide + 1) + '_' + activeEffect; + processingEffect = false; + } +} + +/** Function to display the index sheet. + * + * @param offsetNumber offset number + */ +function displayIndex(offsetNumber) +{ + var offsetX = 0; + var offsetY = 0; + + if (offsetNumber < 0) + offsetNumber = 0; + else if (offsetNumber >= slides.length) + offsetNumber = slides.length - 1; + + for (var counter = 0; counter < slides.length; counter++) + { + if ((counter < offsetNumber) || (counter > offsetNumber + INDEX_COLUMNS * INDEX_COLUMNS - 1)) + { + slides[counter]["element"].setAttribute("opacity",0); + slides[counter]["element"].style.display = "none"; + } + else + { + offsetX = ((counter - offsetNumber) % INDEX_COLUMNS) * WIDTH; + offsetY = Math.floor((counter - offsetNumber) / INDEX_COLUMNS) * HEIGHT; + + slides[counter]["element"].setAttribute("transform","scale("+1/INDEX_COLUMNS+") translate("+offsetX+","+offsetY+")"); + slides[counter]["element"].style.display = "inherit"; + slides[counter]["element"].setAttribute("opacity",0.5); + } + + setSlideToState(counter, STATE_END); + } + + //do we need to save the current offset? + if (INDEX_OFFSET != offsetNumber) + INDEX_OFFSET = offsetNumber; +} + +/** Function to set the active slide in the slide view. + * + * @param nbr index of the active slide + */ +function slideSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0); + slides[activeSlide]["element"].style.display = "none"; + + activeSlide = parseInt(nbr); + + setSlideToState(activeSlide, STATE_START); + slides[activeSlide]["element"].style.display = "inherit"; + slides[activeSlide]["element"].setAttribute("opacity",1); + + activeEffect = 0; + setProgressBarValue(nbr); +} + +/** Function to set the active slide in the index view. + * + * @param nbr index of the active slide + */ +function indexSetActiveSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + slides[activeSlide]["element"].setAttribute("opacity",0.5); + + activeSlide = parseInt(nbr); + window.location.hash = (activeSlide + 1) + '_0'; + + slides[activeSlide]["element"].setAttribute("opacity",1); +} + +/** Function to set the page and active slide in index view. + * + * @param nbr index of the active slide + * + * NOTE: To force a redraw, + * set INDEX_OFFSET to -1 before calling indexSetPageSlide(). + * + * This is necessary for zooming (otherwise the index might not + * get redrawn) and when switching to index mode. + * + * INDEX_OFFSET = -1 + * indexSetPageSlide(activeSlide); + */ +function indexSetPageSlide(nbr) +{ + if (nbr >= slides.length) + nbr = slides.length - 1; + else if (nbr < 0) + nbr = 0; + + //calculate the offset + var offset = nbr - nbr % (INDEX_COLUMNS * INDEX_COLUMNS); + + if (offset < 0) + offset = 0; + + //if different from kept offset, then record and change the page + if (offset != INDEX_OFFSET) + { + INDEX_OFFSET = offset; + displayIndex(INDEX_OFFSET); + } + + //set the active slide + indexSetActiveSlide(nbr); +} + +/** Event handler for key press. + * + * @param e the event + */ +function keydown(e) +{ + if (!e) + e = window.event; + + code = e.keyCode || e.charCode; + + if (!processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code]) + return keyCodeDictionary[currentMode][code](); + else + document.onkeypress = keypress; +} +// Set event handler for key down. +document.onkeydown = keydown; + +/** Event handler for key press. + * + * @param e the event + */ +function keypress(e) +{ + document.onkeypress = null; + + if (!e) + e = window.event; + + str = String.fromCharCode(e.keyCode || e.charCode); + + if (!processingEffect && charCodeDictionary[currentMode] && charCodeDictionary[currentMode][str]) + return charCodeDictionary[currentMode][str](); +} + +/** Function to supply the default char code dictionary. + * + * @returns default char code dictionary + */ +function getDefaultCharCodeDictionary() +{ + var charCodeDict = new Object(); + + charCodeDict[SLIDE_MODE] = new Object(); + charCodeDict[INDEX_MODE] = new Object(); + charCodeDict[DRAWING_MODE] = new Object(); + + charCodeDict[SLIDE_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[SLIDE_MODE]["d"] = function () { return slideSwitchToDrawingMode(); }; + charCodeDict[SLIDE_MODE]["D"] = function () { return slideQueryDuration(); }; + charCodeDict[SLIDE_MODE]["n"] = function () { return slideAddSlide(activeSlide); }; + charCodeDict[SLIDE_MODE]["p"] = function () { return slideToggleProgressBarVisibility(); }; + charCodeDict[SLIDE_MODE]["t"] = function () { return slideResetTimer(); }; + charCodeDict[SLIDE_MODE]["e"] = function () { return slideUpdateExportLayer(); }; + + charCodeDict[DRAWING_MODE]["d"] = function () { return drawingSwitchToSlideMode(); }; + charCodeDict[DRAWING_MODE]["0"] = function () { return drawingResetPathWidth(); }; + charCodeDict[DRAWING_MODE]["1"] = function () { return drawingSetPathWidth(1.0); }; + charCodeDict[DRAWING_MODE]["3"] = function () { return drawingSetPathWidth(3.0); }; + charCodeDict[DRAWING_MODE]["5"] = function () { return drawingSetPathWidth(5.0); }; + charCodeDict[DRAWING_MODE]["7"] = function () { return drawingSetPathWidth(7.0); }; + charCodeDict[DRAWING_MODE]["9"] = function () { return drawingSetPathWidth(9.0); }; + charCodeDict[DRAWING_MODE]["b"] = function () { return drawingSetPathColour("blue"); }; + charCodeDict[DRAWING_MODE]["c"] = function () { return drawingSetPathColour("cyan"); }; + charCodeDict[DRAWING_MODE]["g"] = function () { return drawingSetPathColour("green"); }; + charCodeDict[DRAWING_MODE]["k"] = function () { return drawingSetPathColour("black"); }; + charCodeDict[DRAWING_MODE]["m"] = function () { return drawingSetPathColour("magenta"); }; + charCodeDict[DRAWING_MODE]["o"] = function () { return drawingSetPathColour("orange"); }; + charCodeDict[DRAWING_MODE]["r"] = function () { return drawingSetPathColour("red"); }; + charCodeDict[DRAWING_MODE]["w"] = function () { return drawingSetPathColour("white"); }; + charCodeDict[DRAWING_MODE]["y"] = function () { return drawingSetPathColour("yellow"); }; + charCodeDict[DRAWING_MODE]["z"] = function () { return drawingUndo(); }; + + charCodeDict[INDEX_MODE]["i"] = function () { return toggleSlideIndex(); }; + charCodeDict[INDEX_MODE]["-"] = function () { return indexDecreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["="] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["+"] = function () { return indexIncreaseNumberOfColumns(); }; + charCodeDict[INDEX_MODE]["0"] = function () { return indexResetNumberOfColumns(); }; + + return charCodeDict; +} + +/** Function to supply the default key code dictionary. + * + * @returns default key code dictionary + */ +function getDefaultKeyCodeDictionary() +{ + var keyCodeDict = new Object(); + + keyCodeDict[SLIDE_MODE] = new Object(); + keyCodeDict[INDEX_MODE] = new Object(); + keyCodeDict[DRAWING_MODE] = new Object(); + + keyCodeDict[SLIDE_MODE][LEFT_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][RIGHT_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][UP_KEY] = function() { return skipEffects(-1); }; + keyCodeDict[SLIDE_MODE][DOWN_KEY] = function() { return skipEffects(1); }; + keyCodeDict[SLIDE_MODE][PAGE_UP_KEY] = function() { return dispatchEffects(-1); }; + keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY] = function() { return dispatchEffects(1); }; + keyCodeDict[SLIDE_MODE][HOME_KEY] = function() { return slideSetActiveSlide(0); }; + keyCodeDict[SLIDE_MODE][END_KEY] = function() { return slideSetActiveSlide(slides.length - 1); }; + keyCodeDict[SLIDE_MODE][SPACE_KEY] = function() { return dispatchEffects(1); }; + + keyCodeDict[INDEX_MODE][LEFT_KEY] = function() { return indexSetPageSlide(activeSlide - 1); }; + keyCodeDict[INDEX_MODE][RIGHT_KEY] = function() { return indexSetPageSlide(activeSlide + 1); }; + keyCodeDict[INDEX_MODE][UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_UP_KEY] = function() { return indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][PAGE_DOWN_KEY] = function() { return indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); }; + keyCodeDict[INDEX_MODE][HOME_KEY] = function() { return indexSetPageSlide(0); }; + keyCodeDict[INDEX_MODE][END_KEY] = function() { return indexSetPageSlide(slides.length - 1); }; + keyCodeDict[INDEX_MODE][ENTER_KEY] = function() { return toggleSlideIndex(); }; + + keyCodeDict[DRAWING_MODE][ESCAPE_KEY] = function () { return drawingSwitchToSlideMode(); }; + + return keyCodeDict; +} + +/** Function to handle all mouse events. + * + * @param evnt event + * @param action type of event (e.g. mouse up, mouse wheel) + */ +function mouseHandlerDispatch(evnt, action) +{ + if (!evnt) + evnt = window.event; + + var retVal = true; + + if (!processingEffect && mouseHandlerDictionary[currentMode] && mouseHandlerDictionary[currentMode][action]) + { + var subRetVal = mouseHandlerDictionary[currentMode][action](evnt); + + if (subRetVal != null && subRetVal != undefined) + retVal = subRetVal; + } + + if (evnt.preventDefault && !retVal) + evnt.preventDefault(); + + evnt.returnValue = retVal; + + return retVal; +} + +// Set mouse event handler. +document.onmousedown = function(e) { return mouseHandlerDispatch(e, MOUSE_DOWN); }; +document.onmouseup = function(e) { return mouseHandlerDispatch(e, MOUSE_UP); }; +document.onmousemove = function(e) { return mouseHandlerDispatch(e, MOUSE_MOVE); }; + +// Moz +if (window.addEventListener) +{ + window.addEventListener('DOMMouseScroll', function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }, false); +} + +// Opera Safari OK - may not work in IE +window.onmousewheel = function(e) { return mouseHandlerDispatch(e, MOUSE_WHEEL); }; + +/** Function to supply the default mouse handler dictionary. + * + * @returns default mouse handler dictionary + */ +function getDefaultMouseHandlerDictionary() +{ + var mouseHandlerDict = new Object(); + + mouseHandlerDict[SLIDE_MODE] = new Object(); + mouseHandlerDict[INDEX_MODE] = new Object(); + mouseHandlerDict[DRAWING_MODE] = new Object(); + + mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN] = function(evnt) { return dispatchEffects(1); }; + mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL] = function(evnt) { return slideMousewheel(evnt); }; + + mouseHandlerDict[INDEX_MODE][MOUSE_DOWN] = function(evnt) { return toggleSlideIndex(); }; + + mouseHandlerDict[DRAWING_MODE][MOUSE_DOWN] = function(evnt) { return drawingMousedown(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_UP] = function(evnt) { return drawingMouseup(evnt); }; + mouseHandlerDict[DRAWING_MODE][MOUSE_MOVE] = function(evnt) { return drawingMousemove(evnt); }; + + return mouseHandlerDict; +} + +/** Function to switch from slide mode to drawing mode. +*/ +function slideSwitchToDrawingMode() +{ + currentMode = DRAWING_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "crosshair"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to switch from drawing mode to slide mode. +*/ +function drawingSwitchToSlideMode() +{ + currentMode = SLIDE_MODE; + + var tempDict; + + if (ROOT_NODE.hasAttribute("style")) + tempDict = propStrToDict(ROOT_NODE.getAttribute("style")); + else + tempDict = new Object(); + + tempDict["cursor"] = "auto"; + ROOT_NODE.setAttribute("style", dictToPropStr(tempDict)); +} + +/** Function to decrease the number of columns in index mode. +*/ +function indexDecreaseNumberOfColumns() +{ + if (INDEX_COLUMNS >= 3) + { + INDEX_COLUMNS -= 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to increase the number of columns in index mode. +*/ +function indexIncreaseNumberOfColumns() +{ + if (INDEX_COLUMNS < 7) + { + INDEX_COLUMNS += 1; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset the number of columns in index mode. +*/ +function indexResetNumberOfColumns() +{ + if (INDEX_COLUMNS != INDEX_COLUMNS_DEFAULT) + { + INDEX_COLUMNS = INDEX_COLUMNS_DEFAULT; + INDEX_OFFSET = -1 + indexSetPageSlide(activeSlide); + } +} + +/** Function to reset path width in drawing mode. +*/ +function drawingResetPathWidth() +{ + path_width = path_width_default; + set_path_paint_width(); +} + +/** Function to set path width in drawing mode. + * + * @param width new path width + */ +function drawingSetPathWidth(width) +{ + path_width = width; + set_path_paint_width(); +} + +/** Function to set path colour in drawing mode. + * + * @param colour new path colour + */ +function drawingSetPathColour(colour) +{ + path_colour = colour; +} + +/** Function to query the duration of the presentation from the user in slide mode. +*/ +function slideQueryDuration() +{ + var new_duration = prompt("Length of presentation in minutes?", timer_duration); + + if ((new_duration != null) && (new_duration != '')) + { + timer_duration = new_duration; + } + + updateTimer(); +} + +/** Function to add new slide in slide mode. + * + * @param afterSlide after which slide to insert the new one + */ +function slideAddSlide(afterSlide) +{ + addSlide(afterSlide); + slideSetActiveSlide(afterSlide + 1); + updateTimer(); +} + +/** Function to toggle the visibility of the progress bar in slide mode. +*/ +function slideToggleProgressBarVisibility() +{ + if (progress_bar_visible) + { + progress_bar_visible = false; + hideProgressBar(); + } + else + { + progress_bar_visible = true; + showProgressBar(); + } +} + +/** Function to reset the timer in slide mode. +*/ +function slideResetTimer() +{ + timer_start = timer_elapsed; + updateTimer(); +} + +/** Convenience function to pad a string with zero in front up to a certain length. + */ +function padString(str, len) +{ + var outStr = str; + + while (outStr.length < len) + { + outStr = '0' + outStr; + } + + return outStr; +} + +/** Function to update the export layer. + */ +function slideUpdateExportLayer() +{ + // Suspend redraw since we are going to mess with the slides. + var suspendHandle = ROOT_NODE.suspendRedraw(2000); + + var tmpActiveSlide = activeSlide; + var tmpActiveEffect = activeEffect; + var exportedLayers = new Array(); + + for (var counterSlides = 0; counterSlides < slides.length; counterSlides++) + { + var exportNode; + + setSlideToState(counterSlides, STATE_START); + + var maxEffect = 0; + + if (slides[counterSlides].effects) + { + maxEffect = slides[counterSlides].effects.length; + } + + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString("0", maxEffect.toString().length)); + + exportedLayers.push(exportNode); + + if (slides[counterSlides]["effects"]) + { + for (var counter = 0; counter < slides[counterSlides]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[counterSlides]["effects"][counter].length; subCounter++) + { + var effect = slides[counterSlides]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]), effect["element"], STATE_END, effect["options"]); + } + + var layerName = "slide_" + padString((counterSlides + 1).toString(), slides.length.toString().length) + "_effect_" + padString((counter + 1).toString(), maxEffect.toString().length); + exportNode = slides[counterSlides].element.cloneNode(true); + exportNode.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + exportNode.setAttributeNS(NSS["inkscape"], "label", layerName); + exportNode.setAttribute("id", layerName); + + exportedLayers.push(exportNode); + } + } + } + + activeSlide = tmpActiveSlide; + activeEffect = tmpActiveEffect; + setSlideToState(activeSlide, activeEffect); + + // Copy image. + var newDoc = document.documentElement.cloneNode(true); + + // Delete viewbox form new imag and set width and height. + newDoc.removeAttribute('viewbox'); + newDoc.setAttribute('width', WIDTH); + newDoc.setAttribute('height', HEIGHT); + + // Delete all layers and script elements. + var nodesToBeRemoved = new Array(); + + for (var childCounter = 0; childCounter < newDoc.childNodes.length; childCounter++) + { + var child = newDoc.childNodes[childCounter]; + + if (child.nodeType == 1) + { + if ((child.nodeName.toUpperCase() == 'G') || (child.nodeName.toUpperCase() == 'SCRIPT')) + { + nodesToBeRemoved.push(child); + } + } + } + + for (var ndCounter = 0; ndCounter < nodesToBeRemoved.length; ndCounter++) + { + var nd = nodesToBeRemoved[ndCounter]; + + // Before removing the node, check whether it contains any definitions. + var defs = nd.getElementsByTagNameNS(NSS["svg"], "defs"); + + for (var defsCounter = 0; defsCounter < defs.length; defsCounter++) + { + if (defs[defsCounter].id) + { + newDoc.appendChild(defs[defsCounter].cloneNode(true)); + } + } + + // Remove node. + nd.parentNode.removeChild(nd); + } + + // Set current layer. + if (exportedLayers[0]) + { + var namedView; + + for (var nodeCounter = 0; nodeCounter < newDoc.childNodes.length; nodeCounter++) + { + if ((newDoc.childNodes[nodeCounter].nodeType == 1) && (newDoc.childNodes[nodeCounter].getAttribute('id') == 'base')) + { + namedView = newDoc.childNodes[nodeCounter]; + } + } + + if (namedView) + { + namedView.setAttributeNS(NSS['inkscape'], 'current-layer', exportedLayers[0].getAttributeNS(NSS['inkscape'], 'label')); + } + } + + // Add exported layers. + while (exportedLayers.length > 0) + { + var nd = exportedLayers.pop(); + + nd.setAttribute("opacity",1); + nd.style.display = "inherit"; + + newDoc.appendChild(nd); + } + + // Serialise the new document. + window.location = 'data:application/svg+xml;base64;charset=utf-8,' + window.btoa(unescape(encodeURIComponent((new XMLSerializer()).serializeToString(newDoc)))); + + // Unsuspend redraw. + ROOT_NODE.unsuspendRedraw(suspendHandle); + ROOT_NODE.forceRedraw(); +} + +/** Function to undo last drawing operation. +*/ +function drawingUndo() +{ + mouse_presentation_path = null; + mouse_original_path = null; + + if (history_presentation_elements.length > 0) + { + var p = history_presentation_elements.pop(); + var parent = p.parentNode.removeChild(p); + + p = history_original_elements.pop(); + parent = p.parentNode.removeChild(p); + } +} + +/** Event handler for mouse down in drawing mode. + * + * @param e the event + */ +function drawingMousedown(e) +{ + var value = 0; + + if (e.button) + value = e.button; + else if (e.which) + value = e.which; + + if (value == 1) + { + history_counter++; + + var p = calcCoord(e); + + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + mouse_original_path = document.createElementNS(NSS["svg"], "path"); + mouse_original_path.setAttribute("stroke", path_colour); + mouse_original_path.setAttribute("stroke-width", path_paint_width); + mouse_original_path.setAttribute("fill", "none"); + mouse_original_path.setAttribute("id", "path " + Date()); + mouse_original_path.setAttribute("d", "M" + p.x + "," + p.y); + slides[activeSlide]["original_element"].appendChild(mouse_original_path); + history_original_elements.push(mouse_original_path); + + mouse_presentation_path = document.createElementNS(NSS["svg"], "path"); + mouse_presentation_path.setAttribute("stroke", path_colour); + mouse_presentation_path.setAttribute("stroke-width", path_paint_width); + mouse_presentation_path.setAttribute("fill", "none"); + mouse_presentation_path.setAttribute("id", "path " + Date() + " presentation copy"); + mouse_presentation_path.setAttribute("d", "M" + p.x + "," + p.y); + + if (slides[activeSlide]["viewGroup"]) + slides[activeSlide]["viewGroup"].appendChild(mouse_presentation_path); + else + slides[activeSlide]["element"].appendChild(mouse_presentation_path); + + history_presentation_elements.push(mouse_presentation_path); + + return false; + } + + return true; +} + +/** Event handler for mouse up in drawing mode. + * + * @param e the event + */ +function drawingMouseup(e) +{ + if(!e) + e = window.event; + + if (mouse_presentation_path != null) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_presentation_path = null; + mouse_original_path.setAttribute("d", d); + mouse_original_path = null; + + return false; + } + + return true; +} + +/** Event handler for mouse move in drawing mode. + * + * @param e the event + */ +function drawingMousemove(e) +{ + if(!e) + e = window.event; + + var dist = (mouse_last_x - e.clientX) * (mouse_last_x - e.clientX) + (mouse_last_y - e.clientY) * (mouse_last_y - e.clientY); + + if (mouse_presentation_path == null) + { + return true; + } + + if (dist >= mouse_min_dist_sqr) + { + var p = calcCoord(e); + var d = mouse_presentation_path.getAttribute("d"); + d += " L" + p.x + "," + p.y; + mouse_presentation_path.setAttribute("d", d); + mouse_original_path.setAttribute("d", d); + mouse_last_x = e.clientX; + mouse_last_y = e.clientY; + } + + return false; +} + +/** Event handler for mouse wheel events in slide mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function slideMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + skipEffects(-1); + else if (delta < 0) + skipEffects(1); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Event handler for mouse wheel events in index mode. + * based on http://adomas.org/javascript-mouse-wheel/ + * + * @param e the event + */ +function indexMousewheel(e) +{ + var delta = 0; + + if (!e) + e = window.event; + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + if (delta > 0) + indexSetPageSlide(activeSlide - INDEX_COLUMNS * INDEX_COLUMNS); + else if (delta < 0) + indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); + + if (e.preventDefault) + e.preventDefault(); + + e.returnValue = false; +} + +/** Function to set the path paint width. +*/ +function set_path_paint_width() +{ + var svgPoint1 = document.documentElement.createSVGPoint(); + var svgPoint2 = document.documentElement.createSVGPoint(); + + svgPoint1.x = 0.0; + svgPoint1.y = 0.0; + svgPoint2.x = 1.0; + svgPoint2.y = 0.0; + + var matrix = slides[activeSlide]["element"].getTransformToElement(ROOT_NODE); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getTransformToElement(ROOT_NODE); + + svgPoint1 = svgPoint1.matrixTransform(matrix); + svgPoint2 = svgPoint2.matrixTransform(matrix); + + path_paint_width = path_width / Math.sqrt((svgPoint2.x - svgPoint1.x) * (svgPoint2.x - svgPoint1.x) + (svgPoint2.y - svgPoint1.y) * (svgPoint2.y - svgPoint1.y)); +} + +/** The view effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect); for the view effect the options need to contain the old and the new matrix. + */ +function view(dir, element, time, options) +{ + var length = 250; + var fraction; + + if (!options["matrixInitial"]) + { + var tempString = slides[activeSlide]["viewGroup"].getAttribute("transform"); + + if (tempString) + options["matrixInitial"] = (new matrixSVG()).fromAttribute(tempString); + else + options["matrixInitial"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0); + } + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixNew"].toAttribute()); + + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixNew"], fraction).toAttribute()); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("transform", options["matrixInitial"].toAttribute()); + } + else if (fraction >= 1) + { + element.setAttribute("transform", options["matrixOld"].toAttribute()); + set_path_paint_width(); + + options["matrixInitial"] = null; + return true; + } + else + { + element.setAttribute("transform", options["matrixInitial"].mix(options["matrixOld"], fraction).toAttribute()); + } + } + + return false; +} + +/** The fade effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function fade(dir, element, time, options) +{ + var length = 250; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.style.display = "none"; + element.setAttribute("opacity", 0); + } + else if (fraction >= 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", fraction); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1); + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.style.display = "none"; + return true; + } + else + { + element.style.display = "inherit"; + element.setAttribute("opacity", 1 - fraction); + } + } + return false; +} + +/** The appear effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function appear(dir, element, time, options) +{ + if (dir == 1) + { + element.style.display = "inherit"; + element.setAttribute("opacity",1); + } + else if (dir == -1) + { + element.style.display = "none"; + element.setAttribute("opacity",0); + } + return true; +} + +/** The pop effect. + * + * @param dir direction the effect should be played (1 = forwards, -1 = backwards) + * @param element the element the effect should be applied to + * @param time the time that has elapsed since the beginning of the effect + * @param options a dictionary with additional options (e.g. length of the effect) + */ +function pop(dir, element, time, options) +{ + var length = 500; + var fraction; + + if ((time == STATE_END) || (time == STATE_START)) + fraction = 1; + else + { + if (options && options["length"]) + length = options["length"]; + + fraction = time / length; + } + + if (dir == 1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 0); + element.setAttribute("transform", "scale(0)"); + element.style.display = "none"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 1); + element.removeAttribute("transform"); + element.style.display = "inherit"; + return true; + } + else + { + element.style.display = "inherit"; + var opacityFraction = fraction * 3; + if (opacityFraction > 1) + opacityFraction = 1; + element.setAttribute("opacity", opacityFraction); + var offsetX = WIDTH * (1.0 - fraction) / 2.0; + var offsetY = HEIGHT * (1.0 - fraction) / 2.0; + element.setAttribute("transform", "translate(" + offsetX + "," + offsetY + ") scale(" + fraction + ")"); + } + } + else if (dir == -1) + { + if (fraction <= 0) + { + element.setAttribute("opacity", 1); + element.setAttribute("transform", "scale(1)"); + element.style.display = "inherit"; + } + else if (fraction >= 1) + { + element.setAttribute("opacity", 0); + element.removeAttribute("transform"); + element.style.display = "none"; + return true; + } + else + { + element.setAttribute("opacity", 1 - fraction); + element.setAttribute("transform", "scale(" + 1 - fraction + ")"); + element.style.display = "inherit"; + } + } + return false; +} + +/** Function to set a slide either to the start or the end state. + * + * @param slide the slide to use + * @param state the state into which the slide should be set + */ +function setSlideToState(slide, state) +{ + slides[slide]["viewGroup"].setAttribute("transform", slides[slide].initialView); + + if (slides[slide]["effects"]) + { + if (state == STATE_END) + { + for (var counter = 0; counter < slides[slide]["effects"].length; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + else if (state == STATE_START) + { + for (var counter = slides[slide]["effects"].length - 1; counter >= 0; counter--) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "appear") + appear(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "pop") + pop(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + else if (effect["effect"] == "view") + view(parseInt(effect["dir"]) * -1, effect["element"], STATE_START, effect["options"]); + } + } + } + else + { + setSlideToState(slide, STATE_START); + + for (var counter = 0; counter < slides[slide]["effects"].length && counter < state; counter++) + { + for (var subCounter = 0; subCounter < slides[slide]["effects"][counter].length; subCounter++) + { + var effect = slides[slide]["effects"][counter][subCounter]; + if (effect["effect"] == "fade") + fade(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "appear") + appear(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "pop") + pop(effect["dir"], effect["element"], STATE_END, effect["options"]); + else if (effect["effect"] == "view") + view(effect["dir"], effect["element"], STATE_END, effect["options"]); + } + } + } + } + + window.location.hash = (activeSlide + 1) + '_' + activeEffect; +} + +/** Convenience function to translate a attribute string into a dictionary. + * + * @param str the attribute string + * @return a dictionary + * @see dictToPropStr + */ +function propStrToDict(str) +{ + var list = str.split(";"); + var obj = new Object(); + + for (var counter = 0; counter < list.length; counter++) + { + var subStr = list[counter]; + var subList = subStr.split(":"); + if (subList.length == 2) + { + obj[subList[0]] = subList[1]; + } + } + + return obj; +} + +/** Convenience function to translate a dictionary into a string that can be used as an attribute. + * + * @param dict the dictionary to convert + * @return a string that can be used as an attribute + * @see propStrToDict + */ +function dictToPropStr(dict) +{ + var str = ""; + + for (var key in dict) + { + str += key + ":" + dict[key] + ";"; + } + + return str; +} + +/** Sub-function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @param replace dictionary of replaced ids + * @see suffixNodeIds + */ +function suffixNoneIds_sub(node, suffix, replace) +{ + if (node.nodeType == 1) + { + if (node.getAttribute("id")) + { + var id = node.getAttribute("id") + replace["#" + id] = id + suffix; + node.setAttribute("id", id + suffix); + } + + if ((node.nodeName == "use") && (node.getAttributeNS(NSS["xlink"], "href")) && (replace[node.getAttribute(NSS["xlink"], "href")])) + node.setAttribute(NSS["xlink"], "href", node.getAttribute(NSS["xlink"], "href") + suffix); + + if (node.childNodes) + { + for (var counter = 0; counter < node.childNodes.length; counter++) + suffixNoneIds_sub(node.childNodes[counter], suffix, replace); + } + } +} + +/** Function to add a suffix to the ids of the node and all its children. + * + * @param node the node to change + * @param suffix the suffix to add + * @return the changed node + * @see suffixNodeIds_sub + */ +function suffixNodeIds(node, suffix) +{ + var replace = new Object(); + + suffixNoneIds_sub(node, suffix, replace); + + return node; +} + +/** Function to build a progress bar. + * + * @param parent node to attach the progress bar to + */ +function createProgressBar(parent_node) +{ + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "layer_progress_bar"); + g.setAttribute("style", "display: none;"); + + var rect_progress_bar = document.createElementNS(NSS["svg"], "rect"); + rect_progress_bar.setAttribute("style", "marker: none; fill: rgb(128, 128, 128); stroke: none;"); + rect_progress_bar.setAttribute("id", "rect_progress_bar"); + rect_progress_bar.setAttribute("x", 0); + rect_progress_bar.setAttribute("y", 0.99 * HEIGHT); + rect_progress_bar.setAttribute("width", 0); + rect_progress_bar.setAttribute("height", 0.01 * HEIGHT); + g.appendChild(rect_progress_bar); + + var circle_timer_indicator = document.createElementNS(NSS["svg"], "circle"); + circle_timer_indicator.setAttribute("style", "marker: none; fill: rgb(255, 0, 0); stroke: none;"); + circle_timer_indicator.setAttribute("id", "circle_timer_indicator"); + circle_timer_indicator.setAttribute("cx", 0.005 * HEIGHT); + circle_timer_indicator.setAttribute("cy", 0.995 * HEIGHT); + circle_timer_indicator.setAttribute("r", 0.005 * HEIGHT); + g.appendChild(circle_timer_indicator); + + parent_node.appendChild(g); +} + +/** Function to hide the progress bar. + * + */ +function hideProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: none;"); +} + +/** Function to show the progress bar. + * + */ +function showProgressBar() +{ + var progress_bar = document.getElementById("layer_progress_bar"); + + if (!progress_bar) + { + return; + } + + progress_bar.setAttribute("style", "display: inherit;"); +} + +/** Set progress bar value. + * + * @param value the current slide number + * + */ +function setProgressBarValue(value) +{ + var rect_progress_bar = document.getElementById("rect_progress_bar"); + + if (!rect_progress_bar) + { + return; + } + + if (value < 1) + { + // First slide, assumed to be the title of the presentation + var x = 0; + var w = 0.01 * HEIGHT; + } + else if (value >= slides.length - 1) + { + // Last slide, assumed to be the end of the presentation + var x = WIDTH - 0.01 * HEIGHT; + var w = 0.01 * HEIGHT; + } + else + { + value -= 1; + value /= (slides.length - 2); + + var x = WIDTH * value; + var w = WIDTH / (slides.length - 2); + } + + rect_progress_bar.setAttribute("x", x); + rect_progress_bar.setAttribute("width", w); +} + +/** Set time indicator. + * + * @param value the percentage of time elapse so far between 0.0 and 1.0 + * + */ +function setTimeIndicatorValue(value) +{ + var circle_timer_indicator = document.getElementById("circle_timer_indicator"); + + if (!circle_timer_indicator) + { + return; + } + + if (value < 0.0) + { + value = 0.0; + } + + if (value > 1.0) + { + value = 1.0; + } + + var cx = (WIDTH - 0.01 * HEIGHT) * value + 0.005 * HEIGHT; + circle_timer_indicator.setAttribute("cx", cx); +} + +/** Update timer. + * + */ +function updateTimer() +{ + timer_elapsed += 1; + setTimeIndicatorValue((timer_elapsed - timer_start) / (60 * timer_duration)); +} + +/** Convert screen coordinates to document coordinates. + * + * @param e event with screen coordinates + * + * @return coordinates in SVG file coordinate system + */ +function calcCoord(e) +{ + var svgPoint = document.documentElement.createSVGPoint(); + svgPoint.x = e.clientX + window.pageXOffset; + svgPoint.y = e.clientY + window.pageYOffset; + + var matrix = slides[activeSlide]["element"].getScreenCTM(); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getScreenCTM(); + + svgPoint = svgPoint.matrixTransform(matrix.inverse()); + return svgPoint; +} + +/** Add slide. + * + * @param after_slide after which slide the new slide should be inserted into the presentation + */ +function addSlide(after_slide) +{ + number_of_added_slides++; + + var g = document.createElementNS(NSS["svg"], "g"); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date() + " presentation copy"); + g.setAttribute("style", "display: none;"); + + var new_slide = new Object(); + new_slide["element"] = g; + + // Set build in transition. + new_slide["transitionIn"] = new Object(); + var dict = defaultTransitionInDict; + new_slide["transitionIn"]["name"] = dict["name"]; + new_slide["transitionIn"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionIn"]["options"][key] = dict[key]; + + // Set build out transition. + new_slide["transitionOut"] = new Object(); + dict = defaultTransitionOutDict; + new_slide["transitionOut"]["name"] = dict["name"]; + new_slide["transitionOut"]["options"] = new Object(); + + for (key in dict) + if (key != "name") + new_slide["transitionOut"]["options"][key] = dict[key]; + + // Copy master slide content. + if (masterSlide) + { + var clonedNode = suffixNodeIds(masterSlide.cloneNode(true), "_" + Date() + " presentation_copy"); + clonedNode.removeAttributeNS(NSS["inkscape"], "groupmode"); + clonedNode.removeAttributeNS(NSS["inkscape"], "label"); + clonedNode.style.display = "inherit"; + + g.appendChild(clonedNode); + } + + // Substitute auto texts. + substituteAutoTexts(g, "Whiteboard " + number_of_added_slides, "W" + number_of_added_slides, slides.length); + + g.setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + (after_slide + 1) + ")) { indexSetActiveSlide(" + (after_slide + 1) + "); };"); + + // Create a transform group. + var transformGroup = document.createElementNS(NSS["svg"], "g"); + + // Add content to transform group. + while (g.firstChild) + transformGroup.appendChild(g.firstChild); + + // Transfer the transform attribute from the node to the transform group. + if (g.getAttribute("transform")) + { + transformGroup.setAttribute("transform", g.getAttribute("transform")); + g.removeAttribute("transform"); + } + + // Create a view group. + var viewGroup = document.createElementNS(NSS["svg"], "g"); + + viewGroup.appendChild(transformGroup); + new_slide["viewGroup"] = g.appendChild(viewGroup); + + // Insert background. + if (BACKGROUND_COLOR != null) + { + var rectNode = document.createElementNS(NSS["svg"], "rect"); + + rectNode.setAttribute("x", 0); + rectNode.setAttribute("y", 0); + rectNode.setAttribute("width", WIDTH); + rectNode.setAttribute("height", HEIGHT); + rectNode.setAttribute("id", "jessyInkBackground" + Date()); + rectNode.setAttribute("fill", BACKGROUND_COLOR); + + new_slide["viewGroup"].insertBefore(rectNode, new_slide["viewGroup"].firstChild); + } + + // Set initial view even if there are no other views. + var matrixOld = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + + new_slide["viewGroup"].setAttribute("transform", matrixOld.toAttribute()); + new_slide.initialView = matrixOld.toAttribute(); + + // Insert slide + var node = slides[after_slide]["element"]; + var next_node = node.nextSibling; + var parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + g = document.createElementNS(NSS["svg"], "g"); + g.setAttributeNS(NSS["inkscape"], "groupmode", "layer"); + g.setAttributeNS(NSS["inkscape"], "label", "Whiteboard " + number_of_added_slides); + g.setAttribute("clip-path", "url(#jessyInkSlideClipPath)"); + g.setAttribute("id", "Whiteboard " + Date()); + g.setAttribute("style", "display: none;"); + + new_slide["original_element"] = g; + + node = slides[after_slide]["original_element"]; + next_node = node.nextSibling; + parent_node = node.parentNode; + + if (next_node) + { + parent_node.insertBefore(g, next_node); + } + else + { + parent_node.appendChild(g); + } + + before_new_slide = slides.slice(0, after_slide + 1); + after_new_slide = slides.slice(after_slide + 1); + slides = before_new_slide.concat(new_slide, after_new_slide); + + //resetting the counter attributes on the slides that follow the new slide... + for (var counter = after_slide+2; counter < slides.length; counter++) + { + slides[counter]["element"].setAttribute("onmouseover", "if ((currentMode == INDEX_MODE) && ( activeSlide != " + counter + ")) { indexSetActiveSlide(" + counter + "); };"); + } +} + +/** Convenience function to obtain a transformation matrix from a point matrix. + * + * @param mPoints Point matrix. + * @return A transformation matrix. + */ +function pointMatrixToTransformation(mPoints) +{ + mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1); + + return mPointsOld.mult(mPoints.inv()); +} + +/** Convenience function to obtain a matrix with three corners of a rectangle. + * + * @param rect an svg rectangle + * @return a matrixSVG containing three corners of the rectangle + */ +function rectToMatrix(rect) +{ + rectWidth = rect.getBBox().width; + rectHeight = rect.getBBox().height; + rectX = rect.getBBox().x; + rectY = rect.getBBox().y; + rectXcorr = 0; + rectYcorr = 0; + + scaleX = WIDTH / rectWidth; + scaleY = HEIGHT / rectHeight; + + if (scaleX > scaleY) + { + scaleX = scaleY; + rectXcorr -= (WIDTH / scaleX - rectWidth) / 2; + rectWidth = WIDTH / scaleX; + } + else + { + scaleY = scaleX; + rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2; + rectHeight = HEIGHT / scaleY; + } + + if (rect.transform.baseVal.numberOfItems < 1) + { + mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix); + } + + newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1); + newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0); + + return mRectTrans.mult(newBasePoints.add(newVectors)); +} + +/** Function to handle JessyInk elements. + * + * @param node Element node. + */ +function handleElement(node) +{ + if (node.getAttributeNS(NSS['jessyink'], 'element') == 'core.video') + { + var url; + var width; + var height; + var x; + var y; + var transform; + + var tspans = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "tspan"); + + for (var tspanCounter = 0; tspanCounter < tspans.length; tspanCounter++) + { + if (tspans[tspanCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "url") + { + url = tspans[tspanCounter].firstChild.nodeValue; + } + } + + var rects = node.getElementsByTagNameNS("http://www.w3.org/2000/svg", "rect"); + + for (var rectCounter = 0; rectCounter < rects.length; rectCounter++) + { + if (rects[rectCounter].getAttributeNS("https://launchpad.net/jessyink", "video") == "rect") + { + x = rects[rectCounter].getAttribute("x"); + y = rects[rectCounter].getAttribute("y"); + width = rects[rectCounter].getAttribute("width"); + height = rects[rectCounter].getAttribute("height"); + transform = rects[rectCounter].getAttribute("transform"); + } + } + + for (var childCounter = 0; childCounter < node.childNodes.length; childCounter++) + { + if (node.childNodes[childCounter].nodeType == 1) + { + if (node.childNodes[childCounter].style) + { + node.childNodes[childCounter].style.display = 'none'; + } + else + { + node.childNodes[childCounter].setAttribute("style", "display: none;"); + } + } + } + + var foreignNode = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"); + foreignNode.setAttribute("x", x); + foreignNode.setAttribute("y", y); + foreignNode.setAttribute("width", width); + foreignNode.setAttribute("height", height); + foreignNode.setAttribute("transform", transform); + + var videoNode = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); + videoNode.setAttribute("src", url); + + foreignNode.appendChild(videoNode); + node.appendChild(foreignNode); + } +} + +/** Class processing the location hash. + * + * @param str location hash + */ +function LocationHash(str) +{ + this.slideNumber = 0; + this.effectNumber = 0; + + str = str.substr(1, str.length - 1); + + var parts = str.split('_'); + + // Try to extract slide number. + if (parts.length >= 1) + { + try + { + var slideNumber = parseInt(parts[0]); + + if (!isNaN(slideNumber)) + { + this.slideNumber = slideNumber - 1; + } + } + catch (e) + { + } + } + + // Try to extract effect number. + if (parts.length >= 2) + { + try + { + var effectNumber = parseInt(parts[1]); + + if (!isNaN(effectNumber)) + { + this.effectNumber = effectNumber; + } + } + catch (e) + { + } + } +} + +/** Class representing an svg matrix. +*/ +function matrixSVG() +{ + this.e11 = 0; // a + this.e12 = 0; // c + this.e13 = 0; // e + this.e21 = 0; // b + this.e22 = 0; // d + this.e23 = 0; // f + this.e31 = 0; + this.e32 = 0; + this.e33 = 0; +} + +/** Constructor function. + * + * @param a element a (i.e. 1, 1) as described in the svg standard. + * @param b element b (i.e. 2, 1) as described in the svg standard. + * @param c element c (i.e. 1, 2) as described in the svg standard. + * @param d element d (i.e. 2, 2) as described in the svg standard. + * @param e element e (i.e. 1, 3) as described in the svg standard. + * @param f element f (i.e. 2, 3) as described in the svg standard. + */ +matrixSVG.prototype.fromSVGElements = function(a, b, c, d, e, f) +{ + this.e11 = a; + this.e12 = c; + this.e13 = e; + this.e21 = b; + this.e22 = d; + this.e23 = f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param matrix an svg matrix as described in the svg standard. + */ +matrixSVG.prototype.fromSVGMatrix = function(m) +{ + this.e11 = m.a; + this.e12 = m.c; + this.e13 = m.e; + this.e21 = m.b; + this.e22 = m.d; + this.e23 = m.f; + this.e31 = 0; + this.e32 = 0; + this.e33 = 1; + + return this; +} + +/** Constructor function. + * + * @param e11 element 1, 1 of the matrix. + * @param e12 element 1, 2 of the matrix. + * @param e13 element 1, 3 of the matrix. + * @param e21 element 2, 1 of the matrix. + * @param e22 element 2, 2 of the matrix. + * @param e23 element 2, 3 of the matrix. + * @param e31 element 3, 1 of the matrix. + * @param e32 element 3, 2 of the matrix. + * @param e33 element 3, 3 of the matrix. + */ +matrixSVG.prototype.fromElements = function(e11, e12, e13, e21, e22, e23, e31, e32, e33) +{ + this.e11 = e11; + this.e12 = e12; + this.e13 = e13; + this.e21 = e21; + this.e22 = e22; + this.e23 = e23; + this.e31 = e31; + this.e32 = e32; + this.e33 = e33; + + return this; +} + +/** Constructor function. + * + * @param attrString string value of the "transform" attribute (currently only "matrix" is accepted) + */ +matrixSVG.prototype.fromAttribute = function(attrString) +{ + str = attrString.substr(7, attrString.length - 8); + + str = str.trim(); + + strArray = str.split(","); + + // Opera does not use commas to separate the values of the matrix, only spaces. + if (strArray.length != 6) + strArray = str.split(" "); + + this.e11 = parseFloat(strArray[0]); + this.e21 = parseFloat(strArray[1]); + this.e31 = 0; + this.e12 = parseFloat(strArray[2]); + this.e22 = parseFloat(strArray[3]); + this.e32 = 0; + this.e13 = parseFloat(strArray[4]); + this.e23 = parseFloat(strArray[5]); + this.e33 = 1; + + return this; +} + +/** Output function + * + * @return a string that can be used as the "transform" attribute. + */ +matrixSVG.prototype.toAttribute = function() +{ + return "matrix(" + this.e11 + ", " + this.e21 + ", " + this.e12 + ", " + this.e22 + ", " + this.e13 + ", " + this.e23 + ")"; +} + +/** Matrix nversion. + * + * @return the inverse of the matrix + */ +matrixSVG.prototype.inv = function() +{ + out = new matrixSVG(); + + det = this.e11 * (this.e33 * this.e22 - this.e32 * this.e23) - this.e21 * (this.e33 * this.e12 - this.e32 * this.e13) + this.e31 * (this.e23 * this.e12 - this.e22 * this.e13); + + out.e11 = (this.e33 * this.e22 - this.e32 * this.e23) / det; + out.e12 = -(this.e33 * this.e12 - this.e32 * this.e13) / det; + out.e13 = (this.e23 * this.e12 - this.e22 * this.e13) / det; + out.e21 = -(this.e33 * this.e21 - this.e31 * this.e23) / det; + out.e22 = (this.e33 * this.e11 - this.e31 * this.e13) / det; + out.e23 = -(this.e23 * this.e11 - this.e21 * this.e13) / det; + out.e31 = (this.e32 * this.e21 - this.e31 * this.e22) / det; + out.e32 = -(this.e32 * this.e11 - this.e31 * this.e12) / det; + out.e33 = (this.e22 * this.e11 - this.e21 * this.e12) / det; + + return out; +} + +/** Matrix multiplication. + * + * @param op another svg matrix + * @return this * op + */ +matrixSVG.prototype.mult = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 * op.e11 + this.e12 * op.e21 + this.e13 * op.e31; + out.e12 = this.e11 * op.e12 + this.e12 * op.e22 + this.e13 * op.e32; + out.e13 = this.e11 * op.e13 + this.e12 * op.e23 + this.e13 * op.e33; + out.e21 = this.e21 * op.e11 + this.e22 * op.e21 + this.e23 * op.e31; + out.e22 = this.e21 * op.e12 + this.e22 * op.e22 + this.e23 * op.e32; + out.e23 = this.e21 * op.e13 + this.e22 * op.e23 + this.e23 * op.e33; + out.e31 = this.e31 * op.e11 + this.e32 * op.e21 + this.e33 * op.e31; + out.e32 = this.e31 * op.e12 + this.e32 * op.e22 + this.e33 * op.e32; + out.e33 = this.e31 * op.e13 + this.e32 * op.e23 + this.e33 * op.e33; + + return out; +} + +/** Matrix addition. + * + * @param op another svg matrix + * @return this + op + */ +matrixSVG.prototype.add = function(op) +{ + out = new matrixSVG(); + + out.e11 = this.e11 + op.e11; + out.e12 = this.e12 + op.e12; + out.e13 = this.e13 + op.e13; + out.e21 = this.e21 + op.e21; + out.e22 = this.e22 + op.e22; + out.e23 = this.e23 + op.e23; + out.e31 = this.e31 + op.e31; + out.e32 = this.e32 + op.e32; + out.e33 = this.e33 + op.e33; + + return out; +} + +/** Matrix mixing. + * + * @param op another svg matrix + * @parma contribOp contribution of the other matrix (0 <= contribOp <= 1) + * @return (1 - contribOp) * this + contribOp * op + */ +matrixSVG.prototype.mix = function(op, contribOp) +{ + contribThis = 1.0 - contribOp; + out = new matrixSVG(); + + out.e11 = contribThis * this.e11 + contribOp * op.e11; + out.e12 = contribThis * this.e12 + contribOp * op.e12; + out.e13 = contribThis * this.e13 + contribOp * op.e13; + out.e21 = contribThis * this.e21 + contribOp * op.e21; + out.e22 = contribThis * this.e22 + contribOp * op.e22; + out.e23 = contribThis * this.e23 + contribOp * op.e23; + out.e31 = contribThis * this.e31 + contribOp * op.e31; + out.e32 = contribThis * this.e32 + contribOp * op.e32; + out.e33 = contribThis * this.e33 + contribOp * op.e33; + + return out; +} + +/** Trimming function for strings. +*/ +String.prototype.trim = function() +{ + return this.replace(/^\s+|\s+$/g, ''); +} + +/** SVGElement.getTransformToElement polyfill */ +SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) { + return elem.getScreenCTM().inverse().multiply(this.getScreenCTM()); +}; + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__SPACE__--drawing_undo__ENTER__--index_nextPage__LEFT.out b/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__SPACE__--drawing_undo__ENTER__--index_nextPage__LEFT.out new file mode 100644 index 0000000..4c87b34 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__SPACE__--drawing_undo__ENTER__--index_nextPage__LEFT.out @@ -0,0 +1,61 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +function getCustomKeyBindingsSub() +{ + var keyDict = new Object(); + keyDict[SLIDE_MODE] = new Object(); + keyDict[INDEX_MODE] = new Object(); + keyDict[DRAWING_MODE] = new Object(); + keyDict[SLIDE_MODE][SPACE_KEY] = function() { slideUpdateExportLayer(); }; + keyDict[DRAWING_MODE][ENTER_KEY] = function() { drawingUndo(); }; + keyDict[INDEX_MODE][LEFT_KEY] = function() { indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); }; + return keyDict; +} + +function getCustomCharBindingsSub() +{ + var charDict = new Object(); + charDict[SLIDE_MODE] = new Object(); + charDict[INDEX_MODE] = new Object(); + charDict[DRAWING_MODE] = new Object(); + return charDict; +} + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__a__--drawing_undo__b__--index_nextPage__c.out b/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__a__--drawing_undo__b__--index_nextPage__c.out new file mode 100644 index 0000000..ed3b6bb --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_key_bindings__--slide_export__a__--drawing_undo__b__--index_nextPage__c.out @@ -0,0 +1,61 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +function getCustomKeyBindingsSub() +{ + var keyDict = new Object(); + keyDict[SLIDE_MODE] = new Object(); + keyDict[INDEX_MODE] = new Object(); + keyDict[DRAWING_MODE] = new Object(); + return keyDict; +} + +function getCustomCharBindingsSub() +{ + var charDict = new Object(); + charDict[SLIDE_MODE] = new Object(); + charDict[INDEX_MODE] = new Object(); + charDict[DRAWING_MODE] = new Object(); + charDict[SLIDE_MODE]["a"] = function() { slideUpdateExportLayer(); }; + charDict[DRAWING_MODE]["b"] = function() { drawingUndo(); }; + charDict[INDEX_MODE]["c"] = function() { indexSetPageSlide(activeSlide + INDEX_COLUMNS * INDEX_COLUMNS); }; + return charDict; +} + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_master_slide.out b/share/extensions/tests/data/refs/jessyink_master_slide.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/jessyink_master_slide__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/jessyink_master_slide__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__default.out b/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__default.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__draggingZoom.out b/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__draggingZoom.out new file mode 100644 index 0000000..46d82ea --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__draggingZoom.out @@ -0,0 +1,475 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +// Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Add event listener for initialisation. +document.addEventListener("DOMContentLoaded", jessyInk_core_mouseHandler_zoomControl_init, false); + +/** Initialisation function. + * + * This function looks for the objects of the appropriate sub-type and hands them to another function that will add the required methods. + */ +function jessyInk_core_mouseHandler_zoomControl_init() +{ + var elems = document.getElementsByTagNameNS("https://launchpad.net/jessyink", "mousehandler"); + + for (var counter = 0; counter < elems.length; counter++) + { + if (elems[counter].getAttributeNS("https://launchpad.net/jessyink", "subtype") == "jessyInk_core_mouseHandler_zoomControl") + jessyInk_core_mouseHandler_zoomControl(elems[counter]); + } +} + +/** Function to initialise an object. + * + * @param obj Object to be initialised. + */ +function jessyInk_core_mouseHandler_zoomControl(obj) +{ + // Last dragging position. + obj.dragging_last; + // Flag to indicate whether dragging is active currently. + obj.dragging_active = false; + // Flag to indicate whether dragging is working currently. + obj.dragging_working = false; + // Flag to indicate whether the user clicked. + obj.click = false; + + /** Function supplying a custom mouse handler. + * + * @returns A dictionary containing the new mouse handler functions. + */ + obj.getMouseHandler = function () + { + var handlerDictio = new Object(); + + handlerDictio[SLIDE_MODE] = new Object(); + handlerDictio[SLIDE_MODE][MOUSE_DOWN] = obj.mousedown; + handlerDictio[SLIDE_MODE][MOUSE_MOVE] = obj.mousemove; + handlerDictio[SLIDE_MODE][MOUSE_UP] = obj.mouseup; + handlerDictio[SLIDE_MODE][MOUSE_WHEEL] = obj.mousewheel; + + return handlerDictio; + } + + /** Event handler for mouse clicks. + * + * @param e Event object. + */ + obj.mouseclick = function (e) + { + var elem = obj.getAdHocViewBbox(slides[activeSlide]["viewGroup"], obj.getCoords(e)); + + processingEffect = true; + + effectArray = new Array(); + + effectArray[0] = new Object(); + effectArray[0]["effect"] = "view"; + effectArray[0]["dir"] = 1; + effectArray[0]["element"] = slides[activeSlide]["viewGroup"]; + effectArray[0]["options"] = new Object(); + effectArray[0]["options"]["length"] = 200; + + if (elem == null) + effectArray[0]["options"]["matrixNew"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0); + else + effectArray[0]["options"]["matrixNew"] = obj.pointMatrixToTransformation(obj.rectToMatrix(elem)).mult((new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(elem.parentNode.getScreenCTM())).inv()); + + transCounter = 0; + startTime = (new Date()).getTime(); + lastFrameTime = null; + effect(1); + + return false; + } + + /** Function to search for the element the user clicked on. + * + * This function searches for the element with the highest z-order, which encloses the point the user clicked on + * and which view box fits entierly into the currently visible part of the slide. + * + * @param elem Element to start the search from. + * @param pnt Point where the user clicked. + * @returns The element the user clicked on or null, if no element could be found. + */ + obj.getAdHocViewBbox = function (elem, pnt) + { + var children = elem.childNodes; + + for (var counter = 0; counter < children.length; counter++) + { + if (children[counter].getBBox) + { + var childPointList = obj.projectRect(children[counter].getBBox(), children[counter].getScreenCTM()); + + var viewBbox = document.documentElement.createSVGRect(); + + viewBbox.x = 0.0; + viewBbox.y = 0.0; + viewBbox.width = WIDTH; + viewBbox.height = HEIGHT; + + var screenPointList = obj.projectRect(viewBbox, slides[activeSlide]["element"].getScreenCTM()); + + if (obj.pointsWithinRect([pnt], childPointList) && obj.pointsWithinRect(childPointList, screenPointList)) + return children[counter]; + + child = obj.getAdHocViewBbox(children[counter], pnt); + + if (child != null) + return child; + } + } + + return null; + } + + /** Function to project a rectangle using the projection matrix supplied. + * + * @param rect The rectangle to project. + * @param projectionMatrix The projection matrix. + * @returns A list of the four corners of the projected rectangle starting from the upper left corner and going counter-clockwise. + */ + obj.projectRect = function (rect, projectionMatrix) + { + var pntUL = document.documentElement.createSVGPoint(); + pntUL.x = rect.x; + pntUL.y = rect.y; + pntUL = pntUL.matrixTransform(projectionMatrix); + + var pntLL = document.documentElement.createSVGPoint(); + pntLL.x = rect.x; + pntLL.y = rect.y + rect.height; + pntLL = pntLL.matrixTransform(projectionMatrix); + + var pntUR = document.documentElement.createSVGPoint(); + pntUR.x = rect.x + rect.width; + pntUR.y = rect.y; + pntUR = pntUR.matrixTransform(projectionMatrix); + + var pntLR = document.documentElement.createSVGPoint(); + pntLR.x = rect.x + rect.width; + pntLR.y = rect.y + rect.height; + pntLR = pntLR.matrixTransform(projectionMatrix); + + return [pntUL, pntLL, pntUR, pntLR]; + } + + /** Function to determine whether all the points supplied in a list are within a rectangle. + * + * @param pnts List of points to check. + * @param pointList List of points representing the four corners of the rectangle. + * @return True, if all points are within the rectangle; false, otherwise. + */ + obj.pointsWithinRect = function (pnts, pointList) + { + var pntUL = pointList[0]; + var pntLL = pointList[1]; + var pntUR = pointList[2]; + + var matrixOrig = (new matrixSVG()).fromElements(pntUL.x, pntLL.x, pntUR.x, pntUL.y, pntLL.y, pntUR.y, 1, 1, 1); + var matrixProj = (new matrixSVG()).fromElements(0, 0, 1, 0, 1, 0, 1, 1, 1); + + var matrixProjection = matrixProj.mult(matrixOrig.inv()); + + for (var blockCounter = 0; blockCounter < Math.ceil(pnts.length / 3.0); blockCounter++) + { + var subPnts = new Array(); + + for (var pntCounter = 0; pntCounter < 3.0; pntCounter++) + { + if (blockCounter * 3.0 + pntCounter < pnts.length) + subPnts[pntCounter] = pnts[blockCounter * 3.0 + pntCounter]; + else + { + var tmpPnt = document.documentElement.createSVGPoint(); + + tmpPnt.x = 0.0; + tmpPnt.y = 0.0; + + subPnts[pntCounter] = tmpPnt; + } + } + + var matrixPnt = (new matrixSVG).fromElements(subPnts[0].x, subPnts[1].x, subPnts[2].x, subPnts[0].y, subPnts[1].y, subPnts[2].y, 1, 1, 1); + var matrixTrans = matrixProjection.mult(matrixPnt); + + for (var pntCounter = 0; pntCounter < 3.0; pntCounter++) + { + if (blockCounter * 3.0 + pntCounter < pnts.length) + { + if ((pntCounter == 0) && !((matrixTrans.e11 > 0.01) && (matrixTrans.e11 < 0.99) && (matrixTrans.e21 > 0.01) && (matrixTrans.e21 < 0.99))) + return false; + else if ((pntCounter == 1) && !((matrixTrans.e12 > 0.01) && (matrixTrans.e12 < 0.99) && (matrixTrans.e22 > 0.01) && (matrixTrans.e22 < 0.99))) + return false; + else if ((pntCounter == 2) && !((matrixTrans.e13 > 0.01) && (matrixTrans.e13 < 0.99) && (matrixTrans.e23 > 0.01) && (matrixTrans.e23 < 0.99))) + return false; + } + } + } + + return true; + } + + /** Event handler for mouse movements. + * + * @param e Event object. + */ + obj.mousemove = function (e) + { + obj.click = false; + + if (!obj.dragging_active || obj.dragging_working) + return false; + + obj.dragging_working = true; + + var p = obj.getCoords(e); + + if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1) + { + var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix); + } + + matrix.e13 += p.x - obj.dragging_last.x; + matrix.e23 += p.y - obj.dragging_last.y; + + slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute()); + + obj.dragging_last = p; + obj.dragging_working = false; + + return false; + } + + /** Event handler for mouse down. + * + * @param e Event object. + */ + obj.mousedown = function (e) + { + if (obj.dragging_active) + return false; + + var value = 0; + + if (e.button) + value = e.button; + else if (e.which) + value = e.which; + + if (value == 1) + { + obj.dragging_last = obj.getCoords(e); + obj.dragging_active = true; + obj.click = true; + } + + return false; + } + + /** Event handler for mouse up. + * + * @param e Event object. + */ + obj.mouseup = function (e) + { + obj.dragging_active = false; + + if (obj.click) + return obj.mouseclick(e); + else + return false; + } + + /** Function to get the coordinates of a point corrected for the offset of the viewport. + * + * @param e Point. + * @returns Coordinates of the point corrected for the offset of the viewport. + */ + obj.getCoords = function (e) + { + var svgPoint = document.documentElement.createSVGPoint(); + svgPoint.x = e.clientX + window.pageXOffset; + svgPoint.y = e.clientY + window.pageYOffset; + + return svgPoint; + } + + /** Event handler for scrolling. + * + * @param e Event object. + */ + obj.mousewheel = function(e) + { + var p = obj.projectCoords(obj.getCoords(e)); + + if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1) + { + var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix); + } + + if (e.wheelDelta) + { // IE Opera + delta = e.wheelDelta/120; + } + else if (e.detail) + { // MOZ + delta = -e.detail/3; + } + + var widthOld = p.x * matrix.e11 + p.y * matrix.e12; + var heightOld = p.x * matrix.e21 + p.y * matrix.e22; + + matrix.e11 *= (1.0 - delta / 20.0); + matrix.e12 *= (1.0 - delta / 20.0); + matrix.e21 *= (1.0 - delta / 20.0); + matrix.e22 *= (1.0 - delta / 20.0); + + var widthNew = p.x * matrix.e11 + p.y * matrix.e12; + var heightNew = p.x * matrix.e21 + p.y * matrix.e22; + + matrix.e13 += (widthOld - widthNew); + matrix.e23 += (heightOld - heightNew); + + slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute()); + + return false; + } + + /** Function to project a point to screen coordinates. + * + * @param Point. + * @returns The point projected to screen coordinates. + */ + obj.projectCoords = function(pnt) + { + var matrix = slides[activeSlide]["element"].getScreenCTM(); + + if (slides[activeSlide]["viewGroup"]) + matrix = slides[activeSlide]["viewGroup"].getScreenCTM(); + + pnt = pnt.matrixTransform(matrix.inverse()); + return pnt; + } + + /** Function to convert a rectangle into a point matrix. + * + * The function figures out a rectangle that encloses the rectangle given and has the same width/height ratio as the viewport of the presentation. + * + * @param rect Rectangle. + * @return The upper left, upper right and lower right corner of the rectangle in a point matrix. + */ + obj.rectToMatrix = function(rect) + { + rectWidth = rect.getBBox().width; + rectHeight = rect.getBBox().height; + rectX = rect.getBBox().x; + rectY = rect.getBBox().y; + rectXcorr = 0; + rectYcorr = 0; + + scaleX = WIDTH / rectWidth; + scaleY = HEIGHT / rectHeight; + + if (scaleX > scaleY) + { + scaleX = scaleY; + rectXcorr -= (WIDTH / scaleX - rectWidth) / 2; + rectWidth = WIDTH / scaleX; + } + else + { + scaleY = scaleX; + rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2; + rectHeight = HEIGHT / scaleY; + } + + if (rect.transform.baseVal.numberOfItems < 1) + { + mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1); + } + else + { + mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix); + } + + newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1); + newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0); + + return mRectTrans.mult(newBasePoints.add(newVectors)); + } + + /** Function to return a transformation matrix from a point matrix. + * + * @param mPoints The point matrix. + * @returns The transformation matrix. + */ + obj.pointMatrixToTransformation = function(mPoints) + { + mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1); + + return mPointsOld.mult(mPoints.inv()); + } +} + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__noclick.out b/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__noclick.out new file mode 100644 index 0000000..c21263c --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_mouse_handler__--mouseSetting__noclick.out @@ -0,0 +1,94 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +// Copyright 2008, 2009 Hannes Hochreiner +// 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 3 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, see http://www.gnu.org/licenses/. + +// Add event listener for initialisation. +document.addEventListener("DOMContentLoaded", jessyInk_core_mouseHandler_noclick_init, false); + +/** Initialisation function. + * + * This function looks for the objects of the appropriate sub-type and hands them to another function that will add the required methods. + */ +function jessyInk_core_mouseHandler_noclick_init() +{ + var elems = document.getElementsByTagNameNS("https://launchpad.net/jessyink", "mousehandler"); + + for (var counter = 0; counter < elems.length; counter++) + { + if (elems[counter].getAttributeNS("https://launchpad.net/jessyink", "subtype") == "jessyInk_core_mouseHandler_noclick") + jessyInk_core_mouseHandler_noclick(elems[counter]); + } +} + +/** Function to initialise an object. + * + * @param obj Object to be initialised. + */ +function jessyInk_core_mouseHandler_noclick(obj) +{ + /** Function supplying a custom mouse handler. + * + * @returns A dictionary containing the new mouse handler functions. + */ + obj.getMouseHandler = function () + { + var handlerDictio = new Object(); + + handlerDictio[SLIDE_MODE] = new Object(); + handlerDictio[SLIDE_MODE][MOUSE_DOWN] = null; + + return handlerDictio; + } +} + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_summary.out b/share/extensions/tests/data/refs/jessyink_summary.out new file mode 100644 index 0000000..0c30d07 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_summary.out @@ -0,0 +1,10 @@ +JessyInk script version 1.5.5 installed. + +Slide 1: + Layer name: Slide3 + +Slide 2: + Layer name: Slide2 + +Slide 3: + Layer name: Slide1 diff --git a/share/extensions/tests/data/refs/jessyink_transitions__--layerName__Slide2.out b/share/extensions/tests/data/refs/jessyink_transitions__--layerName__Slide2.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/jessyink_uninstall.out b/share/extensions/tests/data/refs/jessyink_uninstall.out new file mode 100644 index 0000000..f3d83ab --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_uninstall.out @@ -0,0 +1,39 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_video.out b/share/extensions/tests/data/refs/jessyink_video.out new file mode 100644 index 0000000..664de1f --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_video.out @@ -0,0 +1,61 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + <replace this text with the url of the movie> + + + + + + + JessyInk video element + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jessyink_view__--id__r3__--viewOrder__1.out b/share/extensions/tests/data/refs/jessyink_view__--id__r3__--viewOrder__1.out new file mode 100644 index 0000000..dd07df6 --- /dev/null +++ b/share/extensions/tests/data/refs/jessyink_view__--id__r3__--viewOrder__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__gaussian__--end__false__--ctrl__true.out b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__gaussian__--end__false__--ctrl__true.out new file mode 100644 index 0000000..523c51f --- /dev/null +++ b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__gaussian__--end__false__--ctrl__true.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__lognorm__--radiusx__100__--ctrl__true.out b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__lognorm__--radiusx__100__--ctrl__true.out new file mode 100644 index 0000000..6aca453b --- /dev/null +++ b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__lognorm__--radiusx__100__--ctrl__true.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__pareto__--radiusy__100__--ctrl__true.out b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__pareto__--radiusy__100__--ctrl__true.out new file mode 100644 index 0000000..8c38359 --- /dev/null +++ b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__pareto__--radiusy__100__--ctrl__true.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__uniform__--ctrl__false.out b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__uniform__--ctrl__false.out new file mode 100644 index 0000000..f6425d2 --- /dev/null +++ b/share/extensions/tests/data/refs/jitternodes__--id__p1__--dist__uniform__--ctrl__false.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/layer2png.out b/share/extensions/tests/data/refs/layer2png.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/layer2png__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/layer2png__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/layers2svgfont__font_layers__svg.out b/share/extensions/tests/data/refs/layers2svgfont__font_layers__svg.out new file mode 100644 index 0000000..dcfd9f4 --- /dev/null +++ b/share/extensions/tests/data/refs/layers2svgfont__font_layers__svg.out @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/layers2svgfont__font_layers_apostrophe__svg.out b/share/extensions/tests/data/refs/layers2svgfont__font_layers_apostrophe__svg.out new file mode 100644 index 0000000..a8014f1 --- /dev/null +++ b/share/extensions/tests/data/refs/layers2svgfont__font_layers_apostrophe__svg.out @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lindenmayer.out b/share/extensions/tests/data/refs/lindenmayer.out new file mode 100644 index 0000000..ca0de7e --- /dev/null +++ b/share/extensions/tests/data/refs/lindenmayer.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lindenmayer__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/lindenmayer__--id__p1__--id__r3.out new file mode 100644 index 0000000..8c2ec7d --- /dev/null +++ b/share/extensions/tests/data/refs/lindenmayer__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lindenmayer__--rules__F__F-E__F__E-F__E__EE__--axiom__F-E-E__--order__3__--langle__120__--rangle__120.out b/share/extensions/tests/data/refs/lindenmayer__--rules__F__F-E__F__E-F__E__EE__--axiom__F-E-E__--order__3__--langle__120__--rangle__120.out new file mode 100644 index 0000000..8c2852a --- /dev/null +++ b/share/extensions/tests/data/refs/lindenmayer__--rules__F__F-E__F__E-F__E__EE__--axiom__F-E-E__--order__3__--langle__120__--rangle__120.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lindenmayer__--rules__F__F__F--F__F__--axiom__F__--order__1__--langle__60__--rangle__60.out b/share/extensions/tests/data/refs/lindenmayer__--rules__F__F__F--F__F__--axiom__F__--order__1__--langle__60__--rangle__60.out new file mode 100644 index 0000000..d0526d3 --- /dev/null +++ b/share/extensions/tests/data/refs/lindenmayer__--rules__F__F__F--F__F__--axiom__F__--order__1__--langle__60__--rangle__60.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum.out b/share/extensions/tests/data/refs/lorem_ipsum.out new file mode 100644 index 0000000..a2abd4d --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum.out @@ -0,0 +1,49 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam molestie nisl at metus. Mauris ac massa vestibulum nisl facilisis viverra. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Sed quis elit. Mauris sed nulla quis nisi interdum tempor. Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. Integer tempus malesuada pede. Maecenas rhoncus rhoncus ipsum. Mauris ac massa vestibulum nisl facilisis viverra. Suspendisse fermentum. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Nam id neque. Nulla blandit justo a metus. Nam laoreet dui sed magna. Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. Phasellus at purus sed purus cursus iaculis. Vivamus feugiat. Integer fringilla. Praesent a eros. Aliquam sed erat. Nam a nunc. Maecenas rhoncus rhoncus ipsum. + +Praesent scelerisque. Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. Etiam cursus purus interdum libero. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Suspendisse fermentum. Sed at turpis vitae velit euismod aliquet. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. Nam a nunc. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Aliquam metus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. Mauris tincidunt aliquam ante. Mauris et pede. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Donec ut purus. Integer accumsan. Morbi volutpat. Suspendisse potenti. Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. + +Aenean luctus vulputate turpis. Pellentesque convallis dolor vel libero. Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. Etiam non neque ac mi vestibulum placerat. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Phasellus at purus sed purus cursus iaculis. Phasellus lacinia iaculis mi. Mauris tempor ultrices justo. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Nam id neque. Fusce venenatis ligula in pede. Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. Suspendisse lectus. Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. Pellentesque suscipit accumsan massa. Aliquam metus. + +Cras ac enim vel dui vestibulum suscipit. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. Integer accumsan. Nam id neque. Donec at diam a tellus dignissim vestibulum. Donec ut urna. Pellentesque ac turpis. Phasellus hendrerit. Nulla sed lacus. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. Nam pharetra. Nulla sagittis condimentum ligula. Nam malesuada sapien eu nibh. Sed a lorem ut est tincidunt consectetuer. Sed dolor. Donec ut purus. Phasellus hendrerit. Mauris et pede. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Nulla sagittis condimentum ligula. Aliquam imperdiet lobortis metus. Integer accumsan. Donec interdum vestibulum libero. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. + +Donec interdum vestibulum libero. Nam molestie nisl at metus. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Aliquam imperdiet lobortis metus. Nam consectetuer mollis dolor. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Integer tempus malesuada pede. Nam laoreet dui sed magna. Donec sit amet enim. Mauris et dolor. Ut eu metus id lectus vestibulum ultrices. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Pellentesque sit amet dui vel justo gravida auctor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Fusce venenatis ligula in pede. Suspendisse potenti. Quisque vehicula porttitor odio. Praesent a lacus vitae turpis consequat semper. Praesent scelerisque. Pellentesque viverra dolor non nunc. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Mauris sed nulla quis nisi interdum tempor. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Donec ut urna. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum__--id__r1.out b/share/extensions/tests/data/refs/lorem_ipsum__--id__r1.out new file mode 100644 index 0000000..94ac537 --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum__--id__r1.out @@ -0,0 +1,49 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam cursus purus interdum libero. Fusce nonummy commodo dui. Pellentesque convallis dolor vel libero. Phasellus auctor enim eget sem. Donec ut urna. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Quisque pretium rutrum ligula. Praesent scelerisque. Suspendisse lectus. Sed non ipsum. Sed a lorem ut est tincidunt consectetuer. Nullam venenatis gravida orci. Fusce consectetuer tellus ut nisl. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. In hac habitasse platea dictumst. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Aenean ligula. Praesent a eros. Pellentesque et arcu. Donec sit amet enim. Donec nonummy lacinia leo. + +Vestibulum non arcu a ante feugiat vestibulum. Maecenas rhoncus rhoncus ipsum. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Praesent semper, neque vel condimentum hendrerit, lectus elit pretiumligula, nec consequat nisl velit at dui. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. In hac habitasse platea dictumst. Maecenas rhoncus rhoncus ipsum. Integer fringilla. Etiam sodales orci nec ligula. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Donec interdum vestibulum libero. Ut eu metus id lectus vestibulum ultrices. Pellentesque et arcu. Mauris et dolor. Integer accumsan. Maecenas rhoncus rhoncus ipsum. In hac habitasse platea dictumst. Quisque vehicula porttitor odio. Pellentesque et arcu. Mauris tempus diam. Fusce nonummy commodo dui. + +Morbi pulvinar nulla sit amet nisl. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Quisque malesuada nulla sed pede volutpat pulvinar. Ut venenatis. Donec sit amet enim. Vivamus nisi elit, nonummy id, facilisis non, blandit ac, dolor. Aenean scelerisque metus eget sem. Mauris tincidunt aliquam ante. Pellentesque suscipit accumsan massa. Quisque malesuada nulla sed pede volutpat pulvinar. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Pellentesque ac turpis. Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales sapien, sit amet posuere quam purus at lacus. Ut eu metus id lectus vestibulum ultrices. Sed at turpis vitae velit euismod aliquet. Mauris tempus diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam molestie nisl at metus. Aliquam imperdiet lobortis metus. + +Mauris tempus diam. Integer porta. Quisque malesuada nulla sed pede volutpat pulvinar. Suspendisse lectus. Phasellus hendrerit. Quisque vehicula porttitor odio. Praesent a eros. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Nulla sed lacus. Integer fringilla. Phasellus lacinia iaculis mi. Vestibulum non arcu a ante feugiat vestibulum. Aliquam sed erat. Aenean ligula. Mauris et pede. Vestibulum non arcu a ante feugiat vestibulum. Donec rutrum venenatis dui. Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. Sed dolor. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Nam rhoncus, lectus vel hendrerit congue, nisl lorem feugiat ante, in fermentum erat nulla tristique arcu. + +Pellentesque sit amet dui vel justo gravida auctor. Pellentesque tempor. Maecenas justo. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. Nam consectetuer mollis dolor. Pellentesque tempor. Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales sapien, sit amet posuere quam purus at lacus. Aenean luctus vulputate turpis. Mauris et dolor. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Pellentesque convallis dolor vel libero. Donec sit amet enim. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Sed a lorem ut est tincidunt consectetuer. Cras ac enim vel dui vestibulum suscipit. Cras gravida. Quisque pretium rutrum ligula. Curabitur accumsan felis in erat. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Donec tempus quam quis neque. Sed a lorem ut est tincidunt consectetuer. Praesent a eros. In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. Curabitur tincidunt tellus nec purus. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum__--id__r1__--svg2__false.out b/share/extensions/tests/data/refs/lorem_ipsum__--id__r1__--svg2__false.out new file mode 100644 index 0000000..82a61d9 --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum__--id__r1__--svg2__false.out @@ -0,0 +1,42 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Aliquam imperdiet lobortis metus. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Ut venenatis. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Phasellus auctor enim eget sem. Mauris tincidunt aliquam ante. Pellentesque sit amet dui vel justo gravida auctor. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Vivamus feugiat. Mauris ac massa vestibulum nisl facilisis viverra. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Curabitur accumsan felis in erat. Mauris ac massa vestibulum nisl facilisis viverra. Aenean scelerisque metus eget sem. In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. Etiam pede nunc, vestibulum vel, rutrum et, tincidunt eu, enim. Donec ut purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. Sed non ipsum. Nam molestie nisl at metus. Phasellus hendrerit. Suspendisse potenti. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. Suspendisse potenti. Praesent a eros. Donec sit amet enim. Sed non ipsum. Mauris sed nulla quis nisi interdum tempor. Donec at diam a tellus dignissim vestibulum. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Phasellus lacinia iaculis mi. Fusce consectetuer tellus ut nisl. Nam a nunc. Sed a lorem ut est tincidunt consectetuer. Phasellus at purus sed purus cursus iaculis. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Mauris ac massa vestibulum nisl facilisis viverra. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Fusce consectetuer tellus ut nisl. Vivamus feugiat. In commodo, dolor quis fermentum ullamcorper, urna massa volutpat massa, vitae mattis purus arcu nec nulla. Aenean ultrices turpis. Nulla blandit justo a metus. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Integer fringilla. Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. Aliquam vel nibh. Morbi a mauris. Suspendisse potenti. Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. Nam id neque. Integer fringilla. Nullam venenatis gravida orci. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Nam laoreet dui sed magna. Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac pretium nisl lectus at magna. Donec sit amet enim. Nam consectetuer mollis dolor. Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. Aenean scelerisque metus eget sem. Cras gravida. Nam pharetra. Suspendisse venenatis. Vivamus nisi elit, nonummy id, facilisis non, blandit ac, dolor. Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac pretium nisl lectus at magna. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. In commodo, dolor quis fermentum ullamcorper, urna massa volutpat massa, vitae mattis purus arcu nec nulla. Donec rutrum venenatis dui. Cras gravida. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Quisque dictum quam vel neque. Maecenas rhoncus rhoncus ipsum. Vestibulum non arcu a ante feugiat vestibulum. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. Praesent scelerisque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta est, eget sollicitudin lectus lectus eget lacus. Mauris sed nulla quis nisi interdum tempor. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Suspendisse viverra placerat tortor. Nam a nunc. Pellentesque et arcu. Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. Suspendisse viverra placerat tortor. Etiam sodales orci nec ligula. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Fusce consectetuer tellus ut nisl. Nulla sagittis condimentum ligula. Suspendisse lectus. Suspendisse lectus. Maecenas viverra. In hac habitasse platea dictumst. Praesent a eros. Fusce venenatis ligula in pede. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Mauris ac massa vestibulum nisl facilisis viverra. + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum__--id__t4.out b/share/extensions/tests/data/refs/lorem_ipsum__--id__t4.out new file mode 100644 index 0000000..ff93f65 --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum__--id__t4.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wrapsLorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque ac turpis. Nam pharetra. Vestibulum non arcu a ante feugiat vestibulum. Sed at turpis vitae velit euismod aliquet. Mauris tempus diam. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. Morbi urna. Integer accumsan. Phasellus hendrerit. Quisque facilisis, urna sit amet pulvinar mollis, purus arcu adipiscing velit, non condimentum diam purus eu massa. Mauris tempus diam. Suspendisse lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. Praesent semper, neque vel condimentum hendrerit, lectus elit pretiumligula, nec consequat nisl velit at dui. Nam pharetra. Suspendisse viverra placerat tortor. Nulla sagittis condimentum ligula. Sed fringilla. Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. Aenean scelerisque metus eget sem. Donec rutrum venenatis dui. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Integer accumsan. In leo ante, venenatis eu, volutpat ut, imperdiet auctor, enim. Nam consectetuer mollis dolor. Nam consectetuer mollis dolor. Maecenas viverra. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Donec interdum vestibulum libero. Sed elementum, felis quis porttitor sollicitudin, augue nulla sodales sapien, sit amet posuere quam purus at lacus. Praesent scelerisque. Sed a lorem ut est tincidunt consectetuer. Quisque facilisis, urna sit amet pulvinar mollis, purus arcu adipiscing velit, non condimentum diam purus eu massa. Morbi volutpat. Mauris et pede. Suspendisse venenatis. Aliquam sed erat. Praesent scelerisque. Curabitur nunc ante, ullamcorper vel, auctor a, aliquam at, tortor. Suspendisse viverra placerat tortor. Phasellus at purus sed purus cursus iaculis. Nunc metus. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Nam nisl quam, posuere non, volutpat sed, semper vitae, magna. Curabitur nunc ante, ullamcorper vel, auctor a, aliquam at, tortor. Ut eu metus id lectus vestibulum ultrices. Suspendisse lectus. Nam id neque. Aliquam metus. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Quisque pretium rutrum ligula. Sed dolor. Donec at diam a tellus dignissim vestibulum. Integer fringilla. Praesent a lacus vitae turpis consequat semper. Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. Praesent scelerisque. Pellentesque convallis dolor vel libero. Aliquam vel nibh. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Donec interdum vestibulum libero. Aliquam imperdiet lobortis metus. Aenean luctus vulputate turpis. Nam sed nisl nec elit suscipit ullamcorper. Morbi a mauris. Etiam non neque ac mi vestibulum placerat. Sed non ipsum. Mauris et pede. Cras facilisis felis sit amet lorem. Aenean luctus vulputate turpis. Integer porta. Vivamus quis mi. Maecenas convallis dui. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Suspendisse potenti. Aliquam sed erat. Praesent semper, neque vel condimentum hendrerit, lectus elit pretiumligula, nec consequat nisl velit at dui. Suspendisse potenti. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Aenean id purus. Vivamus quis mi. Vestibulum viverra varius enim. Morbi volutpat. Phasellus lacinia iaculis mi. Curabitur tincidunt tellus nec purus. Praesent aliquet, neque pretium congue mattis, ipsum augue dignissim ante, ac pretium nisl lectus at magna. Aliquam vel nibh. UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum__--svg2__false.out b/share/extensions/tests/data/refs/lorem_ipsum__--svg2__false.out new file mode 100644 index 0000000..243a8f1 --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum__--svg2__false.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In hac habitasse platea dictumst. Integer accumsan. Vestibulum viverra varius enim. Phasellus lacinia iaculis mi. Cras gravida. Pellentesque sit amet dui vel justo gravida auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Aenean scelerisque metus eget sem. Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. Vivamus feugiat. Cras gravida. Nam pharetra. Cras gravida. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Donec tempus quam quis neque. Donec tempus quam quis neque. Aliquam imperdiet lobortis metus. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Mauris ac massa vestibulum nisl facilisis viverra. Nulla sagittis condimentum ligula. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Aliquam metus. Sed dolor. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Nam pharetra. Donec interdum vestibulum libero. Pellentesque condimentum felis a sem. Suspendisse potenti. Donec ut urna. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Pellentesque ac turpis. Nam sed nisl nec elit suscipit ullamcorper. Donec ut urna. Fusce nonummy commodo dui. Etiam non neque ac mi vestibulum placerat. Morbi a mauris. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Pellentesque suscipit accumsan massa. Etiam non neque ac mi vestibulum placerat. Donec sit amet enim. Suspendisse potenti. Mauris sed nulla quis nisi interdum tempor. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Nam laoreet dui sed magna. Nulla blandit justo a metus. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Morbi pulvinar nulla sit amet nisl. Aliquam metus. Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Nam rhoncus, lectus vel hendrerit congue, nisl lorem feugiat ante, in fermentum erat nulla tristique arcu. Nullam sapien mauris, venenatis at, fermentum at, tempus eu, urna. Suspendisse lectus. Quisque pretium rutrum ligula. Etiam sodales orci nec ligula. Donec ut purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta est, eget sollicitudin lectus lectus eget lacus. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Vestibulum viverra varius enim. Suspendisse molestie sem. Sed fringilla. Aliquam metus. Vivamus feugiat. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. Aenean scelerisque metus eget sem. Suspendisse fermentum. Mauris ac massa vestibulum nisl facilisis viverra. Suspendisse potenti. Phasellus hendrerit. In tempus urna. Morbi volutpat. Nam id neque. Donec sit amet enim. Phasellus at purus sed purus cursus iaculis. Phasellus auctor enim eget sem. Mauris et pede. Aenean luctus vulputate turpis. Nam consectetuer mollis dolor. Nam id neque. Curabitur tincidunt tellus nec purus. Mauris tincidunt aliquam ante. Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. Donec rutrum venenatis dui. Quisque dictum quam vel neque. Sed a lorem ut est tincidunt consectetuer. Mauris tincidunt aliquam ante. Morbi a mauris. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Suspendisse potenti. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Donec ut purus. Sed at turpis vitae velit euismod aliquet. Nunc in turpis ac lacus eleifend sagittis. Suspendisse fermentum. Pellentesque sit amet dui vel justo gravida auctor. Morbi a mauris. Nulla facilisi. Mauris tempus diam. Donec nonummy lacinia leo. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Aenean ultrices turpis. Cras facilisis felis sit amet lorem. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Sed quis elit. Nulla blandit justo a metus. Quisque vehicula porttitor odio. Integer accumsan. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Nam sed nisl nec elit suscipit ullamcorper. Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. Morbi pulvinar nulla sit amet nisl. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Cras facilisis felis sit amet lorem. Fusce venenatis ligula in pede. Aliquam sed erat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec gravida, ante vel ornare lacinia, orci enim porta est, eget sollicitudin lectus lectus eget lacus. + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/lorem_ipsum__--svg2__true.out b/share/extensions/tests/data/refs/lorem_ipsum__--svg2__true.out new file mode 100644 index 0000000..e47873a --- /dev/null +++ b/share/extensions/tests/data/refs/lorem_ipsum__--svg2__true.out @@ -0,0 +1,42 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam molestie nisl at metus. Mauris ac massa vestibulum nisl facilisis viverra. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Sed quis elit. Mauris sed nulla quis nisi interdum tempor. Proin dolor sapien, adipiscing id, sagittis eu, molestie viverra, mauris. Integer tempus malesuada pede. Maecenas rhoncus rhoncus ipsum. Mauris ac massa vestibulum nisl facilisis viverra. Suspendisse fermentum. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Nam id neque. Nulla blandit justo a metus. Nam laoreet dui sed magna. Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. Phasellus at purus sed purus cursus iaculis. Vivamus feugiat. Integer fringilla. Praesent a eros. Aliquam sed erat. Nam a nunc. Maecenas rhoncus rhoncus ipsum. + +Praesent scelerisque. Proin lectus orci, venenatis pharetra, egestas id, tincidunt vel, eros. Etiam cursus purus interdum libero. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Suspendisse fermentum. Sed at turpis vitae velit euismod aliquet. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. Nam a nunc. Duis sem velit, ultrices et, fermentum auctor, rhoncus ut, ligula. Aliquam metus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. Mauris tincidunt aliquam ante. Mauris et pede. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. Donec ut purus. Integer accumsan. Morbi volutpat. Suspendisse potenti. Vivamus posuere, ante eu tempor dictum, felis nibh facilisis sem, eu auctor metus nulla non lorem. + +Aenean luctus vulputate turpis. Pellentesque convallis dolor vel libero. Quisque arcu ante, cursus in, ornare quis, viverra ut, justo. Etiam non neque ac mi vestibulum placerat. Mauris urna sem, suscipit vitae, dignissim id, ultrices sed, nunc. Phasellus at purus sed purus cursus iaculis. Phasellus lacinia iaculis mi. Mauris tempor ultrices justo. Nam massa turpis, nonummy et, consectetuer id, placerat ac, ante. Nam id neque. Fusce venenatis ligula in pede. Nullam libero nunc, tristique eget, laoreet eu, sagittis id, ante. Suspendisse lectus. Phasellus nisi metus, tempus sit amet, ultrices ac, porta nec, felis. Pellentesque suscipit accumsan massa. Aliquam metus. + +Cras ac enim vel dui vestibulum suscipit. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus eu orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse potenti. Integer accumsan. Nam id neque. Donec at diam a tellus dignissim vestibulum. Donec ut urna. Pellentesque ac turpis. Phasellus hendrerit. Nulla sed lacus. Aenean justo ipsum, luctus ut, volutpat laoreet, vehicula in, libero. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. Nam pharetra. Nulla sagittis condimentum ligula. Nam malesuada sapien eu nibh. Sed a lorem ut est tincidunt consectetuer. Sed dolor. Donec ut purus. Phasellus hendrerit. Mauris et pede. Donec diam eros, tristique sit amet, pretium vel, pellentesque ut, neque. Aenean turpis ipsum, rhoncus vitae, posuere vitae, euismod sed, ligula. Nulla sagittis condimentum ligula. Aliquam imperdiet lobortis metus. Integer accumsan. Donec interdum vestibulum libero. Curabitur risus urna, placerat et, luctus pulvinar, auctor vel, orci. + +Donec interdum vestibulum libero. Nam molestie nisl at metus. In consectetuer, lorem eu lobortis egestas, velit odio imperdiet eros, sit amet sagittis nunc mi ac neque. Phasellus magna sem, vulputate eget, ornare sed, dignissim sit amet, pede. Aliquam imperdiet lobortis metus. Nam consectetuer mollis dolor. Curabitur lorem risus, sagittis vitae, accumsan a, iaculis id, metus. Integer tempus malesuada pede. Nam laoreet dui sed magna. Donec sit amet enim. Mauris et dolor. Ut eu metus id lectus vestibulum ultrices. Quisque aliquam, nulla ac scelerisque convallis, nisi ligula sagittis risus, at nonummy arcu urna pulvinar nibh. Pellentesque sit amet dui vel justo gravida auctor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Fusce venenatis ligula in pede. Suspendisse potenti. Quisque vehicula porttitor odio. Praesent a lacus vitae turpis consequat semper. Praesent scelerisque. Pellentesque viverra dolor non nunc. Aliquam justo lectus, iaculis a, auctor sed, congue in, nisl. Mauris sed nulla quis nisi interdum tempor. Aliquam velit dui, commodo quis, porttitor eget, convallis et, nisi. Donec ut urna. Morbi turpis arcu, egestas congue, condimentum quis, tristique cursus, leo. \ No newline at end of file diff --git a/share/extensions/tests/data/refs/markers_strokepaint__--tab____custom____--id__dimension__--type__stroke.out b/share/extensions/tests/data/refs/markers_strokepaint__--tab____custom____--id__dimension__--type__stroke.out new file mode 100644 index 0000000..0a85c09 --- /dev/null +++ b/share/extensions/tests/data/refs/markers_strokepaint__--tab____custom____--id__dimension__--type__stroke.out @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/markers_strokepaint__--tab____object____--id__dimension__--type__stroke.out b/share/extensions/tests/data/refs/markers_strokepaint__--tab____object____--id__dimension__--type__stroke.out new file mode 100644 index 0000000..070a6e8 --- /dev/null +++ b/share/extensions/tests/data/refs/markers_strokepaint__--tab____object____--id__dimension__--type__stroke.out @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--id__p1__--id__p2__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--id__p1__--id__p2__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..179cbf8 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--id__p1__--id__p2__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 123.48 mm141.14 mm + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_bbox__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_bbox__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..ec3aa85 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_bbox__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 141.14 mm + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..09774b9 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,34 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + 54.15 mm + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..7b61804 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__FT_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 123.48 mm + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_end__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_end__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..6ef1b7c --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_end__--id__p2__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 141.14 mm + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..a21eb63 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__D__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,34 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + 54.15 mm + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..da1b409 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--method__presets__--presetFormat__TaP_start__--id__p1__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 123.48 mm + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--type__area__--id__p1__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--type__area__--id__p1__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..65d9a94 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--type__area__--id__p1__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + 0.0 mm2 + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/measure__--type__cofm__--id__D__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--type__cofm__--id__D__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..6779ab0 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--type__cofm__--id__D__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,34 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/measure__--type__cofm__--id__c3__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out b/share/extensions/tests/data/refs/measure__--type__cofm__--id__c3__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out new file mode 100644 index 0000000..9deca59 --- /dev/null +++ b/share/extensions/tests/data/refs/measure__--type__cofm__--id__c3__--presetFormat__TaP_start__--fontsize__20__--unit__mm__--scale__1__1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/merge_styles__--id__c2__--id__c3.out b/share/extensions/tests/data/refs/merge_styles__--id__c2__--id__c3.out new file mode 100644 index 0000000..13c7bbc --- /dev/null +++ b/share/extensions/tests/data/refs/merge_styles__--id__c2__--id__c3.out @@ -0,0 +1,46 @@ + + + + + + +.css5815 { + display:inline; + stroke-width:16; +} + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/motion__--id__c3__--id__p2.out b/share/extensions/tests/data/refs/motion__--id__c3__--id__p2.out new file mode 100644 index 0000000..aff7cc7 --- /dev/null +++ b/share/extensions/tests/data/refs/motion__--id__c3__--id__p2.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/motion__--magnitude__2__--angle__45__--fillwithstroke__True__--id__path23053__--id__path28636.out b/share/extensions/tests/data/refs/motion__--magnitude__2__--angle__45__--fillwithstroke__True__--id__path23053__--id__path28636.out new file mode 100644 index 0000000..0412348 --- /dev/null +++ b/share/extensions/tests/data/refs/motion__--magnitude__2__--angle__45__--fillwithstroke__True__--id__path23053__--id__path28636.out @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/new_glyph_layer.out b/share/extensions/tests/data/refs/new_glyph_layer.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/new_glyph_layer__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/new_glyph_layer__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/next_glyph_layer.out b/share/extensions/tests/data/refs/next_glyph_layer.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/next_glyph_layer__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/next_glyph_layer__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out new file mode 100644 index 0000000..3374868 --- /dev/null +++ b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + +JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember1978 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__pie__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__pie__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out new file mode 100644 index 0000000..cb8d23f --- /dev/null +++ b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__pie__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + +JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember1978 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__stbar__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__stbar__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out new file mode 100644 index 0000000..d7fe426 --- /dev/null +++ b/share/extensions/tests/data/refs/nicechart__--file__DAT_DIR__io__nicechart_01__csv__--type__stbar__--blur__True__--headings__True__--font-color__black__--what__22__11__67.out @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + +JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember1978 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/nicechart__3afa80cf55d99e9c0ea691c780458309.out b/share/extensions/tests/data/refs/nicechart__3afa80cf55d99e9c0ea691c780458309.out new file mode 100644 index 0000000..2bfbbf0 --- /dev/null +++ b/share/extensions/tests/data/refs/nicechart__3afa80cf55d99e9c0ea691c780458309.out @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + +JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember1978 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/output_scour.out b/share/extensions/tests/data/refs/output_scour.out new file mode 100644 index 0000000..6b54e20 --- /dev/null +++ b/share/extensions/tests/data/refs/output_scour.out @@ -0,0 +1,40 @@ + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps + UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/param_curves__--id__p1__--id__r3__-s__8__--isoscale__True__--drawaxis__True.out b/share/extensions/tests/data/refs/param_curves__--id__p1__--id__r3__-s__8__--isoscale__True__--drawaxis__True.out new file mode 100644 index 0000000..c5acfe7 --- /dev/null +++ b/share/extensions/tests/data/refs/param_curves__--id__p1__--id__r3__-s__8__--isoscale__True__--drawaxis__True.out @@ -0,0 +1,40 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/param_curves__-s__8__--isoscale__True__--drawaxis__True.out b/share/extensions/tests/data/refs/param_curves__-s__8__--isoscale__True__--drawaxis__True.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/path_envelope__--id__obj__--id__envelope.out b/share/extensions/tests/data/refs/path_envelope__--id__obj__--id__envelope.out new file mode 100644 index 0000000..37c35bc --- /dev/null +++ b/share/extensions/tests/data/refs/path_envelope__--id__obj__--id__envelope.out @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_envelope__--id__text__--id__envelope.out b/share/extensions/tests/data/refs/path_envelope__--id__text__--id__envelope.out new file mode 100644 index 0000000..d82aee7 --- /dev/null +++ b/share/extensions/tests/data/refs/path_envelope__--id__text__--id__envelope.out @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__faces.out b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__faces.out new file mode 100644 index 0000000..221aae9 --- /dev/null +++ b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__faces.out @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__gridlines.out b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__gridlines.out new file mode 100644 index 0000000..f315d5e --- /dev/null +++ b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__gridlines.out @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__meshpatches.out b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__meshpatches.out new file mode 100644 index 0000000..5bf081b --- /dev/null +++ b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__meshpatches.out @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__outline.out b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__outline.out new file mode 100644 index 0000000..b4c9fe0 --- /dev/null +++ b/share/extensions/tests/data/refs/path_mesh_m2p__--id__mesh1__--mode__outline.out @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_mesh_p2m__--id__path1__--id__path9.out b/share/extensions/tests/data/refs/path_mesh_p2m__--id__path1__--id__path9.out new file mode 100644 index 0000000..6f6773f --- /dev/null +++ b/share/extensions/tests/data/refs/path_mesh_p2m__--id__path1__--id__path9.out @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_number_nodes__--id__D.out b/share/extensions/tests/data/refs/path_number_nodes__--id__D.out new file mode 100644 index 0000000..ab2102a --- /dev/null +++ b/share/extensions/tests/data/refs/path_number_nodes__--id__D.out @@ -0,0 +1,33 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + 1234567 + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_number_nodes__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/path_number_nodes__--id__p1__--id__r3.out new file mode 100644 index 0000000..c3b1c5d --- /dev/null +++ b/share/extensions/tests/data/refs/path_number_nodes__--id__p1__--id__r3.out @@ -0,0 +1,40 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + 1234 + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_to_absolute__--id__c1__--id__c2__--id__c3.out b/share/extensions/tests/data/refs/path_to_absolute__--id__c1__--id__c2__--id__c3.out new file mode 100644 index 0000000..e904237 --- /dev/null +++ b/share/extensions/tests/data/refs/path_to_absolute__--id__c1__--id__c2__--id__c3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_to_absolute__--id__p1__--id__p2__--id__s1__--id__u1.out b/share/extensions/tests/data/refs/path_to_absolute__--id__p1__--id__p2__--id__s1__--id__u1.out new file mode 100644 index 0000000..8fbffb2 --- /dev/null +++ b/share/extensions/tests/data/refs/path_to_absolute__--id__p1__--id__p2__--id__s1__--id__u1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect.out b/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect.out new file mode 100644 index 0000000..33edebd --- /dev/null +++ b/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect1.out b/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect1.out new file mode 100644 index 0000000..72e29de --- /dev/null +++ b/share/extensions/tests/data/refs/path_to_absolute__--id__r1__--id__r2__--id__r3__--id__slicerect1.out @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated__--kind__Snake__--id__g3427__--id__path2551.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated__--kind__Snake__--id__g3427__--id__path2551.out new file mode 100644 index 0000000..483726d --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated__--kind__Snake__--id__g3427__--id__path2551.out @@ -0,0 +1,101 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--id__g4054__--id__path4056.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--id__g4054__--id__path4056.out new file mode 100644 index 0000000..6622d5e --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--id__g4054__--id__path4056.out @@ -0,0 +1,117 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--vertical__True__--id__g3961__--id__path10007.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--vertical__True__--id__g3961__--id__path10007.out new file mode 100644 index 0000000..d6a315f --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Ribbon__--vertical__True__--id__g3961__--id__path10007.out @@ -0,0 +1,108 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Snake__--noffset__5__--space__5__--id__path2408__--id__path2405.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Snake__--noffset__5__--space__5__--id__path2408__--id__path2405.out new file mode 100644 index 0000000..62e5ba9 --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Repeated____stretched__--kind__Snake__--noffset__5__--space__5__--id__path2408__--id__path2405.out @@ -0,0 +1,98 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Single__--duplicate__True__--kind__Snake__--id__g5848__--id__path3336.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single__--duplicate__True__--kind__Snake__--id__g5848__--id__path3336.out new file mode 100644 index 0000000..ea16422 --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single__--duplicate__True__--kind__Snake__--id__g5848__--id__path3336.out @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__path4585__--id__path4608__--id__path4610__--id__path4612.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__path4585__--id__path4608__--id__path4610__--id__path4612.out new file mode 100644 index 0000000..1012962 --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__path4585__--id__path4608__--id__path4610__--id__path4612.out @@ -0,0 +1,98 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__text4418__--id__path4412.out b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__text4418__--id__path4412.out new file mode 100644 index 0000000..c151f76 --- /dev/null +++ b/share/extensions/tests/data/refs/pathalongpath__--copymode__Single____stretched__--kind__Snake__--id__text4418__--id__path4412.out @@ -0,0 +1,121 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__False__--follow__False.out b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__False__--follow__False.out new file mode 100644 index 0000000..f8d0f71 --- /dev/null +++ b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__False__--follow__False.out @@ -0,0 +1,158 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--copymode__copy__--grouppick__True__--pickmode__seq.out b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--copymode__copy__--grouppick__True__--pickmode__seq.out new file mode 100644 index 0000000..0bf037e --- /dev/null +++ b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--copymode__copy__--grouppick__True__--pickmode__seq.out @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--rotate__True__--copymode__clone.out b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--rotate__True__--copymode__clone.out new file mode 100644 index 0000000..cac8ad1 --- /dev/null +++ b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--rotate__True__--copymode__clone.out @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--space__10.out b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--space__10.out new file mode 100644 index 0000000..4382d7e --- /dev/null +++ b/share/extensions/tests/data/refs/pathscatter__--id__g12668__--id__path8143__--stretch__True__--space__10.out @@ -0,0 +1,74 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pathscatter__--id__path3990__--id__path3982__--stretch__True__--follow__True__--copymode__copy.out b/share/extensions/tests/data/refs/pathscatter__--id__path3990__--id__path3982__--stretch__True__--follow__True__--copymode__copy.out new file mode 100644 index 0000000..6f1ecf5 --- /dev/null +++ b/share/extensions/tests/data/refs/pathscatter__--id__path3990__--id__path3982__--stretch__True__--follow__True__--copymode__copy.out @@ -0,0 +1,65 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pdflatex__--font_size__15.out b/share/extensions/tests/data/refs/pdflatex__--font_size__15.out new file mode 100644 index 0000000..e71064f --- /dev/null +++ b/share/extensions/tests/data/refs/pdflatex__--font_size__15.out @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pdflatex__--font_size__15__--standalone__False.out b/share/extensions/tests/data/refs/pdflatex__--font_size__15__--standalone__False.out new file mode 100644 index 0000000..1371e43 --- /dev/null +++ b/share/extensions/tests/data/refs/pdflatex__--font_size__15__--standalone__False.out @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pdflatex__--font_size__20__--formule________frac__1____sqrt__5______2______.out b/share/extensions/tests/data/refs/pdflatex__--font_size__20__--formule________frac__1____sqrt__5______2______.out new file mode 100644 index 0000000..e862eec --- /dev/null +++ b/share/extensions/tests/data/refs/pdflatex__--font_size__20__--formule________frac__1____sqrt__5______2______.out @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pdflatex__--font_size__20__--standalone__False__--formule________frac__1____sqrt__5______2______.out b/share/extensions/tests/data/refs/pdflatex__--font_size__20__--standalone__False__--formule________frac__1____sqrt__5______2______.out new file mode 100644 index 0000000..1ec3d22 --- /dev/null +++ b/share/extensions/tests/data/refs/pdflatex__--font_size__20__--standalone__False__--formule________frac__1____sqrt__5______2______.out @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pdflatex__0355ed68ae6ec25166e664512ef53660.out b/share/extensions/tests/data/refs/pdflatex__0355ed68ae6ec25166e664512ef53660.out new file mode 100644 index 0000000..4f629c0 --- /dev/null +++ b/share/extensions/tests/data/refs/pdflatex__0355ed68ae6ec25166e664512ef53660.out @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/perfectboundcover.out b/share/extensions/tests/data/refs/perfectboundcover.out new file mode 100644 index 0000000..df88e21 --- /dev/null +++ b/share/extensions/tests/data/refs/perfectboundcover.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/perspective__--id__obj__--id__envelope.out b/share/extensions/tests/data/refs/perspective__--id__obj__--id__envelope.out new file mode 100644 index 0000000..df50e03 --- /dev/null +++ b/share/extensions/tests/data/refs/perspective__--id__obj__--id__envelope.out @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/perspective__--id__p1__--id__p2.out b/share/extensions/tests/data/refs/perspective__--id__p1__--id__p2.out new file mode 100644 index 0000000..b7497dc --- /dev/null +++ b/share/extensions/tests/data/refs/perspective__--id__p1__--id__p2.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/perspective__--id__text__--id__envelope.out b/share/extensions/tests/data/refs/perspective__--id__text__--id__envelope.out new file mode 100644 index 0000000..5093cdd --- /dev/null +++ b/share/extensions/tests/data/refs/perspective__--id__text__--id__envelope.out @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pixelsnap__--id__p1__--id__r3__--snap_to__bl.out b/share/extensions/tests/data/refs/pixelsnap__--id__p1__--id__r3__--snap_to__bl.out new file mode 100644 index 0000000..ad90237 --- /dev/null +++ b/share/extensions/tests/data/refs/pixelsnap__--id__p1__--id__r3__--snap_to__bl.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__bl.out b/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__bl.out new file mode 100644 index 0000000..5782872 --- /dev/null +++ b/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__bl.out @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__tl.out b/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__tl.out new file mode 100644 index 0000000..5a3ce2b --- /dev/null +++ b/share/extensions/tests/data/refs/pixelsnap__--id__rect1144__--id__path1302__--id__path1430__--id__path1434__--id__path1434__--snap_to__tl.out @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__DMPL__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out b/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__DMPL__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out new file mode 100644 index 0000000..aa162ff --- /dev/null +++ b/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__DMPL__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out @@ -0,0 +1,2 @@ + +:HAL0V20EC1U,P1,VS20,FS24,U0,0,D0,90,U5966,2652,D5971,2651,5975,2647,5976,2641,5975,2636,5971,2633,5966,2632,5966,0,5961,1,5957,5,5956,10,3824,10,3825,15,3829,19,3834,20,3834,2652,3839,2651,3843,2647,3844,2642,5976,2642,5975,2637,5971,2633,5966,2632,5966,2592,U5479,7938,D5474,7939,5470,7943,5469,7948,5470,7953,5474,7957,5478,7957,5477,7997,5476,7997,5472,8037,5471,8036,5464,8075,5463,8075,5453,8112,5452,8112,5439,8149,5439,8148,5423,8184,5405,8218,5404,8217,5384,8250,5361,8281,5361,8280,5336,8310,5335,8309,5308,8337,5308,8336,5279,8362,5248,8385,5247,8385,5214,8406,5214,8405,5180,8425,5179,8424,5143,8441,5143,8440,5105,8454,5105,8453,5067,8464,5067,8463,5029,8471,5028,8470,4990,8476,4990,8475,4951,8477,4951,8476,4913,8476,4913,8475,4874,8472,4874,8471,4836,8465,4837,8464,4799,8455,4763,8443,4763,8442,4727,8428,4727,8427,4692,8411,4693,8410,4659,8390,4660,8390,4627,8368,4628,8367,4597,8343,4597,8342,4568,8315,4569,8314,4541,8285,4542,8285,4517,8254,4518,8253,4496,8221,4497,8221,4477,8187,4478,8187,4461,8152,4461,8151,4447,8116,4448,8115,4436,8079,4437,8078,4428,8041,4429,8041,4423,8003,4420,7964,4421,7964,4420,7926,4421,7926,4423,7887,4424,7887,4429,7849,4430,7849,4438,7811,4439,7811,4450,7773,4464,7736,4465,7736,4481,7700,4482,7700,4501,7665,4502,7666,4523,7633,4524,7633,4548,7603,4574,7574,4574,7575,4602,7548,4603,7548,4632,7524,4664,7502,4697,7482,4697,7483,4731,7465,4732,7466,4767,7450,4767,7451,4804,7438,4804,7439,4842,7429,4842,7430,4880,7422,4880,7423,4920,7419,4959,7418,4959,7419,5014,7422,5013,7423,5066,7431,5066,7432,5117,7445,5116,7446,5165,7463,5164,7464,5211,7487,5210,7487,5254,7514,5253,7515,5294,7545,5293,7546,5331,7580,5330,7581,5365,7618,5364,7619,5394,7660,5393,7660,5420,7704,5419,7704,5441,7751,5458,7800,5457,7800,5470,7851,5469,7851,5477,7903,5476,7903,5479,7957,5478,7957,5477,7997,5476,7997,U5478,5312,D5478,5312,5477,5391,5472,5470,5465,5547,5464,5547,5454,5622,5441,5695,5425,5766,5407,5834,5387,5899,5386,5899,5364,5961,5363,5961,5338,6020,5311,6075,5310,6075,5282,6126,5281,6126,5250,6173,5217,6216,5216,6215,5182,6254,5181,6253,5145,6286,5144,6285,5107,6313,5106,6312,5068,6334,5067,6333,5029,6349,5029,6348,4990,6358,4990,6356,4951,6361,4951,6359,4913,6358,4913,6357,4874,6350,4875,6349,4837,6337,4837,6335,4800,6318,4800,6317,4764,6293,4728,6264,4729,6263,4694,6230,4695,6229,4661,6190,4662,6190,4630,6145,4599,6096,4600,6095,4571,6041,4544,5982,4520,5920,4498,5856,4499,5855,4479,5788,4480,5788,4463,5718,4449,5647,4449,5646,4438,5573,4429,5498,4430,5498,4424,5422,4421,5346,4420,5268,4421,5268,4423,5191,4428,5114,4429,5114,4437,5037,4448,4962,4449,4962,4462,4887,4463,4887,4479,4814,4480,4815,4499,4745,4499,4746,4521,4680,4545,4618,4546,4619,4571,4561,4572,4561,4599,4507,4600,4508,4629,4458,4630,4458,4661,4413,4662,4414,4695,4374,4729,4339,4730,4339,4765,4309,4766,4310,4803,4284,4803,4285,4841,4265,4841,4266,4880,4252,4880,4253,4919,4244,4920,4246,4959,4243,4959,4244,4987,4245,4987,4246,5013,4250,5013,4251,5040,4258,5040,4259,5066,4268,5065,4269,5091,4281,5090,4282,5116,4296,5115,4297,5140,4313,5139,4314,5163,4333,5186,4354,5186,4355,5209,4378,5208,4379,5230,4404,5252,4432,5251,4432,5292,4493,5291,4494,5328,4562,5362,4638,5361,4638,5392,4719,5391,4720,5418,4807,5417,4807,5439,4899,5439,4900,5457,4997,5456,4997,5469,5098,5477,5203,5476,5203,5479,5312,5478,5312,5478,5352,U4655,1257,D4650,1256,4649,1256,4615,1306,4615,1307,4583,1362,4584,1362,4554,1422,4555,1422,4528,1486,4528,1487,4504,1554,4505,1554,4483,1625,4484,1625,4465,1699,4466,1699,4450,1775,4451,1775,4438,1854,4429,1934,4423,2016,4420,2099,4421,2099,4421,2182,4425,2266,4432,2350,4443,2433,4457,2514,4474,2592,4494,2667,4495,2667,4517,2737,4542,2803,4543,2803,4570,2865,4571,2865,4600,2922,4601,2922,4632,2975,4633,2974,4667,3022,4667,3021,4703,3064,4703,3063,4741,3100,4741,3099,4780,3130,4780,3129,4820,3154,4821,3153,4862,3171,4862,3170,4904,3182,4905,3181,4948,3186,4948,3184,4991,3183,4990,3181,5033,3173,5032,3171,5074,3156,5073,3155,5114,3134,5113,3133,5152,3105,5151,3104,5189,3071,5188,3070,5225,3031,5224,3031,5259,2986,5258,2986,5291,2936,5290,2936,5321,2881,5349,2821,5375,2757,5375,2756,5398,2688,5419,2615,5437,2539,5437,2538,5452,2458,5464,2376,5472,2293,5477,2209,5479,2126,5477,2043,5472,1961,5464,1880,5453,1800,5439,1723,5438,1723,5422,1647,5421,1648,5401,1575,5378,1505,5378,1506,5352,1439,5352,1440,5324,1377,5323,1378,5292,1319,5292,1320,5258,1266,5254,1270,5253,1275,5255,1280,5259,1284,5260,1284,4946,2136,4942,2133,4940,2128,4940,2123,4944,2119,4946,2117,4652,1238,4647,1241,4645,1246,4646,1251,4649,1255,4649,1256,4627,1289,U3356,8485,D3353,8481,3352,8476,3354,8471,3355,8470,2297,7411,2301,7409,2307,7409,2311,7411,3369,6353,3364,6350,3359,6350,3355,6353,2297,5295,U3355,4236,D3352,4241,3352,4243,3307,4241,3307,4240,3254,4235,3187,4225,3107,4209,3107,4208,3017,4185,3018,4184,2970,4169,2971,4169,2922,4151,2873,4130,2824,4107,2824,4106,2774,4080,2775,4079,2726,4050,2726,4049,2678,4016,2631,3979,2631,3978,2585,3938,2586,3937,2542,3892,2543,3892,2501,3843,2502,3842,2463,3789,2464,3788,2428,3730,2429,3730,2397,3667,2398,3666,2369,3598,2370,3598,2346,3525,2347,3525,2327,3446,2328,3446,2314,3361,2315,3361,2306,3271,2303,3175,2304,3175,2307,3082,2308,3082,2317,3000,2324,2964,2332,2930,2333,2930,2342,2899,2352,2870,2353,2870,2364,2843,2365,2843,2378,2819,2392,2797,2393,2797,2407,2777,2408,2777,2423,2759,2424,2760,2440,2743,2441,2744,2458,2729,2459,2729,2477,2716,2478,2717,2516,2695,2517,2696,2558,2680,2559,2681,2603,2669,2603,2670,2648,2662,2648,2663,2696,2658,2696,2659,2744,2656,2744,2657,2843,2656,2942,2655,2942,2654,2990,2652,2990,2651,3037,2647,3037,2646,3083,2638,3082,2637,3126,2625,3126,2624,3167,2608,3167,2607,3205,2585,3205,2584,3223,2571,3222,2570,3240,2555,3239,2555,3256,2538,3255,2537,3271,2519,3270,2519,3285,2498,3284,2498,3298,2475,3297,2475,3310,2450,3309,2450,3320,2423,3330,2394,3339,2362,3338,2362,3346,2328,3345,2328,3352,2291,3351,2291,3360,2210,3359,2210,3362,2117,3359,2021,3358,2021,3349,1930,3348,1931,3334,1846,3333,1846,3314,1768,3313,1768,3289,1695,3261,1627,3260,1627,3228,1564,3227,1564,3191,1506,3191,1507,3152,1453,3151,1454,3110,1405,3066,1360,3065,1361,3020,1320,3019,1321,2972,1284,2923,1251,2923,1252,2874,1222,2824,1196,2774,1173,2774,1174,2725,1153,2725,1154,2676,1136,2629,1121,2629,1122,2539,1098,2539,1099,2459,1083,2391,1074,2339,1069,2339,1070,2294,1068,U292,6943,D293,6949,297,6952,302,6954,304,6954,390,7434,384,7433,381,7431,34,7774,39,7776,44,7776,49,7773,51,7769,51,7768,534,7834,532,7839,529,7842,748,8277,752,8274,754,8269,752,8264,749,8260,748,8260,960,7821,964,7824,966,7828,1448,7754,1446,7750,1441,7746,1436,7746,1431,7749,1079,7411,1084,7409,1088,7408,1167,6927,1161,6928,1157,6931,1155,6936,1156,6941,1156,6942,726,7172,725,7167,726,7163,293,6939,292,6944,294,6950,298,6953,303,6954,304,6954,311,6993,U272,4837,D272,4837,358,5317,353,5316,349,5314,3,5657,7,5660,13,5660,17,5657,20,5652,20,5651,503,5718,501,5723,497,5725,716,6161,720,6157,722,6152,721,6147,717,6143,716,6143,929,5704,933,5708,934,5712,1416,5638,1414,5633,1409,5630,1404,5629,1399,5632,1047,5295,1052,5292,1056,5292,1135,4811,1130,4811,1125,4814,1123,4819,1124,4825,695,5055,693,5050,695,5046,261,4823,260,4828,262,4833,266,4836,271,4837,272,4837,279,4876,U8793,5312,D8798,5309,8801,5305,8801,5299,8798,5295,8794,5292,8791,5292,8791,4551,8786,4552,8782,4556,8781,4561,8047,4561,8048,4566,8052,4570,8057,4571,8057,5312,8062,5310,8066,5306,8067,5302,8801,5302,8800,5297,8796,5293,8791,5292,8791,5252,U7595,8467,D7595,8467,7595,7408,7590,7410,7587,7414,7585,7418,6527,7418,6528,7423,6532,7427,6537,7428,6537,8487,6542,8485,6546,8481,6547,8477,7605,8477,7604,8472,7600,8468,7595,8467,7595,8427,U7595,6350,D7595,6350,7595,4233,7590,4235,7587,4239,7585,4243,6527,4243,6528,4248,6532,4252,6537,4253,6537,6370,6542,6369,6546,6365,6547,6360,7605,6360,7604,6355,7600,6351,7595,6350,7595,6310,U7595,2699,D7595,2699,7595,1534,7593,1487,7592,1487,7586,1441,7585,1441,7575,1396,7561,1352,7560,1353,7543,1311,7542,1311,7521,1271,7521,1272,7497,1234,7496,1235,7468,1200,7437,1169,7437,1170,7404,1142,7404,1143,7369,1119,7368,1120,7332,1100,7332,1101,7294,1085,7293,1086,7254,1075,7254,1076,7214,1069,7214,1070,7173,1068,6939,1068,6939,1069,6899,1071,6899,1072,6859,1079,6859,1080,6820,1092,6820,1093,6782,1108,6783,1109,6746,1129,6747,1130,6712,1154,6713,1155,6680,1183,6681,1183,6651,1215,6652,1216,6624,1250,6625,1251,6601,1289,6602,1289,6581,1329,6582,1329,6565,1371,6565,1372,6552,1415,6553,1415,6543,1461,6544,1461,6538,1507,6539,1507,6537,1554,6537,2719,6539,2766,6540,2766,6546,2812,6547,2812,6557,2857,6558,2857,6571,2901,6572,2901,6589,2943,6590,2942,6611,2982,6612,2982,6636,3019,6637,3019,6664,3054,6665,3053,6695,3085,6696,3084,6728,3112,6729,3111,6763,3135,6764,3134,6800,3154,6801,3153,6839,3168,6839,3167,6878,3179,6878,3177,6918,3184,6918,3183,6959,3186,6959,3185,7193,3185,7193,3184,7234,3182,7234,3181,7274,3174,7274,3173,7313,3162,7312,3161,7350,3145,7350,3144,7386,3124,7385,3123,7420,3099,7419,3099,7452,3071,7451,3070,7482,3038,7481,3038,7508,3003,7507,3002,7531,2965,7531,2964,7551,2924,7568,2882,7567,2882,7580,2838,7589,2793,7595,2746,7594,2746,7596,2699,7595,2699,7595,2659,P0,U0,0,Z \ No newline at end of file diff --git a/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__KNK__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out b/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__KNK__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out new file mode 100644 index 0000000..3136307 --- /dev/null +++ b/share/extensions/tests/data/refs/plotter__--serialPort____test____--commandLanguage__KNK__--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out @@ -0,0 +1,34 @@ +ZG +PU +SP1 +VS20 +FS24 +PU0,0 +PD0,90 +PU5966,2652 +PD5971,2651,5975,2647,5976,2641,5975,2636,5971,2633,5966,2632,5966,0,5961,1,5957,5,5956,10,3824,10,3825,15,3829,19,3834,20,3834,2652,3839,2651,3843,2647,3844,2642,5976,2642,5975,2637,5971,2633,5966,2632,5966,2592 +PU5479,7938 +PD5474,7939,5470,7943,5469,7948,5470,7953,5474,7957,5478,7957,5477,7997,5476,7997,5472,8037,5471,8036,5464,8075,5463,8075,5453,8112,5452,8112,5439,8149,5439,8148,5423,8184,5405,8218,5404,8217,5384,8250,5361,8281,5361,8280,5336,8310,5335,8309,5308,8337,5308,8336,5279,8362,5248,8385,5247,8385,5214,8406,5214,8405,5180,8425,5179,8424,5143,8441,5143,8440,5105,8454,5105,8453,5067,8464,5067,8463,5029,8471,5028,8470,4990,8476,4990,8475,4951,8477,4951,8476,4913,8476,4913,8475,4874,8472,4874,8471,4836,8465,4837,8464,4799,8455,4763,8443,4763,8442,4727,8428,4727,8427,4692,8411,4693,8410,4659,8390,4660,8390,4627,8368,4628,8367,4597,8343,4597,8342,4568,8315,4569,8314,4541,8285,4542,8285,4517,8254,4518,8253,4496,8221,4497,8221,4477,8187,4478,8187,4461,8152,4461,8151,4447,8116,4448,8115,4436,8079,4437,8078,4428,8041,4429,8041,4423,8003,4420,7964,4421,7964,4420,7926,4421,7926,4423,7887,4424,7887,4429,7849,4430,7849,4438,7811,4439,7811,4450,7773,4464,7736,4465,7736,4481,7700,4482,7700,4501,7665,4502,7666,4523,7633,4524,7633,4548,7603,4574,7574,4574,7575,4602,7548,4603,7548,4632,7524,4664,7502,4697,7482,4697,7483,4731,7465,4732,7466,4767,7450,4767,7451,4804,7438,4804,7439,4842,7429,4842,7430,4880,7422,4880,7423,4920,7419,4959,7418,4959,7419,5014,7422,5013,7423,5066,7431,5066,7432,5117,7445,5116,7446,5165,7463,5164,7464,5211,7487,5210,7487,5254,7514,5253,7515,5294,7545,5293,7546,5331,7580,5330,7581,5365,7618,5364,7619,5394,7660,5393,7660,5420,7704,5419,7704,5441,7751,5458,7800,5457,7800,5470,7851,5469,7851,5477,7903,5476,7903,5479,7957,5478,7957,5477,7997,5476,7997 +PU5478,5312 +PD5478,5312,5477,5391,5472,5470,5465,5547,5464,5547,5454,5622,5441,5695,5425,5766,5407,5834,5387,5899,5386,5899,5364,5961,5363,5961,5338,6020,5311,6075,5310,6075,5282,6126,5281,6126,5250,6173,5217,6216,5216,6215,5182,6254,5181,6253,5145,6286,5144,6285,5107,6313,5106,6312,5068,6334,5067,6333,5029,6349,5029,6348,4990,6358,4990,6356,4951,6361,4951,6359,4913,6358,4913,6357,4874,6350,4875,6349,4837,6337,4837,6335,4800,6318,4800,6317,4764,6293,4728,6264,4729,6263,4694,6230,4695,6229,4661,6190,4662,6190,4630,6145,4599,6096,4600,6095,4571,6041,4544,5982,4520,5920,4498,5856,4499,5855,4479,5788,4480,5788,4463,5718,4449,5647,4449,5646,4438,5573,4429,5498,4430,5498,4424,5422,4421,5346,4420,5268,4421,5268,4423,5191,4428,5114,4429,5114,4437,5037,4448,4962,4449,4962,4462,4887,4463,4887,4479,4814,4480,4815,4499,4745,4499,4746,4521,4680,4545,4618,4546,4619,4571,4561,4572,4561,4599,4507,4600,4508,4629,4458,4630,4458,4661,4413,4662,4414,4695,4374,4729,4339,4730,4339,4765,4309,4766,4310,4803,4284,4803,4285,4841,4265,4841,4266,4880,4252,4880,4253,4919,4244,4920,4246,4959,4243,4959,4244,4987,4245,4987,4246,5013,4250,5013,4251,5040,4258,5040,4259,5066,4268,5065,4269,5091,4281,5090,4282,5116,4296,5115,4297,5140,4313,5139,4314,5163,4333,5186,4354,5186,4355,5209,4378,5208,4379,5230,4404,5252,4432,5251,4432,5292,4493,5291,4494,5328,4562,5362,4638,5361,4638,5392,4719,5391,4720,5418,4807,5417,4807,5439,4899,5439,4900,5457,4997,5456,4997,5469,5098,5477,5203,5476,5203,5479,5312,5478,5312,5478,5352 +PU4655,1257 +PD4650,1256,4649,1256,4615,1306,4615,1307,4583,1362,4584,1362,4554,1422,4555,1422,4528,1486,4528,1487,4504,1554,4505,1554,4483,1625,4484,1625,4465,1699,4466,1699,4450,1775,4451,1775,4438,1854,4429,1934,4423,2016,4420,2099,4421,2099,4421,2182,4425,2266,4432,2350,4443,2433,4457,2514,4474,2592,4494,2667,4495,2667,4517,2737,4542,2803,4543,2803,4570,2865,4571,2865,4600,2922,4601,2922,4632,2975,4633,2974,4667,3022,4667,3021,4703,3064,4703,3063,4741,3100,4741,3099,4780,3130,4780,3129,4820,3154,4821,3153,4862,3171,4862,3170,4904,3182,4905,3181,4948,3186,4948,3184,4991,3183,4990,3181,5033,3173,5032,3171,5074,3156,5073,3155,5114,3134,5113,3133,5152,3105,5151,3104,5189,3071,5188,3070,5225,3031,5224,3031,5259,2986,5258,2986,5291,2936,5290,2936,5321,2881,5349,2821,5375,2757,5375,2756,5398,2688,5419,2615,5437,2539,5437,2538,5452,2458,5464,2376,5472,2293,5477,2209,5479,2126,5477,2043,5472,1961,5464,1880,5453,1800,5439,1723,5438,1723,5422,1647,5421,1648,5401,1575,5378,1505,5378,1506,5352,1439,5352,1440,5324,1377,5323,1378,5292,1319,5292,1320,5258,1266,5254,1270,5253,1275,5255,1280,5259,1284,5260,1284,4946,2136,4942,2133,4940,2128,4940,2123,4944,2119,4946,2117,4652,1238,4647,1241,4645,1246,4646,1251,4649,1255,4649,1256,4627,1289 +PU3356,8485 +PD3353,8481,3352,8476,3354,8471,3355,8470,2297,7411,2301,7409,2307,7409,2311,7411,3369,6353,3364,6350,3359,6350,3355,6353,2297,5295 +PU3355,4236 +PD3352,4241,3352,4243,3307,4241,3307,4240,3254,4235,3187,4225,3107,4209,3107,4208,3017,4185,3018,4184,2970,4169,2971,4169,2922,4151,2873,4130,2824,4107,2824,4106,2774,4080,2775,4079,2726,4050,2726,4049,2678,4016,2631,3979,2631,3978,2585,3938,2586,3937,2542,3892,2543,3892,2501,3843,2502,3842,2463,3789,2464,3788,2428,3730,2429,3730,2397,3667,2398,3666,2369,3598,2370,3598,2346,3525,2347,3525,2327,3446,2328,3446,2314,3361,2315,3361,2306,3271,2303,3175,2304,3175,2307,3082,2308,3082,2317,3000,2324,2964,2332,2930,2333,2930,2342,2899,2352,2870,2353,2870,2364,2843,2365,2843,2378,2819,2392,2797,2393,2797,2407,2777,2408,2777,2423,2759,2424,2760,2440,2743,2441,2744,2458,2729,2459,2729,2477,2716,2478,2717,2516,2695,2517,2696,2558,2680,2559,2681,2603,2669,2603,2670,2648,2662,2648,2663,2696,2658,2696,2659,2744,2656,2744,2657,2843,2656,2942,2655,2942,2654,2990,2652,2990,2651,3037,2647,3037,2646,3083,2638,3082,2637,3126,2625,3126,2624,3167,2608,3167,2607,3205,2585,3205,2584,3223,2571,3222,2570,3240,2555,3239,2555,3256,2538,3255,2537,3271,2519,3270,2519,3285,2498,3284,2498,3298,2475,3297,2475,3310,2450,3309,2450,3320,2423,3330,2394,3339,2362,3338,2362,3346,2328,3345,2328,3352,2291,3351,2291,3360,2210,3359,2210,3362,2117,3359,2021,3358,2021,3349,1930,3348,1931,3334,1846,3333,1846,3314,1768,3313,1768,3289,1695,3261,1627,3260,1627,3228,1564,3227,1564,3191,1506,3191,1507,3152,1453,3151,1454,3110,1405,3066,1360,3065,1361,3020,1320,3019,1321,2972,1284,2923,1251,2923,1252,2874,1222,2824,1196,2774,1173,2774,1174,2725,1153,2725,1154,2676,1136,2629,1121,2629,1122,2539,1098,2539,1099,2459,1083,2391,1074,2339,1069,2339,1070,2294,1068 +PU292,6943 +PD293,6949,297,6952,302,6954,304,6954,390,7434,384,7433,381,7431,34,7774,39,7776,44,7776,49,7773,51,7769,51,7768,534,7834,532,7839,529,7842,748,8277,752,8274,754,8269,752,8264,749,8260,748,8260,960,7821,964,7824,966,7828,1448,7754,1446,7750,1441,7746,1436,7746,1431,7749,1079,7411,1084,7409,1088,7408,1167,6927,1161,6928,1157,6931,1155,6936,1156,6941,1156,6942,726,7172,725,7167,726,7163,293,6939,292,6944,294,6950,298,6953,303,6954,304,6954,311,6993 +PU272,4837 +PD272,4837,358,5317,353,5316,349,5314,3,5657,7,5660,13,5660,17,5657,20,5652,20,5651,503,5718,501,5723,497,5725,716,6161,720,6157,722,6152,721,6147,717,6143,716,6143,929,5704,933,5708,934,5712,1416,5638,1414,5633,1409,5630,1404,5629,1399,5632,1047,5295,1052,5292,1056,5292,1135,4811,1130,4811,1125,4814,1123,4819,1124,4825,695,5055,693,5050,695,5046,261,4823,260,4828,262,4833,266,4836,271,4837,272,4837,279,4876 +PU8793,5312 +PD8798,5309,8801,5305,8801,5299,8798,5295,8794,5292,8791,5292,8791,4551,8786,4552,8782,4556,8781,4561,8047,4561,8048,4566,8052,4570,8057,4571,8057,5312,8062,5310,8066,5306,8067,5302,8801,5302,8800,5297,8796,5293,8791,5292,8791,5252 +PU7595,8467 +PD7595,8467,7595,7408,7590,7410,7587,7414,7585,7418,6527,7418,6528,7423,6532,7427,6537,7428,6537,8487,6542,8485,6546,8481,6547,8477,7605,8477,7604,8472,7600,8468,7595,8467,7595,8427 +PU7595,6350 +PD7595,6350,7595,4233,7590,4235,7587,4239,7585,4243,6527,4243,6528,4248,6532,4252,6537,4253,6537,6370,6542,6369,6546,6365,6547,6360,7605,6360,7604,6355,7600,6351,7595,6350,7595,6310 +PU7595,2699 +PD7595,2699,7595,1534,7593,1487,7592,1487,7586,1441,7585,1441,7575,1396,7561,1352,7560,1353,7543,1311,7542,1311,7521,1271,7521,1272,7497,1234,7496,1235,7468,1200,7437,1169,7437,1170,7404,1142,7404,1143,7369,1119,7368,1120,7332,1100,7332,1101,7294,1085,7293,1086,7254,1075,7254,1076,7214,1069,7214,1070,7173,1068,6939,1068,6939,1069,6899,1071,6899,1072,6859,1079,6859,1080,6820,1092,6820,1093,6782,1108,6783,1109,6746,1129,6747,1130,6712,1154,6713,1155,6680,1183,6681,1183,6651,1215,6652,1216,6624,1250,6625,1251,6601,1289,6602,1289,6581,1329,6582,1329,6565,1371,6565,1372,6552,1415,6553,1415,6543,1461,6544,1461,6538,1507,6539,1507,6537,1554,6537,2719,6539,2766,6540,2766,6546,2812,6547,2812,6557,2857,6558,2857,6571,2901,6572,2901,6589,2943,6590,2942,6611,2982,6612,2982,6636,3019,6637,3019,6664,3054,6665,3053,6695,3085,6696,3084,6728,3112,6729,3111,6763,3135,6764,3134,6800,3154,6801,3153,6839,3168,6839,3167,6878,3179,6878,3177,6918,3184,6918,3183,6959,3186,6959,3185,7193,3185,7193,3184,7234,3182,7234,3181,7274,3174,7274,3173,7313,3162,7312,3161,7350,3145,7350,3144,7386,3124,7385,3123,7420,3099,7419,3099,7452,3071,7451,3070,7482,3038,7481,3038,7508,3003,7507,3002,7531,2965,7531,2964,7551,2924,7568,2882,7567,2882,7580,2838,7589,2793,7595,2746,7594,2746,7596,2699,7595,2699,7595,2659 +SP0 +PU0,0 +@ \ No newline at end of file diff --git a/share/extensions/tests/data/refs/plotter__--serialPort____test____--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out b/share/extensions/tests/data/refs/plotter__--serialPort____test____--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out new file mode 100644 index 0000000..5fab8e2 --- /dev/null +++ b/share/extensions/tests/data/refs/plotter__--serialPort____test____--serialFlowControl__0__--force__24__--speed__20__--orientation__90.out @@ -0,0 +1,35 @@ +IN +PU +SP1 +VS20 +FS24 +PU0,0 +PD0,90 +PU5966,2652 +PD5971,2651,5975,2647,5976,2641,5975,2636,5971,2633,5966,2632,5966,0,5961,1,5957,5,5956,10,3824,10,3825,15,3829,19,3834,20,3834,2652,3839,2651,3843,2647,3844,2642,5976,2642,5975,2637,5971,2633,5966,2632,5966,2592 +PU5479,7938 +PD5474,7939,5470,7943,5469,7948,5470,7953,5474,7957,5478,7957,5477,7997,5476,7997,5472,8037,5471,8036,5464,8075,5463,8075,5453,8112,5452,8112,5439,8149,5439,8148,5423,8184,5405,8218,5404,8217,5384,8250,5361,8281,5361,8280,5336,8310,5335,8309,5308,8337,5308,8336,5279,8362,5248,8385,5247,8385,5214,8406,5214,8405,5180,8425,5179,8424,5143,8441,5143,8440,5105,8454,5105,8453,5067,8464,5067,8463,5029,8471,5028,8470,4990,8476,4990,8475,4951,8477,4951,8476,4913,8476,4913,8475,4874,8472,4874,8471,4836,8465,4837,8464,4799,8455,4763,8443,4763,8442,4727,8428,4727,8427,4692,8411,4693,8410,4659,8390,4660,8390,4627,8368,4628,8367,4597,8343,4597,8342,4568,8315,4569,8314,4541,8285,4542,8285,4517,8254,4518,8253,4496,8221,4497,8221,4477,8187,4478,8187,4461,8152,4461,8151,4447,8116,4448,8115,4436,8079,4437,8078,4428,8041,4429,8041,4423,8003,4420,7964,4421,7964,4420,7926,4421,7926,4423,7887,4424,7887,4429,7849,4430,7849,4438,7811,4439,7811,4450,7773,4464,7736,4465,7736,4481,7700,4482,7700,4501,7665,4502,7666,4523,7633,4524,7633,4548,7603,4574,7574,4574,7575,4602,7548,4603,7548,4632,7524,4664,7502,4697,7482,4697,7483,4731,7465,4732,7466,4767,7450,4767,7451,4804,7438,4804,7439,4842,7429,4842,7430,4880,7422,4880,7423,4920,7419,4959,7418,4959,7419,5014,7422,5013,7423,5066,7431,5066,7432,5117,7445,5116,7446,5165,7463,5164,7464,5211,7487,5210,7487,5254,7514,5253,7515,5294,7545,5293,7546,5331,7580,5330,7581,5365,7618,5364,7619,5394,7660,5393,7660,5420,7704,5419,7704,5441,7751,5458,7800,5457,7800,5470,7851,5469,7851,5477,7903,5476,7903,5479,7957,5478,7957,5477,7997,5476,7997 +PU5478,5312 +PD5478,5312,5477,5391,5472,5470,5465,5547,5464,5547,5454,5622,5441,5695,5425,5766,5407,5834,5387,5899,5386,5899,5364,5961,5363,5961,5338,6020,5311,6075,5310,6075,5282,6126,5281,6126,5250,6173,5217,6216,5216,6215,5182,6254,5181,6253,5145,6286,5144,6285,5107,6313,5106,6312,5068,6334,5067,6333,5029,6349,5029,6348,4990,6358,4990,6356,4951,6361,4951,6359,4913,6358,4913,6357,4874,6350,4875,6349,4837,6337,4837,6335,4800,6318,4800,6317,4764,6293,4728,6264,4729,6263,4694,6230,4695,6229,4661,6190,4662,6190,4630,6145,4599,6096,4600,6095,4571,6041,4544,5982,4520,5920,4498,5856,4499,5855,4479,5788,4480,5788,4463,5718,4449,5647,4449,5646,4438,5573,4429,5498,4430,5498,4424,5422,4421,5346,4420,5268,4421,5268,4423,5191,4428,5114,4429,5114,4437,5037,4448,4962,4449,4962,4462,4887,4463,4887,4479,4814,4480,4815,4499,4745,4499,4746,4521,4680,4545,4618,4546,4619,4571,4561,4572,4561,4599,4507,4600,4508,4629,4458,4630,4458,4661,4413,4662,4414,4695,4374,4729,4339,4730,4339,4765,4309,4766,4310,4803,4284,4803,4285,4841,4265,4841,4266,4880,4252,4880,4253,4919,4244,4920,4246,4959,4243,4959,4244,4987,4245,4987,4246,5013,4250,5013,4251,5040,4258,5040,4259,5066,4268,5065,4269,5091,4281,5090,4282,5116,4296,5115,4297,5140,4313,5139,4314,5163,4333,5186,4354,5186,4355,5209,4378,5208,4379,5230,4404,5252,4432,5251,4432,5292,4493,5291,4494,5328,4562,5362,4638,5361,4638,5392,4719,5391,4720,5418,4807,5417,4807,5439,4899,5439,4900,5457,4997,5456,4997,5469,5098,5477,5203,5476,5203,5479,5312,5478,5312,5478,5352 +PU4655,1257 +PD4650,1256,4649,1256,4615,1306,4615,1307,4583,1362,4584,1362,4554,1422,4555,1422,4528,1486,4528,1487,4504,1554,4505,1554,4483,1625,4484,1625,4465,1699,4466,1699,4450,1775,4451,1775,4438,1854,4429,1934,4423,2016,4420,2099,4421,2099,4421,2182,4425,2266,4432,2350,4443,2433,4457,2514,4474,2592,4494,2667,4495,2667,4517,2737,4542,2803,4543,2803,4570,2865,4571,2865,4600,2922,4601,2922,4632,2975,4633,2974,4667,3022,4667,3021,4703,3064,4703,3063,4741,3100,4741,3099,4780,3130,4780,3129,4820,3154,4821,3153,4862,3171,4862,3170,4904,3182,4905,3181,4948,3186,4948,3184,4991,3183,4990,3181,5033,3173,5032,3171,5074,3156,5073,3155,5114,3134,5113,3133,5152,3105,5151,3104,5189,3071,5188,3070,5225,3031,5224,3031,5259,2986,5258,2986,5291,2936,5290,2936,5321,2881,5349,2821,5375,2757,5375,2756,5398,2688,5419,2615,5437,2539,5437,2538,5452,2458,5464,2376,5472,2293,5477,2209,5479,2126,5477,2043,5472,1961,5464,1880,5453,1800,5439,1723,5438,1723,5422,1647,5421,1648,5401,1575,5378,1505,5378,1506,5352,1439,5352,1440,5324,1377,5323,1378,5292,1319,5292,1320,5258,1266,5254,1270,5253,1275,5255,1280,5259,1284,5260,1284,4946,2136,4942,2133,4940,2128,4940,2123,4944,2119,4946,2117,4652,1238,4647,1241,4645,1246,4646,1251,4649,1255,4649,1256,4627,1289 +PU3356,8485 +PD3353,8481,3352,8476,3354,8471,3355,8470,2297,7411,2301,7409,2307,7409,2311,7411,3369,6353,3364,6350,3359,6350,3355,6353,2297,5295 +PU3355,4236 +PD3352,4241,3352,4243,3307,4241,3307,4240,3254,4235,3187,4225,3107,4209,3107,4208,3017,4185,3018,4184,2970,4169,2971,4169,2922,4151,2873,4130,2824,4107,2824,4106,2774,4080,2775,4079,2726,4050,2726,4049,2678,4016,2631,3979,2631,3978,2585,3938,2586,3937,2542,3892,2543,3892,2501,3843,2502,3842,2463,3789,2464,3788,2428,3730,2429,3730,2397,3667,2398,3666,2369,3598,2370,3598,2346,3525,2347,3525,2327,3446,2328,3446,2314,3361,2315,3361,2306,3271,2303,3175,2304,3175,2307,3082,2308,3082,2317,3000,2324,2964,2332,2930,2333,2930,2342,2899,2352,2870,2353,2870,2364,2843,2365,2843,2378,2819,2392,2797,2393,2797,2407,2777,2408,2777,2423,2759,2424,2760,2440,2743,2441,2744,2458,2729,2459,2729,2477,2716,2478,2717,2516,2695,2517,2696,2558,2680,2559,2681,2603,2669,2603,2670,2648,2662,2648,2663,2696,2658,2696,2659,2744,2656,2744,2657,2843,2656,2942,2655,2942,2654,2990,2652,2990,2651,3037,2647,3037,2646,3083,2638,3082,2637,3126,2625,3126,2624,3167,2608,3167,2607,3205,2585,3205,2584,3223,2571,3222,2570,3240,2555,3239,2555,3256,2538,3255,2537,3271,2519,3270,2519,3285,2498,3284,2498,3298,2475,3297,2475,3310,2450,3309,2450,3320,2423,3330,2394,3339,2362,3338,2362,3346,2328,3345,2328,3352,2291,3351,2291,3360,2210,3359,2210,3362,2117,3359,2021,3358,2021,3349,1930,3348,1931,3334,1846,3333,1846,3314,1768,3313,1768,3289,1695,3261,1627,3260,1627,3228,1564,3227,1564,3191,1506,3191,1507,3152,1453,3151,1454,3110,1405,3066,1360,3065,1361,3020,1320,3019,1321,2972,1284,2923,1251,2923,1252,2874,1222,2824,1196,2774,1173,2774,1174,2725,1153,2725,1154,2676,1136,2629,1121,2629,1122,2539,1098,2539,1099,2459,1083,2391,1074,2339,1069,2339,1070,2294,1068 +PU292,6943 +PD293,6949,297,6952,302,6954,304,6954,390,7434,384,7433,381,7431,34,7774,39,7776,44,7776,49,7773,51,7769,51,7768,534,7834,532,7839,529,7842,748,8277,752,8274,754,8269,752,8264,749,8260,748,8260,960,7821,964,7824,966,7828,1448,7754,1446,7750,1441,7746,1436,7746,1431,7749,1079,7411,1084,7409,1088,7408,1167,6927,1161,6928,1157,6931,1155,6936,1156,6941,1156,6942,726,7172,725,7167,726,7163,293,6939,292,6944,294,6950,298,6953,303,6954,304,6954,311,6993 +PU272,4837 +PD272,4837,358,5317,353,5316,349,5314,3,5657,7,5660,13,5660,17,5657,20,5652,20,5651,503,5718,501,5723,497,5725,716,6161,720,6157,722,6152,721,6147,717,6143,716,6143,929,5704,933,5708,934,5712,1416,5638,1414,5633,1409,5630,1404,5629,1399,5632,1047,5295,1052,5292,1056,5292,1135,4811,1130,4811,1125,4814,1123,4819,1124,4825,695,5055,693,5050,695,5046,261,4823,260,4828,262,4833,266,4836,271,4837,272,4837,279,4876 +PU8793,5312 +PD8798,5309,8801,5305,8801,5299,8798,5295,8794,5292,8791,5292,8791,4551,8786,4552,8782,4556,8781,4561,8047,4561,8048,4566,8052,4570,8057,4571,8057,5312,8062,5310,8066,5306,8067,5302,8801,5302,8800,5297,8796,5293,8791,5292,8791,5252 +PU7595,8467 +PD7595,8467,7595,7408,7590,7410,7587,7414,7585,7418,6527,7418,6528,7423,6532,7427,6537,7428,6537,8487,6542,8485,6546,8481,6547,8477,7605,8477,7604,8472,7600,8468,7595,8467,7595,8427 +PU7595,6350 +PD7595,6350,7595,4233,7590,4235,7587,4239,7585,4243,6527,4243,6528,4248,6532,4252,6537,4253,6537,6370,6542,6369,6546,6365,6547,6360,7605,6360,7604,6355,7600,6351,7595,6350,7595,6310 +PU7595,2699 +PD7595,2699,7595,1534,7593,1487,7592,1487,7586,1441,7585,1441,7575,1396,7561,1352,7560,1353,7543,1311,7542,1311,7521,1271,7521,1272,7497,1234,7496,1235,7468,1200,7437,1169,7437,1170,7404,1142,7404,1143,7369,1119,7368,1120,7332,1100,7332,1101,7294,1085,7293,1086,7254,1075,7254,1076,7214,1069,7214,1070,7173,1068,6939,1068,6939,1069,6899,1071,6899,1072,6859,1079,6859,1080,6820,1092,6820,1093,6782,1108,6783,1109,6746,1129,6747,1130,6712,1154,6713,1155,6680,1183,6681,1183,6651,1215,6652,1216,6624,1250,6625,1251,6601,1289,6602,1289,6581,1329,6582,1329,6565,1371,6565,1372,6552,1415,6553,1415,6543,1461,6544,1461,6538,1507,6539,1507,6537,1554,6537,2719,6539,2766,6540,2766,6546,2812,6547,2812,6557,2857,6558,2857,6571,2901,6572,2901,6589,2943,6590,2942,6611,2982,6612,2982,6636,3019,6637,3019,6664,3054,6665,3053,6695,3085,6696,3084,6728,3112,6729,3111,6763,3135,6764,3134,6800,3154,6801,3153,6839,3168,6839,3167,6878,3179,6878,3177,6918,3184,6918,3183,6959,3186,6959,3185,7193,3185,7193,3184,7234,3182,7234,3181,7274,3174,7274,3173,7313,3162,7312,3161,7350,3145,7350,3144,7386,3124,7385,3123,7420,3099,7419,3099,7452,3071,7451,3070,7482,3038,7481,3038,7508,3003,7507,3002,7531,2965,7531,2964,7551,2924,7568,2882,7567,2882,7580,2838,7589,2793,7595,2746,7594,2746,7596,2699,7595,2699,7595,2659 +PU0,0 +SP0 +IN + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/plt_output.out b/share/extensions/tests/data/refs/plt_output.out new file mode 100644 index 0000000..b64aac8 --- /dev/null +++ b/share/extensions/tests/data/refs/plt_output.out @@ -0,0 +1 @@ +IN;PU7353,7293;PD10160,7293;PD10160,5019;PD7353,5019;PD7353,7293;PU2258,6209;PD2255,6151;PD2246,6095;PD2232,6041;PD2213,5989;PD2190,5940;PD2161,5893;PD2129,5850;PD2092,5810;PD2052,5773;PD2009,5741;PD1962,5713;PD1913,5689;PD1861,5670;PD1807,5656;PD1751,5647;PD1693,5644;PD1636,5647;PD1580,5656;PD1526,5670;PD1474,5689;PD1424,5713;PD1378,5741;PD1334,5773;PD1294,5810;PD1258,5850;PD1225,5893;PD1197,5940;PD1173,5989;PD1154,6041;PD1140,6095;PD1132,6151;PD1129,6209;PD1132,6267;PD1140,6323;PD1154,6377;PD1173,6429;PD1197,6478;PD1225,6524;PD1258,6568;PD1294,6608;PD1334,6644;PD1378,6677;PD1424,6705;PD1474,6729;PD1526,6748;PD1580,6762;PD1636,6770;PD1693,6773;PD1751,6770;PD1807,6762;PD1861,6748;PD1913,6729;PD1962,6705;PD2009,6677;PD2052,6644;PD2092,6608;PD2129,6568;PD2161,6524;PD2190,6478;PD2213,6429;PD2232,6377;PD2246,6323;PD2255,6267;PD2258,6209;PU5644,6209;PD5639,6151;PD5621,6095;PD5594,6041;PD5556,5989;PD5508,5940;PD5452,5893;PD5387,5850;PD5314,5810;PD5233,5773;PD5147,5741;PD5053,5713;PD4955,5689;PD4851,5670;PD4743,5656;PD4631,5647;PD4516,5644;PD4400,5647;PD4288,5656;PD4180,5670;PD4076,5689;PD3978,5713;PD3885,5741;PD3798,5773;PD3717,5810;PD3645,5850;PD3580,5893;PD3523,5940;PD3475,5989;PD3437,6041;PD3410,6095;PD3392,6151;PD3387,6209;PD3392,6267;PD3410,6323;PD3437,6377;PD3475,6429;PD3523,6478;PD3580,6524;PD3645,6568;PD3717,6608;PD3798,6644;PD3885,6677;PD3978,6705;PD4076,6729;PD4180,6748;PD4288,6762;PD4400,6770;PD4516,6773;PD4631,6770;PD4743,6762;PD4851,6748;PD4955,6729;PD5053,6705;PD5147,6677;PD5233,6644;PD5314,6608;PD5387,6568;PD5452,6524;PD5508,6478;PD5556,6429;PD5594,6377;PD5621,6323;PD5639,6267;PD5644,6209;PU8840,5895;PD7902,6209;PD8840,5895;PU1129,4516;PD2258,3387;PD3387,4516;PD4516,3387;PU5644,4516;PD5647,4467;PD5662,4339;PD5679,4254;PD5704,4158;PD5739,4056;PD5786,3951;PD5814,3898;PD5845,3846;PD5881,3794;PD5920,3744;PD5963,3695;PD6011,3648;PD6064,3604;PD6121,3563;PD6183,3525;PD6250,3491;PD6323,3461;PD6401,3435;PD6485,3415;PD6575,3399;PD6671,3390;PD6773,3387;PD6873,3390;PD6960,3399;PD7035,3415;PD7100,3435;PD7154,3461;PD7200,3491;PD7237,3525;PD7267,3563;PD7291,3604;PD7308,3648;PD7321,3695;PD7329,3744;PD7337,3846;PD7338,3951;PD7339,4056;PD7347,4158;PD7355,4207;PD7368,4254;PD7385,4298;PD7408,4339;PD7438,4377;PD7476,4411;PD7521,4441;PD7576,4467;PD7641,4488;PD7716,4503;PD7803,4512;PD7902,4516;PD8005,4512;PD8101,4503;PD8191,4488;PD8275,4467;PD8353,4441;PD8426,4411;PD8493,4377;PD8555,4339;PD8612,4298;PD8664,4254;PD8712,4207;PD8756,4158;PD8795,4108;PD8830,4056;PD8862,4004;PD8890,3951;PD8937,3846;PD8972,3744;PD8997,3648;PD9013,3563;PD9029,3435;PD9031,3387;PU2764,1251;PD2252,1343;PD1886,974;PD1815,1489;PD1351,1723;PD1819,1949;PD1898,2463;PD2258,2088;PD2771,2172;PD2525,1714;PD2764,1251;PU5022,1218;PD4510,1309;PD4144,940;PD4073,1455;PD3609,1689;PD4077,1915;PD4155,2429;PD4516,2054;PD5029,2138;PD4783,1680;PD5022,1218;PU1161,10281;PD1161,10231;PD1221,10231;PD1221,10281;PD1237,10281;PD1237,10160;PD1221,10160;PD1221,10217;PD1161,10217;PD1161,10160;PD1145,10160;PD1145,10281;PD1161,10281;PU1349,10202;PD1281,10202;PD1284,10188;PD1290,10178;PD1300,10172;PD1313,10170;PD1322,10171;PD1330,10172;PD1338,10175;PD1346,10179;PD1346,10165;PD1338,10162;PD1330,10159;PD1321,10158;PD1312,10158;PD1293,10161;PD1278,10170;PD1269,10185;PD1266,10204;PD1269,10224;PD1278,10240;PD1292,10249;PD1310,10253;PD1326,10250;PD1339,10241;PD1347,10227;PD1349,10209;PD1349,10202;PU1310,10240;PD1299,10238;PD1290,10233;PD1284,10225;PD1282,10213;PD1335,10213;PD1333,10224;PD1328,10233;PD1320,10238;PD1310,10240;PU1391,10286;PD1391,10160;PD1376,10160;PD1376,10286;PD1391,10286;PU1438,10286;PD1438,10160;PD1423,10160;PD1423,10286;PD1438,10286;PU1480,10205;PD1481,10191;PD1487,10180;PD1495,10173;PD1506,10170;PD1516,10173;PD1524,10180;PD1530,10191;PD1531,10205;PD1530,10220;PD1524,10231;PD1516,10238;PD1506,10240;PD1495,10238;PD1487,10231;PD1481,10220;PD1480,10205;PU1547,10205;PD1544,10185;PD1536,10170;PD1523,10161;PD1506,10158;PD1488,10161;PD1475,10170;PD1467,10185;PD1464,10205;PD1467,10225;PD1475,10240;PD1488,10250;PD1506,10253;PD1523,10250;PD1536,10240;PD1544,10225;PD1547,10205;PU1635,10281;PD1660,10179;PD1685,10281;PD1704,10281;PD1729,10179;PD1754,10281;PD1771,10281;PD1740,10160;PD1720,10160;PD1694,10265;PD1669,10160;PD1648,10160;PD1618,10281;PD1635,10281;PU1793,10205;PD1795,10191;PD1800,10180;PD1808,10173;PD1819,10170;PD1830,10173;PD1838,10180;PD1843,10191;PD1845,10205;PD1843,10220;PD1838,10231;PD1830,10238;PD1819,10240;PD1808,10238;PD1800,10231;PD1795,10220;PD1793,10205;PU1861,10205;PD1858,10185;PD1850,10170;PD1837,10161;PD1819,10158;PD1802,10161;PD1789,10170;PD1780,10185;PD1778,10205;PD1780,10225;PD1789,10240;PD1802,10250;PD1819,10253;PD1837,10250;PD1850,10240;PD1858,10225;PD1861,10205;PU1928,10239;PD1917,10237;PD1909,10231;PD1904,10221;PD1902,10208;PD1902,10160;PD1887,10160;PD1887,10251;PD1902,10251;PD1902,10236;PD1908,10244;PD1914,10249;PD1923,10252;PD1933,10253;PD1934,10253;PD1936,10253;PD1938,10252;PD1940,10252;PD1940,10237;PD1938,10238;PD1935,10239;PD1932,10239;PD1928,10239;PU1972,10286;PD1972,10160;PD1958,10160;PD1958,10286;PD1972,10286;PU2064,10286;PD2079,10286;PD2079,10160;PD2064,10160;PD2064,10174;PD2059,10167;PD2052,10162;PD2045,10159;PD2035,10158;PD2020,10161;PD2009,10171;PD2001,10186;PD1998,10205;PD2001,10224;PD2009,10240;PD2020,10249;PD2035,10253;PD2045,10252;PD2052,10249;PD2059,10244;PD2064,10237;PD2064,10286;PU2039,10170;PD2049,10172;PD2057,10179;PD2063,10191;PD2064,10205;PD2063,10220;PD2057,10231;PD2049,10238;PD2039,10240;PD2028,10238;PD2020,10231;PD2015,10220;PD2014,10205;PD2015,10191;PD2020,10179;PD2028,10172;PD2039,10170;PU4516,10306;PD5306,10306;PD5306,9523;PD4516,9523;PD4516,10306;PU2289,10281;PD2289,10207;PD2290,10191;PD2296,10179;PD2305,10173;PD2318,10171;PD2332,10173;PD2341,10179;PD2346,10191;PD2348,10207;PD2348,10281;PD2365,10281;PD2365,10205;PD2362,10185;PD2353,10170;PD2338,10161;PD2318,10158;PD2298,10161;PD2284,10170;PD2275,10185;PD2272,10205;PD2272,10281;PD2289,10281;PU2414,10222;PD2435,10222;PD2445,10223;PD2453,10228;PD2457,10235;PD2459,10245;PD2457,10254;PD2453,10261;PD2445,10266;PD2435,10267;PD2414,10267;PD2414,10222;PU2435,10281;PD2453,10278;PD2466,10272;PD2473,10260;PD2476,10245;PD2473,10229;PD2466,10218;PD2453,10211;PD2435,10209;PD2414,10209;PD2414,10160;PD2398,10160;PD2398,10281;PD2435,10281;PU2517,10222;PD2537,10222;PD2547,10223;PD2555,10228;PD2560,10235;PD2561,10245;PD2560,10254;PD2555,10261;PD2547,10266;PD2537,10267;PD2517,10267;PD2517,10222;PU2537,10281;PD2555,10278;PD2568,10272;PD2576,10260;PD2578,10245;PD2576,10229;PD2568,10218;PD2555,10211;PD2537,10209;PD2517,10209;PD2517,10160;PD2500,10160;PD2500,10281;PD2537,10281;PU2679,10281;PD2679,10267;PD2619,10267;PD2619,10231;PD2676,10231;PD2676,10217;PD2619,10217;PD2619,10174;PD2680,10174;PD2680,10160;PD2603,10160;PD2603,10281;PD2679,10281;PU2787,10193;PD2804,10160;PD2786,10160;PD2771,10191;PD2765,10201;PD2759,10207;PD2753,10210;PD2744,10211;PD2726,10211;PD2726,10160;PD2710,10160;PD2710,10281;PD2747,10281;PD2765,10279;PD2777,10272;PD2785,10261;PD2788,10246;PD2786,10236;PD2782,10227;PD2776,10221;PD2767,10217;PD2772,10214;PD2777,10209;PD2782,10202;PD2787,10193;PU2726,10224;PD2747,10224;PD2757,10226;PD2764,10230;PD2769,10237;PD2770,10246;PD2769,10255;PD2764,10262;PD2757,10266;PD2747,10267;PD2726,10267;PD2726,10224;PU3416,10247;PD3438,10188;PD3461,10247;PD3478,10247;PD3478,10160;PD3467,10160;PD3467,10236;PD3444,10177;PD3432,10177;PD3410,10236;PD3410,10160;PD3398,10160;PD3398,10247;PD3416,10247;PU3502,10225;PD3513,10225;PD3513,10186;PD3514,10178;PD3517,10172;PD3521,10169;PD3528,10168;PD3535,10169;PD3541,10173;PD3545,10180;PD3546,10188;PD3546,10225;PD3557,10225;PD3557,10160;PD3546,10160;PD3546,10170;PD3542,10165;PD3537,10161;PD3532,10159;PD3525,10158;PD3515,10160;PD3508,10165;PD3504,10174;PD3502,10186;PD3502,10225;PU3592,10251;PD3592,10160;PD3581,10160;PD3581,10251;PD3592,10251;PU3626,10225;PD3648,10225;PD3648,10217;PD3626,10217;PD3626,10182;PD3626,10175;PD3628,10171;PD3631,10170;PD3637,10169;PD3648,10169;PD3648,10160;PD3637,10160;PD3626,10161;PD3620,10165;PD3616,10171;PD3615,10182;PD3615,10217;PD3607,10217;PD3607,10225;PD3615,10225;PD3615,10244;PD3626,10244;PD3626,10225;PU3674,10225;PD3674,10160;PD3663,10160;PD3663,10225;PD3674,10225;PU3674,10251;PD3674,10237;PD3663,10237;PD3663,10251;PD3674,10251;PU3747,10251;PD3747,10160;PD3736,10160;PD3736,10251;PD3747,10251;PU3781,10225;PD3781,10160;PD3770,10160;PD3770,10225;PD3781,10225;PU3781,10251;PD3781,10237;PD3770,10237;PD3770,10251;PD3781,10251;PU3858,10160;PD3847,10160;PD3847,10199;PD3847,10207;PD3844,10213;PD3839,10216;PD3833,10218;PD3825,10216;PD3819,10212;PD3815,10205;PD3814,10197;PD3814,10160;PD3803,10160;PD3803,10225;PD3814,10225;PD3814,10215;PD3818,10220;PD3823,10224;PD3829,10226;PD3835,10227;PD3845,10225;PD3852,10220;PD3857,10211;PD3858,10199;PD3858,10160;PU3937,10190;PD3888,10190;PD3890,10180;PD3895,10173;PD3902,10169;PD3911,10167;PD3917,10168;PD3923,10169;PD3929,10171;PD3935,10173;PD3935,10163;PD3929,10161;PD3923,10160;PD3917,10159;PD3911,10158;PD3897,10161;PD3886,10167;PD3879,10178;PD3877,10192;PD3879,10206;PD3885,10217;PD3896,10225;PD3909,10227;PD3921,10225;PD3930,10218;PD3935,10208;PD3937,10195;PD3937,10190;PU3909,10218;PD3901,10217;PD3894,10213;PD3890,10207;PD3888,10198;PD3927,10199;PD3925,10206;PD3922,10213;PD3916,10217;PD3909,10218;PU3967,10225;PD3989,10225;PD3989,10217;PD3967,10217;PD3967,10182;PD3968,10175;PD3969,10171;PD3973,10170;PD3978,10169;PD3989,10169;PD3989,10160;PD3978,10160;PD3968,10161;PD3961,10165;PD3958,10171;PD3956,10182;PD3956,10217;PD3949,10217;PD3949,10225;PD3956,10225;PD3956,10244;PD3967,10244;PD3967,10225;PU4061,10190;PD4011,10190;PD4013,10180;PD4018,10173;PD4025,10169;PD4034,10167;PD4041,10168;PD4046,10169;PD4052,10171;PD4058,10173;PD4058,10163;PD4052,10161;PD4046,10160;PD4040,10159;PD4034,10158;PD4020,10161;PD4009,10167;PD4002,10178;PD4000,10192;PD4002,10206;PD4009,10217;PD4019,10225;PD4032,10227;PD4044,10225;PD4053,10218;PD4059,10208;PD4061,10195;PD4061,10190;PU4032,10218;PD4024,10217;PD4018,10213;PD4013,10207;PD4011,10198;PD4050,10199;PD4048,10206;PD4045,10213;PD4039,10217;PD4032,10218;PU4108,10194;PD4133,10160;PD4120,10160;PD4101,10186;PD4082,10160;PD4069,10160;PD4095,10194;PD4071,10225;PD4084,10225;PD4101,10202;PD4119,10225;PD4131,10225;PD4108,10194;PU4160,10225;PD4182,10225;PD4182,10217;PD4160,10217;PD4160,10182;PD4161,10175;PD4162,10171;PD4166,10170;PD4171,10169;PD4182,10169;PD4182,10160;PD4171,10160;PD4161,10161;PD4154,10165;PD4150,10171;PD4149,10182;PD4149,10217;PD4141,10217;PD4141,10225;PD4149,10225;PD4149,10244;PD4160,10244;PD4160,10225;PU4248,10247;PD4248,10237;PD4210,10237;PD4210,10212;PD4244,10212;PD4244,10202;PD4210,10202;PD4210,10160;PD4198,10160;PD4198,10247;PD4248,10247;PU4276,10203;PD4278,10189;PD4283,10177;PD4292,10170;PD4304,10168;PD4315,10170;PD4324,10177;PD4330,10189;PD4331,10203;PD4330,10218;PD4324,10230;PD4315,10237;PD4304,10239;PD4292,10237;PD4283,10230;PD4278,10218;PD4276,10203;PU4344,10203;PD4341,10185;PD4333,10171;PD4320,10161;PD4304,10158;PD4287,10161;PD4274,10171;PD4266,10185;PD4263,10203;PD4266,10222;PD4274,10236;PD4287,10246;PD4304,10249;PD4320,10246;PD4333,10236;PD4341,10222;PD4344,10203;PU4372,10203;PD4374,10189;PD4380,10177;PD4388,10170;PD4400,10168;PD4411,10170;PD4420,10177;PD4426,10189;PD4428,10203;PD4426,10218;PD4420,10230;PD4411,10237;PD4400,10239;PD4388,10237;PD4380,10230;PD4374,10218;PD4372,10203;PU4440,10203;PD4437,10185;PD4429,10171;PD4416,10161;PD4400,10158;PD4383,10161;PD4371,10171;PD4362,10185;PD4360,10203;PD4362,10222;PD4371,10236;PD4383,10246;PD4400,10249;PD4416,10246;PD4429,10236;PD4437,10222;PD4440,10203;PU5716,10196;PD5696,10196;PD5696,10206;PD5727,10206;PD5727,10168;PD5720,10164;PD5712,10161;PD5704,10159;PD5695,10158;PD5676,10161;PD5663,10170;PD5654,10185;PD5651,10203;PD5654,10222;PD5663,10237;PD5676,10246;PD5695,10249;PD5703,10248;PD5711,10247;PD5718,10244;PD5725,10240;PD5725,10228;PD5718,10233;PD5711,10236;PD5704,10238;PD5696,10239;PD5682,10237;PD5672,10230;PD5666,10219;PD5664,10203;PD5666,10188;PD5672,10177;PD5682,10170;PD5696,10168;PD5702,10168;PD5707,10169;PD5711,10170;PD5716,10172;PD5716,10196;PU5780,10217;PD5772,10216;PD5766,10211;PD5762,10204;PD5761,10194;PD5761,10160;PD5750,10160;PD5750,10225;PD5761,10225;PD5761,10215;PD5765,10220;PD5770,10224;PD5776,10226;PD5783,10227;PD5784,10227;PD5785,10227;PD5787,10227;PD5788,10226;PD5788,10215;PD5786,10216;PD5784,10217;PD5782,10217;PD5780,10217;PU5804,10193;PD5805,10182;PD5809,10174;PD5815,10169;PD5822,10167;PD5830,10169;PD5836,10174;PD5840,10182;PD5841,10193;PD5840,10203;PD5836,10211;PD5830,10216;PD5822,10218;PD5815,10216;PD5809,10211;PD5805,10203;PD5804,10193;PU5852,10193;PD5850,10178;PD5844,10167;PD5835,10161;PD5822,10158;PD5810,10161;PD5800,10167;PD5794,10178;PD5792,10193;PD5794,10207;PD5800,10218;PD5810,10225;PD5822,10227;PD5835,10225;PD5844,10218;PD5850,10207;PD5852,10193;PU5871,10225;PD5882,10225;PD5882,10186;PD5882,10178;PD5885,10172;PD5890,10169;PD5896,10168;PD5904,10169;PD5910,10173;PD5914,10180;PD5915,10188;PD5915,10225;PD5926,10225;PD5926,10160;PD5915,10160;PD5915,10170;PD5911,10165;PD5906,10161;PD5900,10159;PD5894,10158;PD5884,10160;PD5877,10165;PD5872,10174;PD5871,10186;PD5871,10225;PU5960,10135;PD5949,10135;PD5949,10225;PD5960,10225;PD5960,10215;PD5964,10221;PD5968,10224;PD5974,10226;PD5981,10227;PD5992,10225;PD6000,10217;PD6006,10207;PD6008,10193;PD6006,10179;PD6000,10168;PD5992,10161;PD5981,10158;PD5974,10159;PD5968,10161;PD5964,10165;PD5960,10170;PD5960,10135;PU5978,10218;PD5970,10216;PD5965,10211;PD5961,10203;PD5960,10193;PD5961,10182;PD5965,10174;PD5970,10169;PD5978,10167;PD5986,10169;PD5991,10174;PD5995,10182;PD5996,10193;PD5995,10203;PD5991,10211;PD5986,10216;PD5978,10218;PU6083,10190;PD6034,10190;PD6036,10180;PD6040,10173;PD6047,10169;PD6057,10167;PD6063,10168;PD6069,10169;PD6075,10171;PD6080,10173;PD6080,10163;PD6075,10161;PD6069,10160;PD6063,10159;PD6056,10158;PD6042,10161;PD6032,10167;PD6025,10178;PD6022,10192;PD6025,10206;PD6031,10217;PD6041,10225;PD6054,10227;PD6066,10225;PD6075,10218;PD6081,10208;PD6083,10195;PD6083,10190;PU6055,10218;PD6047,10217;PD6040,10213;PD6036,10207;PD6034,10198;PD6072,10199;PD6071,10206;PD6067,10213;PD6062,10217;PD6055,10218;PU6145,10251;PD6156,10251;PD6156,10160;PD6145,10160;PD6145,10170;PD6142,10165;PD6137,10161;PD6131,10159;PD6124,10158;PD6114,10161;PD6105,10168;PD6100,10179;PD6098,10193;PD6100,10207;PD6105,10217;PD6114,10225;PD6124,10227;PD6131,10226;PD6137,10224;PD6142,10221;PD6145,10215;PD6145,10251;PU6127,10167;PD6135,10169;PD6140,10174;PD6144,10182;PD6145,10193;PD6144,10203;PD6140,10211;PD6135,10216;PD6127,10218;PD6119,10216;PD6114,10211;PD6110,10203;PD6109,10193;PD6110,10182;PD6114,10174;PD6119,10169;PD6127,10167;PU5675,9912;PD5705,9912;PD5705,9900;PD5675,9900;PD5675,9851;PD5676,9842;PD5678,9837;PD5682,9835;PD5690,9834;PD5705,9834;PD5705,9821;PD5690,9821;PD5676,9823;PD5666,9828;PD5661,9837;PD5660,9851;PD5660,9900;PD5649,9900;PD5649,9912;PD5660,9912;PD5660,9938;PD5675,9938;PD5675,9912;PU5804,9863;PD5736,9863;PD5738,9850;PD5745,9840;PD5755,9834;PD5768,9832;PD5776,9832;PD5785,9834;PD5793,9836;PD5800,9840;PD5800,9826;PD5792,9823;PD5784,9821;PD5776,9819;PD5767,9819;PD5748,9822;PD5733,9832;PD5723,9846;PD5720,9866;PD5723,9886;PD5732,9901;PD5746,9911;PD5764,9914;PD5781,9911;PD5793,9902;PD5801,9888;PD5804,9870;PD5804,9863;PU5765,9901;PD5753,9900;PD5745,9894;PD5739,9886;PD5736,9875;PD5789,9875;PD5787,9886;PD5782,9894;PD5775,9900;PD5765,9901;PU5869,9868;PD5904,9821;PD5886,9821;PD5860,9857;PD5834,9821;PD5816,9821;PD5851,9869;PD5819,9912;PD5837,9912;PD5861,9880;PD5885,9912;PD5902,9912;PD5869,9868;PU5942,9912;PD5973,9912;PD5973,9900;PD5942,9900;PD5942,9851;PD5943,9842;PD5945,9837;PD5950,9835;PD5957,9834;PD5973,9834;PD5973,9821;PD5957,9821;PD5943,9823;PD5934,9828;PD5929,9837;PD5927,9851;PD5927,9900;PD5916,9900;PD5916,9912;PD5927,9912;PD5927,9938;PD5942,9938;PD5942,9912;PU1129,9031;PD2258,9031;PD2258,7902;PD1129,7902;PD1129,9031;PU3387,9031;PD5644,9031;PD5644,7902;PD3387,7902;PD3387,9031;PU7281,9031;PD8524,9031;PD8576,9029;PD8626,9022;PD8675,9011;PD8721,8997;PD8766,8978;PD8807,8956;PD8846,8931;PD8882,8902;PD8915,8871;PD8944,8837;PD8970,8801;PD8991,8762;PD9008,8722;PD9021,8680;PD9028,8636;PD9031,8591;PD9031,8342;PD9028,8297;PD9021,8253;PD9008,8211;PD8991,8171;PD8970,8132;PD8944,8096;PD8915,8062;PD8882,8031;PD8846,8003;PD8807,7977;PD8766,7955;PD8721,7937;PD8675,7922;PD8626,7911;PD8576,7904;PD8524,7902;PD7281,7902;PD7229,7904;PD7178,7911;PD7130,7922;PD7083,7937;PD7039,7955;PD6997,7977;PD6958,8003;PD6922,8031;PD6889,8062;PD6860,8096;PD6835,8132;PD6813,8171;PD6796,8211;PD6784,8253;PD6776,8297;PD6773,8342;PD6773,8591;PD6776,8636;PD6784,8680;PD6796,8722;PD6813,8762;PD6835,8801;PD6860,8837;PD6889,8871;PD6922,8902;PD6958,8931;PD6997,8956;PD7039,8978;PD7083,8997;PD7130,9011;PD7178,9022;PD7229,9029;PD7281,9031;PU; \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__methane__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__methane__--cw_wound__True.out new file mode 100644 index 0000000..9bd5bde --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__methane__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__oct__--r1_ax__z__--r1_ang__45__--th__4__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__oct__--r1_ax__z__--r1_ang__45__--th__4__--cw_wound__True.out new file mode 100644 index 0000000..1327760 --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__edg__--obj__oct__--r1_ax__z__--r1_ang__45__--th__4__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__x__--r1_ang__45__--r2_ax__y__--r2_ang__45__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__x__--r1_ang__45__--r2_ax__y__--r2_ang__45__--cw_wound__True.out new file mode 100644 index 0000000..5b78bb8 --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__x__--r1_ang__45__--r2_ax__y__--r2_ang__45__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__y__--r1_ang__45__--z_sort__cent__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__y__--r1_ang__45__--z_sort__cent__--cw_wound__True.out new file mode 100644 index 0000000..703447a --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__y__--r1_ang__45__--z_sort__cent__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__z__--r1_ang__45__--z_sort__max__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__z__--r1_ang__45__--z_sort__max__--cw_wound__True.out new file mode 100644 index 0000000..a7e0a5d --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__cube__--r1_ax__z__--r1_ang__45__--z_sort__max__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__from_file__--spec_file__great_stel_dodec__obj__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__from_file__--spec_file__great_stel_dodec__obj__--cw_wound__True.out new file mode 100644 index 0000000..f3a5255 --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__fce__--obj__from_file__--spec_file__great_stel_dodec__obj__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__--show__vtx__--obj__methane__--cw_wound__True.out b/share/extensions/tests/data/refs/polyhedron_3d__--show__vtx__--obj__methane__--cw_wound__True.out new file mode 100644 index 0000000..9870376 --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__--show__vtx__--obj__methane__--cw_wound__True.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/polyhedron_3d__31c852a9dcfffc92123ff370cba34361.out b/share/extensions/tests/data/refs/polyhedron_3d__31c852a9dcfffc92123ff370cba34361.out new file mode 100644 index 0000000..dc24f34 --- /dev/null +++ b/share/extensions/tests/data/refs/polyhedron_3d__31c852a9dcfffc92123ff370cba34361.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/refs/prepare_file_save_as.out b/share/extensions/tests/data/refs/prepare_file_save_as.out new file mode 100644 index 0000000..999f85f --- /dev/null +++ b/share/extensions/tests/data/refs/prepare_file_save_as.out @@ -0,0 +1,115 @@ + + + + + image/svg+xml + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/previous_glyph_layer.out b/share/extensions/tests/data/refs/previous_glyph_layer.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/previous_glyph_layer__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/previous_glyph_layer__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/print_win32_vector.out b/share/extensions/tests/data/refs/print_win32_vector.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/print_win32_vector__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/print_win32_vector__--id__p1__--id__r3.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/printing_marks.out b/share/extensions/tests/data/refs/printing_marks.out new file mode 100644 index 0000000..f720f14 --- /dev/null +++ b/share/extensions/tests/data/refs/printing_marks.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/printing_marks__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/printing_marks__--id__p1__--id__r3.out new file mode 100644 index 0000000..f720f14 --- /dev/null +++ b/share/extensions/tests/data/refs/printing_marks__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/printing_marks__fcb9f72a813c7f3f65cc9dbdb50c294a.out b/share/extensions/tests/data/refs/printing_marks__fcb9f72a813c7f3f65cc9dbdb50c294a.out new file mode 100644 index 0000000..9ef49f1 --- /dev/null +++ b/share/extensions/tests/data/refs/printing_marks__fcb9f72a813c7f3f65cc9dbdb50c294a.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +Page size: 1000.0x1000.0 px \ No newline at end of file diff --git a/share/extensions/tests/data/refs/ps_input__test__eps.out b/share/extensions/tests/data/refs/ps_input__test__eps.out new file mode 100644 index 0000000..c35759d --- /dev/null +++ b/share/extensions/tests/data/refs/ps_input__test__eps.out @@ -0,0 +1,82 @@ +%PDF-1.4 +%Çì¢ +%%Invocation: path/gs -P- -dSAFER -dCompatibilityLevel=1.4 -dAutoRotatePages=/None -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=? -sOutputFile=? -P- -dSAFER -dCompatibilityLevel=1.4 -dAutoRotatePages=/None ? +5 0 obj +<> +stream +xœ]K1†÷œ‚ ô9C7 ÑqÑ1½"ÛÆÒ–ÂìÈ$ÈÍú[68]2®oØ¡±; ãë†W|SŠÎ‡`ù »ì›E²(¾VDAبd²„ÔÙ_ЃÔ{Ê5;Jª“§¨X ³;î:P¥°˜\2m¯¿]–9ĈT09/3ÂSŒ{—b»öþµ¹}²Q؆þÝ­Àão×;œÍ>ÇœAÌendstream +endobj +6 0 obj +171 +endobj +4 0 obj +<> +/Contents 5 0 R +>> +endobj +3 0 obj +<< /Type /Pages /Kids [ +4 0 R +] /Count 1 +>> +endobj +1 0 obj +<> +endobj +7 0 obj +<>endobj +8 0 obj +<> +endobj +9 0 obj +<>stream + + + + + +2022-03-08T21:09:40+01:00 +2022-03-08T21:09:40+01:00 +cairo 1.15.10 (http://cairographics.org) + +Untitled + + + + + +endstream +endobj +2 0 obj +<>endobj +xref +0 10 +0000000000 65535 f +0000000680 00000 n +0000002256 00000 n +0000000621 00000 n +0000000490 00000 n +0000000230 00000 n +0000000471 00000 n +0000000744 00000 n +0000000785 00000 n +0000000814 00000 n +trailer +<< /Size 10 /Root 1 0 R /Info 2 0 R +/ID [<1B178512AC3E04BC69A8E7E5FE2378BB><1B178512AC3E04BC69A8E7E5FE2378BB>] +>> +startxref +2432 +%%EOF diff --git a/share/extensions/tests/data/refs/ps_input__test__ps.out b/share/extensions/tests/data/refs/ps_input__test__ps.out new file mode 100644 index 0000000..cfbdbc8 Binary files /dev/null and b/share/extensions/tests/data/refs/ps_input__test__ps.out differ diff --git a/share/extensions/tests/data/refs/render_barcode__--type__Code93__--text__3332222.out b/share/extensions/tests/data/refs/render_barcode__--type__Code93__--text__3332222.out new file mode 100644 index 0000000..aa4ba53 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode__--type__Code93__--text__3332222.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + 3332222 + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode__--type__Ean2__--text__55.out b/share/extensions/tests/data/refs/render_barcode__--type__Ean2__--text__55.out new file mode 100644 index 0000000..5795ee5 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode__--type__Ean2__--text__55.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + 5 5 + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode__--type__Upce__--text__123456.out b/share/extensions/tests/data/refs/render_barcode__--type__Upce__--text__123456.out new file mode 100644 index 0000000..334fb2f --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode__--type__Upce__--text__123456.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + 0 123456 + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__rect8x32__--text__1234Foo.out b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__rect8x32__--text__1234Foo.out new file mode 100644 index 0000000..febc9b6 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__rect8x32__--text__1234Foo.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq10.out b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq10.out new file mode 100644 index 0000000..b270ac6 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq10.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq144__--text__HelloTest.out b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq144__--text__HelloTest.out new file mode 100644 index 0000000..1bdb7da --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq144__--text__HelloTest.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq96__--text__Sunshine.out b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq96__--text__Sunshine.out new file mode 100644 index 0000000..be4c31f --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_datamatrix__--symbol__sq96__--text__Sunshine.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__0123456789__--typenumber__0__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__0123456789__--typenumber__0__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out new file mode 100644 index 0000000..b9eaf54 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__0123456789__--typenumber__0__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out @@ -0,0 +1,2 @@ + + diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Blue__Front__Yard__--typenumber__3__--correctionlevel__1__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Blue__Front__Yard__--typenumber__3__--correctionlevel__1__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out new file mode 100644 index 0000000..732616a --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Blue__Front__Yard__--typenumber__3__--correctionlevel__1__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__BreadRolls__--typenumber__2__--encoding__utf8__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__BreadRolls__--typenumber__2__--encoding__utf8__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out new file mode 100644 index 0000000..a84e328 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__BreadRolls__--typenumber__2__--encoding__utf8__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__ThingOne__--drawtype__symbol__--correctionlevel__2__--symbolid__AirTransportation_Inv__--modulesize__10.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__ThingOne__--drawtype__symbol__--correctionlevel__2__--symbolid__AirTransportation_Inv__--modulesize__10.out new file mode 100644 index 0000000..1576a05 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__ThingOne__--drawtype__symbol__--correctionlevel__2__--symbolid__AirTransportation_Inv__--modulesize__10.out @@ -0,0 +1,12 @@ + + + + Air Transportation + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Waterfall__--typenumber__1__--drawtype__pathpreset__--pathtype__circle__--modulesize__10.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Waterfall__--typenumber__1__--drawtype__pathpreset__--pathtype__circle__--modulesize__10.out new file mode 100644 index 0000000..84f55c6 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__Waterfall__--typenumber__1__--drawtype__pathpreset__--pathtype__circle__--modulesize__10.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__groupid__--groupid__testid__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__groupid__--groupid__testid__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out new file mode 100644 index 0000000..238624b --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__groupid__--groupid__testid__--modulesize__10__--drawtype__smooth__--smoothness__greedy.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__--text__test__--drawtype__selection__--id__r3__--modulesize__10.out b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__test__--drawtype__selection__--id__r3__--modulesize__10.out new file mode 100644 index 0000000..e1deb0c --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__--text__test__--drawtype__selection__--id__r3__--modulesize__10.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__a95852ad07710857e3fadaaa059140e8.out b/share/extensions/tests/data/refs/render_barcode_qrcode__a95852ad07710857e3fadaaa059140e8.out new file mode 100644 index 0000000..8244654 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__a95852ad07710857e3fadaaa059140e8.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_barcode_qrcode__e3208cfbf8a72ec55b5335e55f8674db.out b/share/extensions/tests/data/refs/render_barcode_qrcode__e3208cfbf8a72ec55b5335e55f8674db.out new file mode 100644 index 0000000..801d0c6 --- /dev/null +++ b/share/extensions/tests/data/refs/render_barcode_qrcode__e3208cfbf8a72ec55b5335e55f8674db.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_gear_rack.out b/share/extensions/tests/data/refs/render_gear_rack.out new file mode 100644 index 0000000..3c89abc --- /dev/null +++ b/share/extensions/tests/data/refs/render_gear_rack.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_gear_rack__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/render_gear_rack__--id__p1__--id__r3.out new file mode 100644 index 0000000..3c89abc --- /dev/null +++ b/share/extensions/tests/data/refs/render_gear_rack__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_gears__--centerdiameter__10__0.out b/share/extensions/tests/data/refs/render_gears__--centerdiameter__10__0.out new file mode 100644 index 0000000..cb5f548 --- /dev/null +++ b/share/extensions/tests/data/refs/render_gears__--centerdiameter__10__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/render_gears__--id__p1__--id__r3__--centerdiameter__10__0.out b/share/extensions/tests/data/refs/render_gears__--id__p1__--id__r3__--centerdiameter__10__0.out new file mode 100644 index 0000000..cb5f548 --- /dev/null +++ b/share/extensions/tests/data/refs/render_gears__--id__p1__--id__r3__--centerdiameter__10__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/replace_font__--action__find_replace__--fr_find__sans-serif__--fr_replace__monospace.out b/share/extensions/tests/data/refs/replace_font__--action__find_replace__--fr_find__sans-serif__--fr_replace__monospace.out new file mode 100644 index 0000000..30b778d --- /dev/null +++ b/share/extensions/tests/data/refs/replace_font__--action__find_replace__--fr_find__sans-serif__--fr_replace__monospace.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/replace_font__--action__list_only.out b/share/extensions/tests/data/refs/replace_font__--action__list_only.out new file mode 100644 index 0000000..5883134 --- /dev/null +++ b/share/extensions/tests/data/refs/replace_font__--action__list_only.out @@ -0,0 +1 @@ +Found the following font only: sans-serif diff --git a/share/extensions/tests/data/refs/restack__--id__g20858__--id__g21085__--id__g20940__--id__g26580__--id__g21081__--id__g20854.out b/share/extensions/tests/data/refs/restack__--id__g20858__--id__g21085__--id__g20940__--id__g26580__--id__g21081__--id__g20854.out new file mode 100644 index 0000000..799e354 --- /dev/null +++ b/share/extensions/tests/data/refs/restack__--id__g20858__--id__g21085__--id__g20940__--id__g26580__--id__g21081__--id__g20854.out @@ -0,0 +1,38 @@ + + + + + Ungrouped objects + Grouped objects + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/restack__--tab__positional__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out b/share/extensions/tests/data/refs/restack__--tab__positional__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out new file mode 100644 index 0000000..7604bd6 --- /dev/null +++ b/share/extensions/tests/data/refs/restack__--tab__positional__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/restack__--tab__z_order__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out new file mode 100644 index 0000000..7604bd6 --- /dev/null +++ b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r2__--id__t5__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r2__--id__t5__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out new file mode 100644 index 0000000..7915077 --- /dev/null +++ b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r2__--id__t5__--id__p1__--id__r3__--direction__tb__--xanchor__m__--yanchor__m.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + Grouped + text + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r3__--id__p1__--id__t5__--id__r2__--direction__tb__--xanchor__m__--yanchor__m.out b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r3__--id__p1__--id__t5__--id__r2__--direction__tb__--xanchor__m__--yanchor__m.out new file mode 100644 index 0000000..7915077 --- /dev/null +++ b/share/extensions/tests/data/refs/restack__--tab__z_order__--id__r3__--id__p1__--id__t5__--id__r2__--direction__tb__--xanchor__m__--yanchor__m.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + Grouped + text + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/restack__cde2e552c805941baaf79d0821ec1e63.out b/share/extensions/tests/data/refs/restack__cde2e552c805941baaf79d0821ec1e63.out new file mode 100644 index 0000000..7ebd13e --- /dev/null +++ b/share/extensions/tests/data/refs/restack__cde2e552c805941baaf79d0821ec1e63.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/rtree__--minimum__4__0.out b/share/extensions/tests/data/refs/rtree__--minimum__4__0.out new file mode 100644 index 0000000..eeef67a --- /dev/null +++ b/share/extensions/tests/data/refs/rtree__--minimum__4__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__0__--curve__50.out b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__0__--curve__50.out new file mode 100644 index 0000000..671e63c --- /dev/null +++ b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__0__--curve__50.out @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__25__--curve__25.out b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__25__--curve__25.out new file mode 100644 index 0000000..adb25b9 --- /dev/null +++ b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__25__--curve__25.out @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__50__--curve__0.out b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__50__--curve__0.out new file mode 100644 index 0000000..5e0a460 --- /dev/null +++ b/share/extensions/tests/data/refs/rubberstretch__--id__path3997__--ratio__50__--curve__0.out @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/scribus_export_pdf__--pdf-version__13__--bleed__0.out b/share/extensions/tests/data/refs/scribus_export_pdf__--pdf-version__13__--bleed__0.out new file mode 100644 index 0000000..463561d Binary files /dev/null and b/share/extensions/tests/data/refs/scribus_export_pdf__--pdf-version__13__--bleed__0.out differ diff --git a/share/extensions/tests/data/refs/setup_typography_canvas__empty__svg.out b/share/extensions/tests/data/refs/setup_typography_canvas__empty__svg.out new file mode 100644 index 0000000..1db316a --- /dev/null +++ b/share/extensions/tests/data/refs/setup_typography_canvas__empty__svg.out @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/setup_typography_canvas__shapes__svg.out b/share/extensions/tests/data/refs/setup_typography_canvas__shapes__svg.out new file mode 100644 index 0000000..9148166 --- /dev/null +++ b/share/extensions/tests/data/refs/setup_typography_canvas__shapes__svg.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/sk1_output.out b/share/extensions/tests/data/refs/sk1_output.out new file mode 100644 index 0000000..59afc69 --- /dev/null +++ b/share/extensions/tests/data/refs/sk1_output.out @@ -0,0 +1,126 @@ +##sK1 1 2 +document() +layout((800,800),0) +grid((0,0,2.83465,2.83465),0,("RGB",0.83,0.87,0.91),'Grid') +page() +layer('New Layer',1,1,0,0,("RGB",0.196,0.314,0.635)) +G() +fp(("RGB",1.0,0.0,0.0)) +le() +lw(0.895418) +r(198.953,0,0,-161.198,521.047,516.859) +G_() +G() +fp(("RGB",0.0,0.0,0.502)) +le() +lw(0.283286) +e(40,0,0,-40,120,440) +lp(("RGB",1.0,0.0,0.0)) +lw(12.8) +e(80,0,0,-40,320,440) +fp(("RGB",1.0,1.0,0.0)) +lp(("RGB",0.0,0.502,0.0)) +lw(12.8) +b() +bs(626.469,417.741,0) +bs(560,440,0) +bs(626.469,417.741,0) +bC() +lp(("RGB",0.0,0.0,0.0)) +lw(8) +b() +bs(80,320,0) +bs(160,240,0) +bs(240,320,0) +bs(320,240,0) +lp(("RGB",0.0,0.0,0.0)) +lw(8) +b() +bs(400,320,0) +bc(400,320,400,240,480,240,0) +bc(560,240,480,320,560,320,0) +bc(640,320,640,240,640,240,0) +fp(("RGB",1.0,1.0,0.0)) +lp(("RGB",0.0,0.502,0.0)) +lw(8) +b() +bs(195.867,88.688,0) +bs(159.595,95.1955,0) +bs(133.672,69.0055,0) +bs(128.653,105.512,0) +bs(95.7337,122.074,0) +bs(128.903,138.129,0) +bs(134.481,174.554,0) +bs(160,147.97,0) +bs(196.367,153.921,0) +bs(178.969,121.436,0) +bs(195.867,88.688,0) +bC() +fp(("RGB",1.0,1.0,0.0)) +lp(("RGB",0.0,0.502,0.0)) +lw(8) +b() +bs(355.867,86.291,0) +bs(319.595,92.7986,0) +bs(293.672,66.6085,0) +bs(288.653,103.115,0) +bs(255.734,119.677,0) +bs(288.903,135.732,0) +bs(294.481,172.157,0) +bs(320,145.573,0) +bs(356.367,151.524,0) +bs(338.969,119.039,0) +bs(355.867,86.291,0) +bC() +G_() +G() +fp(("RGB",0.0,0.0,0.0)) +le() +lw(0.283286) +Fn('BitstreamVeraSans-Roman') +Fs(14.6667) +txt('\\u048\\u065\\u06c\\u06c\\u06f\\u020\\u057\\u06f\\u072\\u06c\\u064',(0.8,0,0,0.8,80,720),0,0,1,1,1) +fp(("RGB",0.0,0.0,0.0,0.5)) +le() +lw(0.283286) +r(56.0001,0,0,-55.4909,320,730.381) +fp(("RGB",0.0,0.0,0.0)) +le() +lw(0.283286) +Fn('BitstreamVeraSans-Roman') +Fs(14.6667) +txt('\\u055\\u050\\u050\\u045\\u052',(0.8,0,0,0.8,160,720),0,0,1,1,1) +fp(("RGB",0.0,0.0,0.0)) +le() +lw(0.283286) +Fn('BitstreamVeraSans-Roman') +Fs(10.5833) +txt('\\u04d\\u075\\u06c\\u074\\u069\\u020\\u06c\\u069\\u06e\\u065\\u074\\u065\\u078\\u074\\u046\\u04f\\u04f',(0.8,0,0,0.8,240,720),0,0,1,1,1) +G() +fp(("RGB",0.0,0.0,0.0)) +le() +lw(0.283286) +Fn('BitstreamVeraSans-Roman') +Fs(10.5833) +txt('\\u047\\u072\\u06f\\u075\\u070\\u065\\u064',(0.8,0,0,0.8,400,720),0,0,1,1,1) +fp(("RGB",0.0,0.0,0.0)) +le() +lw(0.283286) +Fn('BitstreamVeraSans-Roman') +Fs(14.6667) +txt('\\u074\\u065\\u078\\u074',(0.8,0,0,0.8,400,696),0,0,1,1,1) +G_() +fp(("RGB",0.0,0.0,0.502)) +le() +lw(0.283286) +r(80,0,0,-80,80,640) +lp(("RGB",1.0,0.0,0.0)) +lw(12.8) +r(160,0,0,-80,240,640) +fp(("RGB",1.0,1.0,0.0)) +lp(("RGB",0.0,0.502,0.0)) +lw(12.8) +r(160,0,0,-80,480,640,0.224716,0.389508) +G_() +masterlayer('MasterLayer 1',1,1,0,0,("RGB",0.196,0.314,0.635)) +guidelayer('Guide Lines',1,0,0,1,("RGB",0.0,0.3,1.0)) diff --git a/share/extensions/tests/data/refs/spirograph__--primaryr__60__0__--secondaryr__100__0.out b/share/extensions/tests/data/refs/spirograph__--primaryr__60__0__--secondaryr__100__0.out new file mode 100644 index 0000000..cc27d4d --- /dev/null +++ b/share/extensions/tests/data/refs/spirograph__--primaryr__60__0__--secondaryr__100__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/straightseg.out b/share/extensions/tests/data/refs/straightseg.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/straightseg__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/straightseg__--id__p1__--id__r3.out new file mode 100644 index 0000000..f05ae54 --- /dev/null +++ b/share/extensions/tests/data/refs/straightseg__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/svgcalendar__9cc828f60a4a546fd4e0fdf4dd392e96.out b/share/extensions/tests/data/refs/svgcalendar__9cc828f60a4a546fd4e0fdf4dd392e96.out new file mode 100644 index 0000000..fae3a9c --- /dev/null +++ b/share/extensions/tests/data/refs/svgcalendar__9cc828f60a4a546fd4e0fdf4dd392e96.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + +2019JanuarySunMonTueWedThuFriSat303112345678910111213141516171819202122232425262728293031123456789FebruarySunMonTueWedThuFriSat272829303112345678910111213141516171819202122232425262728123456789MarchSunMonTueWedThuFriSat242526272812345678910111213141516171819202122232425262728293031123456AprilSunMonTueWedThuFriSat311234567891011121314151617181920212223242526272829301234567891011MaySunMonTueWedThuFriSat2829301234567891011121314151617181920212223242526272829303112345678JuneSunMonTueWedThuFriSat262728293031123456789101112131415161718192021222324252627282930123456JulySunMonTueWedThuFriSat301234567891011121314151617181920212223242526272829303112345678910AugustSunMonTueWedThuFriSat28293031123456789101112131415161718192021222324252627282930311234567SeptemberSunMonTueWedThuFriSat123456789101112131415161718192021222324252627282930123456789101112OctoberSunMonTueWedThuFriSat293012345678910111213141516171819202122232425262728293031123456789NovemberSunMonTueWedThuFriSat27282930311234567891011121314151617181920212223242526272829301234567DecemberSunMonTueWedThuFriSat123456789101112131415161718192021222324252627282930311234567891011 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/svgfont2layers__--count__3.out b/share/extensions/tests/data/refs/svgfont2layers__--count__3.out new file mode 100644 index 0000000..ec11f1d --- /dev/null +++ b/share/extensions/tests/data/refs/svgfont2layers__--count__3.out @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/synfig_output.out b/share/extensions/tests/data/refs/synfig_output.out new file mode 100644 index 0000000..f982632 --- /dev/null +++ b/share/extensions/tests/data/refs/synfig_output.out @@ -0,0 +1,3 @@ + + input.svg + 0.00.01.00.00.01.00.00.02.52181499999999972.43455650000000026.66666699999999952.43455650000000026.6666669999999995-0.92374516666666672.5218149999999997-0.92374516666666670.00.00.00.00.50196078431372551.00.00.0-5.00.8333333333333334-5.2440776823445430.24407768234454277-5.8333333333333330.0-6.4225889843221230.24407768234454277-6.6666666666666670.8333333333333334-6.4225889843221231.422588984322124-5.8333333333333331.6666666666666667-5.2440776823445431.4225889843221241.00.00.01.00.00.00.00.8333333333333334-0.48815536468908650.24407768234454277-1.66666666666666670.0-2.84517796864424580.24407768234454277-3.33333333333333350.8333333333333334-2.84517796864424671.422588984322124-1.66666666666666671.6666666666666667-0.48815536468908651.4225889843221241.01.00.01.00.00.04.7181058333333340.36960316666666512.86646450000000060.033362833333336541.66708099999999980.81475333333334182.7956021666666671.62210183333333284.6753821666666661.32746966666666523.33333333333333350.83333333333333340.00.50196078431372550.01.00.00.04.7181058333333340.36960316666666512.86646450000000060.033362833333336541.66708099999999980.81475333333334182.7956021666666671.62210183333333284.6753821666666661.32746966666666523.33333333333333350.83333333333333340.00.00.01.00.00.0-6.666666666666667-1.6666666666666667-5.0-3.3333333333333335-3.3333333333333335-1.6666666666666667-1.6666666666666667-3.33333333333333350.00.00.01.00.00.00.0-1.66666666666666671.6666666666666667-3.33333333333333353.3333333333333335-1.66666666666666675.0-3.33333333333333351.01.00.01.00.00.0-4.25278-6.4856675-5.008427833333333-6.3500931666666665-5.548499166666667-6.895718666666666-5.653068333333334-6.13516-6.338880333333333-5.790129333333335-5.647859666666666-5.4556525-5.5316434999999995-4.696786333333334-5.0-5.250627000000001-4.242362666666667-5.1266525000000005-4.604809500000001-5.8034216666666660.00.50196078431372550.01.00.00.0-4.25278-6.4856675-5.008427833333333-6.3500931666666665-5.548499166666667-6.895718666666666-5.653068333333334-6.13516-6.338880333333333-5.790129333333335-5.647859666666666-5.4556525-5.5316434999999995-4.696786333333334-5.0-5.250627000000001-4.242362666666667-5.1266525000000005-4.604809500000001-5.8034216666666661.01.00.01.00.00.0-0.9194468333333333-6.535604333333334-1.6750948333333335-6.400030166666666-2.2151660000000004-6.945655666666666-2.3197353333333335-6.185097-3.0055471666666667-5.8400663333333345-2.3145265000000004-5.5055895-2.1983105000000003-4.746723333333334-1.6666670000000001-5.3005638333333325-0.9090294999999997-5.1765895-1.2714765-5.8533586666666660.00.50196078431372550.01.00.00.0-0.9194468333333333-6.535604333333334-1.6750948333333335-6.400030166666666-2.2151660000000004-6.945655666666666-2.3197353333333335-6.185097-3.0055471666666667-5.8400663333333345-2.3145265000000004-5.5055895-2.1983105000000003-4.746723333333334-1.6666670000000001-5.3005638333333325-0.9090294999999997-5.1765895-1.2714765-5.8533586666666660.00.00.00.00.01.00.00.0-6.6426756666666666.844868033333333-6.61856556.844868033333333-6.61856556.771820983333333-6.53095666666666656.771820983333333-6.53095666666666656.844868033333333-6.50684656.844868033333333-6.50684656.666666666666667-6.53095666666666656.666666666666667-6.53095666666666656.75153015-6.61856556.75153015-6.61856556.666666666666667-6.6426756666666666.6666666666666670.00.00.01.00.00.0-6.3454666666666676.738998333333332-6.3454666666666676.7282561166666675-6.44644356.7282561166666675-6.4328366666666666.693642283333334-6.3987003333333336.681825849999999-6.3742326.684929166666666-6.3505996.694239083333334-6.3505996.673470749999999-6.3748286666666676.665831850000001-6.4000133333333336.663206016666667-6.4507403333333336.681825849999999-6.4693601666666666.73219485-6.4516951666666666.78423485-6.4038326666666676.80357085-6.3612226.786144516666667-6.3454666666666666.738998183333333-6.3454666666666676.738998333333332-6.36743333333333356.745443333333332-6.3775788333333336.774208666666667-6.4035988333333346.784950883333333-6.4330801666666676.774566733333334-6.4457321666666676.745324066666668-6.36743333333333356.745443333333332-6.36743333333333356.745443333333332-6.3454666666666676.7389983333333320.00.00.01.00.00.0-6.3094284999999996.852387583333333-6.28746656.852387583333333-6.28746656.666666666666667-6.3094284999999996.6666666666666670.00.00.01.00.00.0-6.2415138333333336.852387583333333-6.2195519999999996.852387583333333-6.2195519999999996.666666666666667-6.2415138333333336.6666666666666670.00.00.01.00.00.0-6.12179999999999956.784949999999999-6.1497296666666676.771104466666666-6.15999456.7333873-6.1498490000000016.695550800000001-6.12179999999999956.681824633333334-6.09398956.695670150000001-6.0837248333333336.733387316666667-6.09398956.77098515-6.12179999999999956.784950033333333-6.12179999999999956.784949999999999-6.12179999999999956.80357-6.0768026.784950166666666-6.06044999999999946.7333875-6.0768026.681824833333334-6.12179999999999956.663205000000001-6.1669171666666676.681824833333334-6.1831498333333336.7333875-6.1669171666666676.784950166666666-6.12179999999999956.80357-6.12179999999999956.80357-6.12179999999999956.80357-6.12179999999999956.7849499999999990.00.00.01.00.00.0-5.9612615000000016.844868033333333-5.93691256.844868033333333-5.8994346.694238350000001-5.8620750000000016.844868033333333-5.8349808333333346.844868033333333-5.7975023333333336.694238350000001-5.7601433333333346.844868033333333-5.7356750000000016.844868033333333-5.7804341666666676.666666666666667-5.8107511666666676.666666666666667-5.84834883333333366.821354516666668-5.8863046666666666.666666666666667-5.9166215000000016.6666666666666670.00.00.01.00.00.0-5.6671666666666666.784949999999999-5.6950963333333346.771104466666666-5.7053611666666676.7333873-5.6952158333333336.695550800000001-5.6671666666666666.681824633333334-5.6393563333333346.695670150000001-5.62909156.733387316666667-5.6393563333333346.77098515-5.6671666666666666.784950033333333-5.6671666666666666.784949999999999-5.6671666666666666.80357-5.6221686666666666.784950166666666-5.6058166666666676.7333875-5.6221686666666666.681824833333334-5.6671666666666666.663205000000001-5.71228399999999956.681824833333334-5.7285166666666676.7333875-5.71228399999999956.784950166666666-5.6671666666666666.80357-5.6671666666666666.80357-5.6671666666666666.80357-5.6671666666666666.7849499999999990.00.00.01.00.00.0-5.4919461666666676.779817966666667-5.5000624999999996.7829212666666665-5.5096111666666686.783995433333333-5.5382570000000016.771820916666667-5.54816366666666656.737087766666667-5.54816366666666656.666666666666667-5.5702456.666666666666667-5.5702456.800347533333333-5.54816366666666656.800347533333333-5.54816366666666656.77957925-5.5301406666666676.797602299999999-5.5031658333333336.803570199999999-5.4981526666666676.8032122-5.49206556.80237670.00.00.01.00.00.0-5.4689099999999996.852387583333333-5.4469481666666676.852387583333333-5.4469481666666676.666666666666667-5.4689099999999996.6666666666666670.00.00.01.00.00.0-5.3130333333333346.780056666666667-5.3130333333333346.852388333333333-5.2910666666666676.852388333333333-5.2910666666666676.666666666666667-5.3130286666666676.666666666666667-5.3130286666666676.686718833333333-5.3305741666666676.668934500000001-5.3558786.663205366666667-5.39538556.682541366666667-5.4105440000000016.733387866666667-5.39538556.784234366666667-5.3558786.803570366666667-5.3305741666666676.797721816666668-5.3130286666666676.780056816666667-5.3130333333333346.780056666666667-5.3878666666666676.733388333333333-5.377966.695313166666667-5.3505076666666666.6815869999999995-5.3230553333333336.695313166666667-5.3130293333333336.733388333333333-5.3230553333333336.771344166666667-5.3505076666666666.785189683333332-5.377966.771344166666667-5.3878666666666676.733388333333333-5.3878666666666676.733388333333333-5.3878666666666676.733388333333333-5.3130333333333346.7800566666666670.00.00.01.00.00.0-1.5967173111865016.852388455020832-1.53560622289916766.852388455020832-1.53560622289916766.666668122332834-1.5576873940386676.666668122332834-1.5576873940386676.834126759972166-1.59695600914966756.834126759972166-1.61342735923166756.829352447931501-1.61796292921200046.812164959862832-1.61796292921200046.800348594888501-1.5817976081086.800348594888501-1.5817976081086.783280433752833-1.61796292921200046.783280433752833-1.61796292921200046.666668122332834-1.64004410035150076.666668122332834-1.64004410035150076.783280433752833-1.66105102041383366.783280433752833-1.66105102041383366.800348594888501-1.64004410035150076.800348594888501-1.64004410035150076.809658476909501-1.62965996725333386.8421237370500005-1.5967173111865016.8523884550208340.00.00.01.00.00.0-1.4378531672333346.784951760466667-1.46578285739350066.771106264368166-1.47604761946150046.7333892962606665-1.4659022284236676.695552957123001-1.4378531672333346.681826832054666-1.41004289220050046.695672328153167-1.39977813013250056.7333892962606665-1.41004289220050046.7709869374351666-1.4378531672333346.784951760466667-1.4378531672333346.784951760466667-1.4378531672333346.803569584233332-1.39285553642333376.784949820191334-1.3765035132743346.733387444179668-1.39285553642333376.681825068167999-1.4378531672333346.663205304125999-1.48297030136500046.681825068167999-1.49920290938666776.733387444179668-1.48297030136500046.784949820191334-1.4378531672333346.803569584233332-1.4378531672333346.803569584233332-1.4378531672333346.803569584233332-1.4378531672333346.7849517604666670.00.00.01.00.00.0-1.35286981318800016.800348594888501-1.33090801307866686.800348594888501-1.30345580703916736.696030088466333-1.27612292793266716.800348594888501-1.25022232479950066.800348594888501-1.22277007466283386.696030088466333-1.19543719555633376.800348594888501-1.17347539544700036.800348594888501-1.20844718263800056.666668122332834-1.2343477857711676.666668122332834-1.2631129408516.776238336722001-1.29199746696100046.666668122332834-1.3178980700941676.6666681223328340.00.00.01.00.00.0-1.04074980293833426.838304260959167-1.04074980293833426.800348594888501-0.99551325367933336.800348594888501-0.99551325367933336.783280433752833-1.04074980293833426.783280433752833-1.04074980293833426.7107110494845-1.03633355989100086.689704129422167-1.01807186484233336.685049188411667-0.99551325367933336.685049188411667-0.99551325367933336.666668122332834-1.01807186484233336.666668122332834-1.05316297896633376.676097375384001-1.06283092998066696.7107110494845-1.06283092998066696.783280433752833-1.0789442110693346.783280433752833-1.0789442110693346.800348594888501-1.06283092998066696.800348594888501-1.06283092998066696.8383042609591670.00.00.01.00.00.0-0.85228248135000046.738998103083333-0.85228248135000046.728255900991834-0.95325881941333356.728255900991834-0.93965202127800086.693642226891332-0.9055157872016.681825817819833-0.88104746004116716.6849291118268335-0.85741468599533356.694238993847834-0.85741468599533356.673470771748667-0.88164427109483476.665831907761333-0.90682869214416736.663206053777833-0.95755586781916696.681825817819833-0.97617563186116746.732194924501501-0.95851070376900046.784234872828167-0.91064852101233386.8035707748568335-0.86803786983400086.7861445888250005-0.85228265773866766.7389985440550015-0.85228248135000046.738998103083333-0.87424728006666716.74544510885-0.88439267110450056.774210263929833-0.91041260117066746.784952466021334-0.93989393833433426.7745683770203335-0.95254581232550026.745325737819834-0.87424728006666716.74544510885-0.87424728006666716.74544510885-0.85228248135000046.7389981030833330.00.00.01.00.00.0-0.70941321759300056.800348594888501-0.75775301676183356.735298703577333-0.70690669054249996.666668122332834-0.73280729367566746.666668122332834-0.77171783979333396.719185422488666-0.81062838591100036.666668122332834-0.83652898904416686.666668122332834-0.78460845584483356.736611652617667-0.83211274599683436.800348594888501-0.80621218696083376.800348594888501-0.77076295974633426.752724889609167-0.73531377662900096.8003485948885010.00.00.01.00.00.0-0.65415069242350046.838304260959167-0.65415069242350046.800348594888501-0.60891414316450046.800348594888501-0.60891414316450046.783280433752833-0.65415069242350046.783280433752833-0.65415069242350046.7107110494845-0.64973444937616696.689704129422167-0.63147275432750036.685049188411667-0.60891414316450046.685049188411667-0.60891414316450046.666668122332834-0.63147275432750036.666668122332834-0.66656386845150076.676097375384001-0.67623181946583396.7107110494845-0.67623181946583396.783280433752833-0.69234510055449996.783280433752833-0.69234510055449996.800348594888501-0.67623181946583396.800348594888501-0.67623181946583396.8383042609591670.00.00.01.00.00.0-1.65639607940333346.494793197548999-1.63443427929400036.494793197548999-1.60698202915733366.390474691126834-1.57964915005083346.494793197548999-1.55374859101483396.494793197548999-1.52629634087816736.390474691126834-1.4989634617716676.494793197548999-1.47700166166233386.494793197548999-1.51197344885333386.361112769090499-1.53787400788933346.361112769090499-1.56663920706633356.470682983479666-1.59552373317633376.361112769090499-1.62142429221233436.3611127690904990.00.00.01.00.00.0-1.33257903111233426.441798457369667-1.33257903111233426.361112769090499-1.35454083122166746.361112769090499-1.35454083122166746.441082319382999-1.36194099724583386.4694894054695-1.38414149531833376.478918658520667-1.41219051241149976.467579689472666-1.42245527447950056.4366660763356665-1.42245527447950056.361112769090499-1.4445364015218346.361112769090499-1.4445364015218346.5468331017785-1.42245527447950056.5468331017785-1.42245527447950056.474025019546999-1.40395483737050026.492047972535333-1.37924781224749986.498015862586166-1.3443954401838346.483692970561333-1.33257903111233426.4417984573696670.00.00.01.00.00.0-1.28877387588333366.4947924038-1.26681207577400056.4947924038-1.26681207577400056.361111843049999-1.28877387588333366.361111843049999-1.28877387588333366.4947924038-1.28877387588333366.546831470183334-1.26681207577400056.546831470183334-1.26681207577400056.519021151053333-1.28877387588333366.519021151053333-1.28877387588333366.546831470183334-1.28877387588333366.546831470183334-1.28877387588333366.49479240380.00.00.01.00.00.0-1.12465815625466716.489660816515-1.12465815625466716.469131336476166-1.1433972913268346.4767702004635-1.16225579742916726.479396098544167-1.19543719555633376.465789344506001-1.20725360462783356.427833634338167-1.19543719555633376.389758553140166-1.16225579742916726.376271170132168-1.1433972913268346.378777653085502-1.12465815625466716.386535932200166-1.12465815625466716.366245106027335-1.1437553603201676.359799820050167-1.16464295344950046.357651361993001-1.21262468362500056.3766292391255-1.23040893865016696.427833634338167-1.21250531259483426.479276727514001-1.16321067747616666.4980158625861675-1.1433972913268346.495867448626168-1.12465815625466716.4896608165150.00.00.01.00.00.0-0.97534188673099996.441798457369667-0.97534188673099996.361112769090499-0.99730364274316716.361112769090499-0.99730364274316716.441082319382999-1.00470380876733356.4694894054695-1.02690435093700026.478918658520667-1.05495336803016736.467579689472666-1.0652180860016.4366660763356665-1.0652180860016.361112769090499-1.08729925714049986.361112769090499-1.08729925714049986.5468331017785-1.0652180860016.5468331017785-1.0652180860016.474025019546999-1.04671769298916686.492047972535333-1.02201066786616736.498015862586166-0.98715825170533366.483692970561333-0.97534188673099996.4417984573696670.00.00.01.00.00.0-1.65639607940333346.189237844306666-1.63443427929400036.189237844306666-1.60698202915733366.084919337884499-1.57964915005083346.189237844306666-1.55374859101483396.189237844306666-1.52629634087816736.084919337884499-1.4989634617716676.189237844306666-1.47700166166233386.189237844306666-1.51197344885333386.055557371750999-1.53787400788933346.055557371750999-1.56663920706633356.1651276302373335-1.59552373317633376.055557371750999-1.62142429221233436.0555573717509990.00.00.01.00.00.0-1.3662378692636.168708364267833-1.3743541732738346.171811658274834-1.3839027973551676.172885865254833-1.41254858140483376.160711387190001-1.42245527447950056.125978342059333-1.42245527447950056.055557371750999-1.4445364015218346.055557371750999-1.4445364015218346.189237844306666-1.42245527447950056.189237844306666-1.42245527447950056.168469622207499-1.40443227739400066.186492619293-1.37745746728083426.192460509343834-1.37244445727700036.1921024403505-1.36635719619600026.1912669313336670.00.00.01.00.00.0-1.28245034218333386.122757837783333-1.31933180127400076.116670620799501-1.32959656334200066.095902398700334-1.32195769935466676.077282634658333-1.30095077929233386.070479235590667-1.27170814009183376.083369851642165-1.26060791310416686.117864198809666-1.26060791310416686.122757837783333-1.28245034218333386.122757837783333-1.23864421681666766.1318286249666665-1.23864421681666766.055559047443334-1.2606060169260016.055559047443334-1.2606060169260016.075849829518999-1.2793451519981676.057826876530667-1.30679740213483346.052097684443-1.33950136023850066.063556024521167-1.3515564672731676.094469637658166-1.3365173931645016.128486544802167-1.29140025903283426.1399448407831665-1.2606060169266.1399448407831665-1.2606060169266.142093298840333-1.2706320369336676.165487374923-1.29856172709383396.173842420994166-1.32088159619650016.1710971959805-1.34176914522866666.1628615209395-1.34176914522866666.1831523030151665-1.31837506914600066.190075029015833-1.29629389800656.192462185036167-1.25296710884156.1774231109275-1.23864421681666766.131828404480832-1.23864421681666766.1318286249666665-1.23864421681666766.1318286249666665-1.28245034218333386.1227578377833330.00.00.01.00.00.0-1.17216332835000016.075609147183333-1.17216332835000016.0047106045600005-1.19424445539233376.0047106045600005-1.19424445539233376.189238726249999-1.17216332835000016.189238726249999-1.17216332835000016.168947944174333-1.15473709822100086.186612872266499-1.12943330614150076.192461391287168-1.08992594897016676.173125445161334-1.07464817689833386.122279207136334-1.08992594897016676.071432969111333-1.12943330614150076.0520970229855005-1.15473709822100086.057826215073165-1.17216332835000016.075610470098331-1.17216332835000016.075609147183333-1.09744508915000076.122277178666667-1.1074711091576676.160232844737334-1.13480398826416726.174078340835833-1.16225623840083376.160232844737334-1.17216293147550076.122277178666667-1.16225623840083376.084202097468666-1.13480398826416726.070475972400334-1.1074711091576676.084202097468666-1.09744508915000076.122277178666667-1.09744508915000076.122277178666667-1.09744508915000076.122277178666667-1.17216332835000016.0756091471833330.00.00.01.00.00.0-0.95302201762833366.185299041282834-0.95302201762833366.164530819183667-0.9723579196570016.171692287244666-0.99312614175616726.174079443265-1.01771379584900036.1690664332611655-1.02583014395700066.1540273591525-1.01998158083916726.141972252117834-0.99646817782350086.133736577076833-0.98894864076916736.132065603140332-0.95576724264200076.117862038048499-0.94586054956733396.092438874938834-0.96066088161566756.062957537775166-1.0011231188340016.052096008750666-1.02356231486966756.054244466807832-1.04803064202950026.060451054821832-1.04803064202950026.083128992917834-1.02403975489316776.073580368836501-1.00064567881050076.0704770748295-0.97677416270433366.075728826893665-0.96841911663316676.090767856905165-0.97450637771416766.1044939819735005-1.00088437677366736.113684537061499-1.00852328485816736.115474882028165-1.03800457792466726.128604196042833-1.04707576198250096.153072523202665-1.03370770590756.182195747275833-0.9957520398368346.1924605093438325-0.97283535968050036.19067012028-0.95302201762833366.1852990412828340.00.00.01.00.00.0-4.9787543333333336.844868033333333-4.9545246666666676.844868033333333-4.9545246666666676.736610400000001-4.94414056.695312566666667-4.91048149999999956.682779983333334-4.8769426.695312566666667-4.8665578333333336.736610400000001-4.8665578333333336.844868033333333-4.84232816666666556.844868033333333-4.84232816666666556.733626450000001-4.8596351666666666.6809896166666665-4.91048149999999956.663205333333334-4.9615668333333336.6809896166666665-4.9787543333333336.7336264500000010.00.00.01.00.00.0-4.7729833333333336.825055-4.7729833333333336.758095166666667-4.74266649999999956.758095166666667-4.71664649999999956.766808283333334-4.70745583333333256.791634783333333-4.71664649999999956.816341949999999-4.74266649999999956.825055083333333-4.7729833333333336.825055-4.7970833333333336.844868333333333-4.74265616666666656.844868333333333-4.69741956.831261533333333-4.6820223333333336.7916346999999995-4.69741956.751769199999999-4.74265616666666656.7382817500000005-4.77297299999999956.7382817500000005-4.77297299999999956.666666666666667-4.7970833333333336.666666666666667-4.7970833333333336.844868333333333-4.7970833333333336.844868333333333-4.7729833333333336.8250550.00.00.01.00.00.0-4.6255666666666676.825055-4.6255666666666676.758095166666667-4.5952498333333336.758095166666667-4.5692298333333336.766808283333334-4.5600391666666676.791634783333333-4.5692298333333336.816341949999999-4.5952498333333336.825055083333333-4.6255666666666676.825055-4.6496833333333336.844868333333333-4.5952561666666676.844868333333333-4.55001956.831261533333333-4.5346223333333336.7916346999999995-4.55001956.751769199999999-4.5952561666666676.7382817500000005-4.6255736.7382817500000005-4.6255736.666666666666667-4.6496833333333336.666666666666667-4.6496833333333336.844868333333333-4.6496833333333336.844868333333333-4.6255666666666676.8250550.00.00.01.00.00.0-4.5022775000000016.844868033333333-4.3896036666666676.844868033333333-4.3896036666666676.824577183333334-4.4781671666666666.824577183333334-4.4781671666666666.771820983333333-4.3933036666666666.771820983333333-4.3933036666666666.75153015-4.4781671666666666.75153015-4.4781671666666666.686957516666666-4.3874551666666666.686957516666666-4.3874551666666666.666666666666667-4.50227756.6666666666666670.00.00.01.00.00.0-4.2633166666666666.750216666666668-4.24827749999999956.738997033333334-4.2334771666666666.715364199999999-4.2090166666666676.666666666666667-4.2349173333333336.666666666666667-4.2577146666666676.712380666666666-4.2749021666666666.736132833333333-4.2974608333333336.741981383333333-4.32371956.741981383333333-4.32371956.666666666666667-4.3478333333333336.666666666666667-4.3478333333333336.844868333333333-4.2934061666666676.844868333333333-4.24781156.832097033333334-4.2327723333333336.793544366666667-4.240656.765614533333333-4.2633286.750217349999999-4.2633166666666666.750216666666668-4.3237166666666676.825055-4.3237166666666676.761795333333334-4.2933998333333346.761795333333334-4.2671416.769792316666667-4.2581891666666676.793544483333333-4.2671416.817057983333332-4.2933998333333346.8250549666666664-4.3237166666666676.825055-4.3237166666666676.825055-4.2633166666666666.7502166666666680.00.00.01.00.00.0-3.30934233333333346.844868033333333-3.27341566666666676.844868033333333-3.22794033333333366.723600383333333-3.1822261666666676.844868033333333-3.14629950000000056.844868033333333-3.14629950000000056.666666666666667-3.1698130000000016.666666666666667-3.1698130000000016.823144883333333-3.2157658333333346.700922383333333-3.23999550000000056.700922383333333-3.2859481666666676.823144883333333-3.2859481666666676.666666666666667-3.30934233333333436.6666666666666670.00.00.01.00.00.0-3.1016666666666676.719423333333333-3.1016666666666676.8003480000000005-3.0797048333333346.8003480000000005-3.0797048333333346.720258833333332-3.07230466666666766.691732333333334-3.05010400000000066.68230305-3.0220548333333346.693642049999999-3.0116708333333346.724555716666667-3.0116708333333346.80034805-2.98970883333333376.80034805-2.98970883333333376.666666666666667-3.0116708333333346.666666666666667-3.0116708333333346.687196166666666-3.0302906666666676.6690536666666675-3.05475900000000026.663205183333334-3.0897308333333346.677528083333334-3.1016666666666686.719422749999999-3.1016666666666676.719423333333333-3.04639999999999986.80357-3.04639999999999986.80357-3.04639999999999986.80357-3.1016666666666676.7194233333333330.00.00.01.00.00.0-2.9444651666666676.852387583333333-2.92250333333333376.852387583333333-2.92250333333333376.666666666666667-2.9444651666666676.6666666666666670.00.00.01.00.00.0-2.85482756.838303350000001-2.85482756.800347533333333-2.8095908333333336.800347533333333-2.8095908333333336.78327935-2.85482756.78327935-2.85482756.710709733333332-2.8504111666666676.6897027499999995-2.83214956.685047783333334-2.8095908333333336.685047783333334-2.8095908333333336.666666666666667-2.83214956.666666666666667-2.8672406666666676.67609595-2.8769086666666676.710709733333332-2.8769086666666676.78327935-2.8930226.78327935-2.8930226.800347533333333-2.8769086666666676.800347533333333-2.8769086666666676.83830334999999940.00.00.01.00.00.0-2.78076.800348333333333-2.7587381666666676.800348333333333-2.7587381666666676.666666666666667-2.78076.666666666666667-2.78076.800348333333333-2.78076.852388333333333-2.7587381666666676.852388333333333-2.7587381666666676.824578000000001-2.78076.824578000000001-2.78076.852388333333333-2.78076.852388333333333-2.78076.8003483333333330.00.00.01.00.00.0-2.63508956.852387583333333-2.61312766666666676.852387583333333-2.61312766666666676.666666666666667-2.63508956.6666666666666670.00.00.01.00.00.0-2.5671666666666666.800348333333333-2.54520483333333356.800348333333333-2.54520483333333356.666666666666667-2.5671666666666666.666666666666667-2.5671666666666666.800348333333333-2.5671666666666666.852388333333333-2.54520483333333356.852388333333333-2.54520483333333356.824578000000001-2.5671666666666666.824578000000001-2.5671666666666666.852388333333333-2.5671666666666666.852388333333333-2.5671666666666666.8003483333333330.00.00.01.00.00.0-2.38813799999999966.7473526166666655-2.38813799999999966.666666666666667-2.41009983333333286.666666666666667-2.41009983333333286.746636466666667-2.41750016666666626.77504365-2.4397006666666666.7844729333333325-2.4677498333333336.773133933333335-2.47801449999999966.742220233333334-2.47801449999999966.666666666666667-2.5000958333333336.666666666666667-2.5000958333333336.800347533333333-2.47801449999999966.800347533333333-2.47801449999999966.77957925-2.45951399999999956.797602299999999-2.43480699999999976.803570199999999-2.39995449999999936.78924725-2.38813799999999966.7473526166666680.00.00.01.00.00.0-2.22998333333333286.738998333333332-2.22998333333333286.7282561166666675-2.3309601666666666.7282561166666675-2.31735333333333236.693642283333334-2.2832169999999996.681825849999999-2.25874849999999856.684929166666666-2.2351156666666656.694239083333334-2.2351156666666656.673470749999999-2.25934533333333136.665831850000001-2.28452983333333176.663206016666667-2.33525699999999866.681825849999999-2.35387683333333186.73219485-2.33621183333333136.78423485-2.2883493333333316.80357085-2.24573849999999766.786144516666667-2.2299833333333316.738998183333333-2.22998333333333286.738998333333332-2.25195000000000036.745443333333332-2.26209556.774208666666667-2.28811549999999956.784950883333333-2.31759683333333346.774566733333334-2.33024883333333356.745324066666668-2.25195000000000036.745443333333332-2.25195000000000036.745443333333332-2.22998333333333286.7389983333333320.00.00.01.00.00.0-3.28857416666666726.532747166666667-3.28857416666666726.4947913333333345-3.24333750000000046.4947913333333345-3.24333750000000046.477723166666667-3.28857416666666726.477723166666667-3.28857416666666726.4051535-3.2841578333333346.384146500000001-3.2658961666666676.3794915-3.24333750000000046.3794915-3.24333750000000046.3611103333333325-3.2658961666666676.3611103333333325-3.3009873333333346.370539666666668-3.31065533333333446.4051535-3.31065533333333446.477723166666667-3.3267686666666676.477723166666667-3.3267686666666676.4947913333333345-3.31065533333333446.4947913333333345-3.31065533333333446.5327471666666670.00.00.01.00.00.0-3.10009999999999946.4334333333333324-3.10009999999999946.4226911666666675-3.20107683333333266.4226911666666675-3.1874699999999996.3880773333333325-3.1533336666666666.376260833333333-3.1288651666666656.379364166666666-3.10523233333333166.388674166666665-3.10523233333333166.367905833333333-3.1294619999999986.360266833333332-3.15464649999999846.357640999999999-3.20537366666666526.376260833333333-3.22399349999999846.426629833333334-3.2063284999999986.478669999999999-3.15846599999999766.498006-3.11585516666666436.480579666666667-3.10009999999999766.4334333333333324-3.10009999999999946.4334333333333324-3.1220666666666676.439883333333333-3.13221216666666676.4686485000000005-3.1582321666666666.479390833333334-3.18771356.469006666666667-3.20036549999999986.439764-3.1220666666666676.439883333333333-3.1220666666666676.439883333333333-3.10009999999999946.43343333333333240.00.00.01.00.00.0-2.95723656.4947913333333345-3.00557649999999976.429741166666668-2.95472999999999966.3611103333333325-2.9806306666666666.3611103333333325-3.01954133333333236.413627833333334-3.05845199999999866.3611103333333325-3.08435266666666546.3611103333333325-3.03243199999999826.431054166666667-3.07993649999999836.4947913333333345-3.0540358333333326.4947913333333345-3.01858649999999876.447167500000001-2.98313716666666556.49479133333333450.00.00.01.00.00.0-2.90197383333333346.532747166666667-2.90197383333333346.4947913333333345-2.85673716666666656.4947913333333345-2.85673716666666656.477723166666667-2.90197383333333346.477723166666667-2.90197383333333346.4051535-2.89755766666666636.384146500000001-2.8792958333333336.3794915-2.85673716666666656.3794915-2.85673716666666656.3611103333333325-2.8792958333333336.3611103333333325-2.9143876.370539666666668-2.92405500000000056.4051535-2.92405500000000056.477723166666667-2.94016833333333336.477723166666667-2.94016833333333336.4947913333333345-2.92405500000000056.4947913333333345-2.92405500000000056.5327471666666670.00.00.01.00.00.0-3.30934233333333346.233755499999999-3.2069333333333336.233755499999999-3.2069333333333336.213464666666666-3.28523216666666646.213464666666666-3.28523216666666646.160947166666667-3.21457216666666626.160947166666667-3.21457216666666626.140656333333334-3.28523216666666646.140656333333334-3.28523216666666646.055554166666665-3.30934233333333346.0555541666666650.00.00.01.00.00.0-3.09646.2174-3.13817533333333386.197825333333332-3.15357250000000066.144472333333332-3.13817533333333386.091238666666667-3.09646.071664-3.05486356.091238666666667-3.0394663333333336.144472333333332-3.05486356.197825333333332-3.09646.2174-3.09646.2174-3.09646.236983333333334-3.03648233333333336.211798833333334-3.0140436.144481-3.03648233333333336.077163166666666-3.09646.052098000000001-3.15655656.077163166666666-3.17899566666666636.144481-3.15655656.211798833333334-3.09646.236983333333334-3.09646.236983333333334-3.09646.236983333333334-3.09646.21740.00.00.01.00.00.0-2.90400000000000046.2174-2.94577516666666656.197825333333332-2.96117233333333336.144472333333332-2.94577516666666656.091238666666667-2.90400000000000046.071664-2.8624633333333336.091238666666667-2.8470661666666666.144472333333332-2.8624633333333336.197825333333332-2.90400000000000046.2174-2.90400000000000046.2174-2.90400000000000046.236983333333334-2.84408216666666656.211798833333334-2.82164300000000036.144481-2.84408216666666656.077163166666666-2.90400000000000046.052098000000001-2.96415633333333346.077163166666666-2.98659566666666666.144481-2.96415633333333346.211798833333334-2.90400000000000046.236983333333334-2.90400000000000046.236983333333334-2.90400000000000046.236983333333334-2.90400000000000046.21740.00.00.01.00.00.00.145490883333332966.6920886666666660.145490883333332966.7399511666666670.10610278333333276.7399511666666670.10610278333333276.7597646666666660.16936246666666656.7597646666666660.16936246666666656.6832561666666660.138568133333332826.66821716666666650.102641399999999796.6632041666666660.037233266666666516.6875531666666650.0137197499999994466.7555871666666660.037233266666666516.82362116666666550.102641399999999796.84808949999999950.135703533333332886.8437926666666650.164707516666665786.8311406666666660.164707516666665786.8054786666666670.136300333333332446.8225468333333330.104670483333332726.8282761666666660.055495016666666676.8100143333333330.0391429833333328746.7555871666666670.055495016666666676.7012793333333340.104670483333332726.68301750.127467849999999336.6851660.00.00.01.00.00.00.28991396666666566.7798168333333320.281797616666665366.7829201666666680.27224898333333276.78399350.24360308333333296.7718190000000020.23369638333333196.7370858333333330.23369638333333196.6666646666666680.211615166666666726.6666646666666680.211615166666666726.80034550.23369638333333196.80034550.23369638333333196.7795771666666670.251719433333333136.7976003333333330.27869431666666556.8035681666666660.28370734999999936.8032098333333330.2897945999999996.80237483333333250.00.00.01.00.00.00.359379999999998766.7849499999999990.33145016666666536.7711045000000020.321185383333333136.7333873333333340.331330816666665366.6955510.359379983333334046.6818248333333340.3871903166666666.6956703333333340.397455100000000066.7333873333333340.3871903166666666.7709851666666660.359379983333334046.7849499999999990.359379999999998766.7849499999999990.359379999999998766.8035666666666660.404377999999998856.7849468333333340.420730033333332646.7333841666666670.404377999999998856.6818216666666670.359379999999998766.6632018333333330.31426266666666536.6818216666666670.298029983333333366.7333841666666670.31426266666666536.7849468333333340.359379999999998766.8035666666666660.359379999999998766.8035666666666660.359379999999998766.8035666666666660.359379999999998766.7849499999999990.00.00.01.00.00.00.454866666666665256.7194166666666660.454866666666665256.8003413333333340.476828499999999166.8003413333333340.476828499999999166.72025216666666750.48422869999999996.6917256666666660.50642920000000056.68229633333333250.53447836666666716.6936353333333330.54486249999999936.7245490.54486249999999936.8003413333333320.56682433333333326.8003413333333320.56682433333333326.6666605000000010.54486249999999936.6666605000000010.54486249999999936.687190.5262426666666676.6690476666666660.50177433333333296.6631991666666680.46680256.6775219999999990.454866716666667066.7194166666666660.454866666666665256.7194166666666660.510136.8035666666666660.510136.8035666666666660.510136.8035666666666660.454866666666665256.7194166666666660.00.00.01.00.00.00.63330666666666586.6867166666666660.63330666666666586.6158180.61122499999999986.6158180.61122499999999986.8003499999999990.63330666666666586.8003499999999990.63330666666666586.7800591666666660.65073283333333246.7977241666666660.67603666666666616.8035726666666660.71554416666666616.7842366666666680.7308219833333326.7333901666666670.71554416666666616.6825436666666670.67603666666666616.6632078333333330.65073283333333246.6689370.63330666666666586.6867213333333330.63330666666666586.6867166666666660.70802499999999976.7333833333333320.69799893333333416.77133916666666650.67066593333333356.7851846666666670.64321359999999956.77133916666666650.63330690000000056.7333833333333320.64321359999999956.6953081666666660.67066593333333356.6815820.69799893333333416.6953081666666660.70802499999999976.7333833333333320.70802499999999976.7333833333333320.70802499999999976.7333833333333320.63330666666666586.6867166666666660.00.00.01.00.00.00.88156666666666676.7390000000000010.88156666666666676.7282578333333330.78058983333333266.7282578333333330.79419666666666636.6936440000000010.82833299999999976.6818276666666670.85280133333333396.6849308333333340.87643416666666666.6942408333333340.87643416666666666.6734725000000010.85220449999999916.6658336666666670.82702000000000086.6632078333333350.77629300000000026.6818276666666670.75767316666666616.7321966666666680.77533799999999936.7842366666666680.82320066666666596.8035726666666680.86581133333333286.7861463333333330.88156666666666676.7390000000000010.88156666666666676.7390000000000010.85961666666666666.7454333333333340.8494711666666666.7741986666666660.82345116666666636.7849408333333340.79396983333333356.7745566666666660.78131783333333266.7453140.85961666666666666.7454333333333340.85961666666666666.7454333333333340.88156666666666676.7390000000000010.00.00.01.00.00.01.0055833333333346.780051.0055833333333346.8523808333333321.0275451666666666.8523808333333321.0275451666666666.6666591666666661.0055833333333346.6666591666666661.0055833333333346.6867113333333330.98803783333333216.6689270.96273383333333236.6631978333333330.92322633333333216.6825336666666660.90806799999999916.7333801666666660.92322633333333216.7842266666666660.96273383333333236.8035626666666660.98803783333333216.7977141666666661.0055833333333346.7800491666666671.0055833333333346.780050.93075000000000046.7333833333333320.94065666666666636.6953081666666660.96810900000000026.6815820.99556133333333236.6953081666666661.00558733333333346.7333833333333320.99556133333333236.77133916666666650.96810900000000026.7851846666666670.94065666666666636.77133916666666650.93075000000000046.7333833333333320.93075000000000046.7333833333333320.93075000000000046.7333833333333321.0055833333333346.780050.00.00.01.00.00.00.04475286666666616.3383021666666670.04475286666666616.3003463333333330.089989516666666236.3003463333333330.089989516666666236.28327816666666550.04475286666666616.28327816666666550.04475286666666616.21070850.049169116666665986.1897014999999990.067430883333332766.1850466666666670.089989516666666236.1850466666666670.089989516666666236.1666654999999990.067430883333332766.1666654999999990.032339650000000126.1760948333333340.0226716666666665876.21070850.0226716666666665876.28327816666666550.0065583499999992986.28327816666666550.0065583499999992986.30034633333333450.0226716666666665876.30034633333333450.0226716666666665876.3383021666666670.00.00.01.00.00.00.233218333333333786.2390000000000010.233218333333333786.2282578333333330.13224149999999976.2282578333333330.145848316666666736.1936440000000010.17998465000000016.1818276666666670.204452983333332376.1849308333333340.228085816666667086.1942408333333340.228085816666667086.1734725000000010.203856149999999546.1658336666666670.178671649999999246.1632078333333330.12794448333333346.1818276666666670.109324650000000186.2321966666666680.126989649999999686.2842366666666680.174852156.3035726666666660.21746298333333326.2861463333333330.233218233333332146.2390000000000010.233218333333333786.2390000000000010.211256666666666126.2454333333333340.2011112333333326.2741986666666660.17509123333333326.2849408333333340.145609899999999466.2745566666666660.13295794999999946.2453140.211256666666666126.2454333333333340.211256666666666126.2454333333333340.233218333333333786.2390000000000010.00.00.01.00.00.00.376090456.30034633333333450.32775056.2352963333333340.378596966666666876.16666550000000150.352696300000000466.16666550000000150.313785616666666546.2191830.27487493333333276.16666550000000150.248974266666666226.16666550000000150.300894966666665656.2366091666666670.25339051666666526.30034633333333450.279291183333333476.30034633333333450.31474048333333266.2527225000000010.350189783333333566.30034633333333450.00.00.01.00.00.00.431353149999999136.3383021666666670.431353149999999136.3003463333333330.47658979999999936.3003463333333330.47658979999999936.28327816666666550.431353149999999136.28327816666666550.431353149999999136.21070850.435769383333333376.1897014999999990.45403114999999926.1850466666666670.47658979999999936.1850466666666670.47658979999999936.1666654999999990.45403114999999926.1666654999999990.41893991666666666.1760948333333340.409271933333332066.21070850.409271933333332066.28327816666666550.39315861666666676.28327816666666550.39315861666666676.30034633333333450.409271933333332066.30034633333333450.409271933333332066.3383021666666670.00.00.50196078431372551.00.00.0-6.6666666666666675.0-5.05.0-5.03.3333333333333335-6.6666666666666673.33333333333333351.00.00.01.00.00.0-3.33333333333333355.00.05.00.03.3333333333333335-3.33333333333333353.33333333333333351.01.00.01.00.00.02.41572049999999955.04.2509461666666675.05.04.3508200000000015.03.98251333333333474.2509461666666673.33333333333333352.41572049999999953.33333333333333351.66666666666666673.98251333333333471.66666666666666674.3508200000000010.00.50196078431372550.01.00.00.02.41572049999999955.04.2509461666666675.05.04.3508200000000015.03.98251333333333474.2509461666666673.33333333333333352.41572049999999953.33333333333333351.66666666666666673.98251333333333471.66666666666666674.350820000000001 \ No newline at end of file diff --git a/share/extensions/tests/data/refs/tar_layers.out b/share/extensions/tests/data/refs/tar_layers.out new file mode 100644 index 0000000..50ce2ee Binary files /dev/null and b/share/extensions/tests/data/refs/tar_layers.out differ diff --git a/share/extensions/tests/data/refs/tar_layers__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/tar_layers__--id__p1__--id__r3.out new file mode 100644 index 0000000..50ce2ee Binary files /dev/null and b/share/extensions/tests/data/refs/tar_layers__--id__p1__--id__r3.out differ diff --git a/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__horizontal.out b/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__horizontal.out new file mode 100644 index 0000000..6a0bbf9 --- /dev/null +++ b/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__horizontal.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__vertical.out b/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__vertical.out new file mode 100644 index 0000000..ad7607e --- /dev/null +++ b/share/extensions/tests/data/refs/template__--size__100x50__--grid__true__--orientation__vertical.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/template__--size__5mmx15mm__--background__black__--noborder__true.out b/share/extensions/tests/data/refs/template__--size__5mmx15mm__--background__black__--noborder__true.out new file mode 100644 index 0000000..5b92e4d --- /dev/null +++ b/share/extensions/tests/data/refs/template__--size__5mmx15mm__--background__black__--noborder__true.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/template__--size__custom__--width__100__--height__100__--unit__in.out b/share/extensions/tests/data/refs/template__--size__custom__--width__100__--height__100__--unit__in.out new file mode 100644 index 0000000..fb3d8ad --- /dev/null +++ b/share/extensions/tests/data/refs/template__--size__custom__--width__100__--height__100__--unit__in.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/template_dvd_cover__-s__10__-b__10.out b/share/extensions/tests/data/refs/template_dvd_cover__-s__10__-b__10.out new file mode 100644 index 0000000..131054a --- /dev/null +++ b/share/extensions/tests/data/refs/template_dvd_cover__-s__10__-b__10.out @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/template_seamless_pattern__--width__100__--height__100.out b/share/extensions/tests/data/refs/template_seamless_pattern__--width__100__--height__100.out new file mode 100644 index 0000000..ccb26ab --- /dev/null +++ b/share/extensions/tests/data/refs/template_seamless_pattern__--width__100__--height__100.out @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Seamless pattern + Use the layers "Pattern Foreground" and "Pattern Background" on the pattern page to create your design. The separation into two layers will make it easier for you to create and edit overlapping content like a foreground drawing with a background fill. The layer named "Pattern" is for using the seamless pattern, copying it to other documents, adding opacity etc. Select the group on the page, and use Object->Pattern->Objects to Pattern to convert your creation into a fill pattern. The layer "Preview Background" provides an easy way to preview your creation if it contains transparency.Changing this layer's visibility will not alter the pattern. If an object is moved outside the pattern/page limits, it will be difficult to select it. To move it back onto the page, select the object using the rubberband selection (click and drag a selection box) with the selection tool.Then move it back onto the page, using the arrow keys or the "Align and Distribute" dialog (Shift+Ctrl+A). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Seamless Pattern + Seamless Pattern + Seamless Pattern + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/test_color_list.out b/share/extensions/tests/data/refs/test_color_list.out new file mode 100644 index 0000000..12d8497 --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list.out @@ -0,0 +1,10 @@ +7: red +7: #729fcf +7: #3465a4 +7: #000000 +6: #75507b +5: #cc0000 +4: #5c3566 +4: blue +3: #2e3436 +3: #123456 diff --git a/share/extensions/tests/data/refs/test_color_list__--id__color_svg.out b/share/extensions/tests/data/refs/test_color_list__--id__color_svg.out new file mode 100644 index 0000000..e4a6102 --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__color_svg.out @@ -0,0 +1,10 @@ +5: red +5: #729fcf +5: #3465a4 +4: #75507b +4: #000000 +3: #5c3566 +3: blue +3: #cc0000 +2: #2e3436 +2: #123456 diff --git a/share/extensions/tests/data/refs/test_color_list__--id__r1.out b/share/extensions/tests/data/refs/test_color_list__--id__r1.out new file mode 100644 index 0000000..7afd4b9 --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__r1.out @@ -0,0 +1,3 @@ +1: #5c3566 +1: #75507b +1: red diff --git a/share/extensions/tests/data/refs/test_color_list__--id__r1__--id__r2.out b/share/extensions/tests/data/refs/test_color_list__--id__r1__--id__r2.out new file mode 100644 index 0000000..67efc55 --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__r1__--id__r2.out @@ -0,0 +1,10 @@ +3: red +3: #729fcf +3: #3465a4 +2: #5c3566 +2: #75507b +2: blue +1: #2e3436 +1: #cc0000 +1: #000000 +1: #123456 diff --git a/share/extensions/tests/data/refs/test_color_list__--id__r2.out b/share/extensions/tests/data/refs/test_color_list__--id__r2.out new file mode 100644 index 0000000..0803b0f --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__r2.out @@ -0,0 +1,6 @@ +1: #5c3566 +1: #75507b +1: red +1: #729fcf +1: #3465a4 +1: blue diff --git a/share/extensions/tests/data/refs/test_color_list__--id__r3.out b/share/extensions/tests/data/refs/test_color_list__--id__r3.out new file mode 100644 index 0000000..168ffca --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__r3.out @@ -0,0 +1,8 @@ +2: red +1: #5c3566 +1: #75507b +1: #729fcf +1: #3465a4 +1: blue +1: #2e3436 +1: #cc0000 diff --git a/share/extensions/tests/data/refs/test_color_list__--id__r4.out b/share/extensions/tests/data/refs/test_color_list__--id__r4.out new file mode 100644 index 0000000..3745888 --- /dev/null +++ b/share/extensions/tests/data/refs/test_color_list__--id__r4.out @@ -0,0 +1,10 @@ +2: red +2: #729fcf +2: #3465a4 +1: #5c3566 +1: #75507b +1: blue +1: #2e3436 +1: #cc0000 +1: #000000 +1: #123456 diff --git a/share/extensions/tests/data/refs/text_braille.out b/share/extensions/tests/data/refs/text_braille.out new file mode 100644 index 0000000..52cfd76 --- /dev/null +++ b/share/extensions/tests/data/refs/text_braille.out @@ -0,0 +1,41 @@ + +⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀ +⠀⠀ +⠀⠀⠀⠀ +⠀⠀ +⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠋⠕⠗⠍⠁⠞⠱⠀⠏⠝⠛ +⠙⠏⠊⠱⠀⠔⠖ +⠇⠁⠽⠕⠥⠞⠤⠙⠊⠎⠏⠕⠎⠊⠞⠊⠕⠝⠱⠀⠃⠛⠤⠑⠇⠤⠝⠕⠗⠑⠏⠑⠁⠞ +⠇⠁⠽⠕⠥⠞⠤⠏⠕⠎⠊⠞⠊⠕⠝⠤⠁⠝⠉⠓⠕⠗⠱⠀⠞⠇ +⠀⠀⠀⠀ +⠀⠀ +⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀ +⠀⠀ +⠀⠀⠀⠀⠓⠑⠇⠇⠕⠀⠺⠕⠗⠇⠙ +⠀⠀⠀⠀⠋⠇⠕⠺⠀⠞⠑⠭⠞⠀⠺⠓⠊⠉⠓⠀⠺⠗⠁⠏⠎⠀⠀⠀⠀⠥⠏⠏⠑⠗ +⠀⠀⠀⠀⠍⠥⠇⠞⠊⠀⠇⠊⠝⠑⠞⠑⠭⠞⠋⠕⠕ +⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠛⠗⠕⠥⠏⠑⠙ +⠀⠀⠀⠀⠀⠀⠞⠑⠭⠞ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀⠀⠀ +⠀⠀ +⠀⠀ + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_extract__--direction__bt__--xanchor__center_x__--yanchor__center_y.out b/share/extensions/tests/data/refs/text_extract__--direction__bt__--xanchor__center_x__--yanchor__center_y.out new file mode 100644 index 0000000..6c3dac7 --- /dev/null +++ b/share/extensions/tests/data/refs/text_extract__--direction__bt__--xanchor__center_x__--yanchor__center_y.out @@ -0,0 +1,8 @@ +text +Grouped +Multi line +text +FOO +flow text which wraps +UPPER +Hello World diff --git a/share/extensions/tests/data/refs/text_extract__--direction__lr__--xanchor__center_x__--yanchor__center_y.out b/share/extensions/tests/data/refs/text_extract__--direction__lr__--xanchor__center_x__--yanchor__center_y.out new file mode 100644 index 0000000..2eec938 --- /dev/null +++ b/share/extensions/tests/data/refs/text_extract__--direction__lr__--xanchor__center_x__--yanchor__center_y.out @@ -0,0 +1,8 @@ +Grouped +text +Hello World +UPPER +Multi line +text +FOO +flow text which wraps diff --git a/share/extensions/tests/data/refs/text_extract__--direction__rl__--xanchor__center_x__--yanchor__center_y.out b/share/extensions/tests/data/refs/text_extract__--direction__rl__--xanchor__center_x__--yanchor__center_y.out new file mode 100644 index 0000000..bc3ed2e --- /dev/null +++ b/share/extensions/tests/data/refs/text_extract__--direction__rl__--xanchor__center_x__--yanchor__center_y.out @@ -0,0 +1,8 @@ +flow text which wraps +Multi line +text +FOO +UPPER +Hello World +text +Grouped diff --git a/share/extensions/tests/data/refs/text_extract__--direction__tb__--xanchor__center_x__--yanchor__center_y.out b/share/extensions/tests/data/refs/text_extract__--direction__tb__--xanchor__center_x__--yanchor__center_y.out new file mode 100644 index 0000000..3634b71 --- /dev/null +++ b/share/extensions/tests/data/refs/text_extract__--direction__tb__--xanchor__center_x__--yanchor__center_y.out @@ -0,0 +1,8 @@ +Hello World +UPPER +flow text which wraps +Multi line +text +FOO +Grouped +text diff --git a/share/extensions/tests/data/refs/text_flipcase.out b/share/extensions/tests/data/refs/text_flipcase.out new file mode 100644 index 0000000..cd9ebc3 --- /dev/null +++ b/share/extensions/tests/data/refs/text_flipcase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + FORMAT: PNG +DPI: 96 +LAYOUT-DISPOSITION: BG-EL-NOREPEAT +LAYOUT-POSITION-ANCHOR: TL + + + + + + + + + + + + + hELLO wORLD + FLOW TEXT WHICH WRAPS upper + mULTI LINETEXTfoo + + gROUPED + TEXT + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_lowercase.out b/share/extensions/tests/data/refs/text_lowercase.out new file mode 100644 index 0000000..b492bd3 --- /dev/null +++ b/share/extensions/tests/data/refs/text_lowercase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + hello world + flow text which wraps upper + multi linetextfoo + + grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_merge.out b/share/extensions/tests/data/refs/text_merge.out new file mode 100644 index 0000000..0d42bf7 --- /dev/null +++ b/share/extensions/tests/data/refs/text_merge.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + GroupedtextHello WorldUPPERMulti linetextFOOflow text which wraps + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_randomcase.out b/share/extensions/tests/data/refs/text_randomcase.out new file mode 100644 index 0000000..7291480 --- /dev/null +++ b/share/extensions/tests/data/refs/text_randomcase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + fOrmAT: pNg +DpI: 96 +lAyOUT-DiSpOSiTioN: BG-eL-nOrEPeAt +LayouT-pOsitIOn-ANcHoR: tl + + + + + + + + + + + + + HEllO wOrLD + fLoW TexT WhIch wraPs upPEr + mUlTi lInEtEXtFoo + + GrouPeD + teXt + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_sentencecase.out b/share/extensions/tests/data/refs/text_sentencecase.out new file mode 100644 index 0000000..9968709 --- /dev/null +++ b/share/extensions/tests/data/refs/text_sentencecase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + Format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello world + Flow text which wraps Upper + Multi linetextfoo + + Grouped + Text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__5478757cb04224bacfa3c641fea954ba.out b/share/extensions/tests/data/refs/text_split__5478757cb04224bacfa3c641fea954ba.out new file mode 100644 index 0000000..13a8cdc --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__5478757cb04224bacfa3c641fea954ba.out @@ -0,0 +1,28 @@ + + + + + + + This is a regular textWith a line break.This is regular textwith a line breakand some transforms.This is an SVG2 flowed text. (inline size) +This is a line break inside that text.This is a text with kerns adjusted in tspans(as Inkscape does it)This is an SVG1.2 flowed text (flowroot)And this is a linebreak inside.inside.linebreakaisthisAnd(flowroot)textflowedSVG1.2anisThis + This is an SVG1.2 flowed textWith absolute line-heightline-heightabsoluteWithtextflowedSVG1.2anisThis + This is an SVG1.2 flowed textwithout line height.height.linewithouttextflowedSVG1.2anisThis + 0.50.10.10.10.34.20.54.30.14.5This is a text with direction:rtl This is an SVG2 flowed text (shape inside)This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + break.lineaWithtextregularaisThis + + transforms.someandbreaklineawithtextregularisThis + + text.thatinsidebreaklineaisThise) +size(inlintext.flowedSVG2anisThis + + it)doesInkscape(astspansinadjustedkernswithtextaisThis + + 4.50.14.30.54.20.30.10.10.10.5 + + direction:rtlwithtextaisThis + + inside)(shapetextflowedSVG2anisThis + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__74947d6e9e9ee89a80bbec0bfacc6dfb.out b/share/extensions/tests/data/refs/text_split__74947d6e9e9ee89a80bbec0bfacc6dfb.out new file mode 100644 index 0000000..325c2e5 --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__74947d6e9e9ee89a80bbec0bfacc6dfb.out @@ -0,0 +1,28 @@ + + + + + + + This is a regular textWith a line break.This is regular textwith a line breakand some transforms.This is an SVG2 flowed text. (inline size) +This is a line break inside that text.This is a text with kerns adjusted in tspans(as Inkscape does it)This is an SVG1.2 flowed text (flowroot)And this is a linebreak inside..edisni kaerbenil a si siht dnA)toorwolf( txet dewolf 2.1GVS na si sihT + This is an SVG1.2 flowed textWith absolute line-heightthgieh-enil etulosba htiWtxet dewolf 2.1GVS na si sihT + This is an SVG1.2 flowed textwithout line height..thgieh enil tuohtiwtxet dewolf 2.1GVS na si sihT + 0.50.10.10.10.34.20.54.30.14.5This is a text with direction:rtl This is an SVG2 flowed text (shape inside)This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + .kaerb enil a htiWtxet raluger a si sihT + + .smrofsnart emos dnakaerb enil a htiwtxet raluger si sihT + + .txet taht edisni kaerb enil a si sihT +)ezis enilni( .txet dewolf 2GVS na si sihT + + )ti seod epacsknI sa(snapst ni detsujda snrek htiw txet a si sihT + + 5.41.03.45.02.43.01.01.01.05.0 + + ltr:noitcerid htiw txet a si sihT + + )edisni epahs( txet dewolf 2GVS na si sihT + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__897ab8b3c516acacaf68391a51eb8836.out b/share/extensions/tests/data/refs/text_split__897ab8b3c516acacaf68391a51eb8836.out new file mode 100644 index 0000000..cca50e7 --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__897ab8b3c516acacaf68391a51eb8836.out @@ -0,0 +1,27 @@ + + + + + + + inside.linebreakaisthisAnd(flowroot)textflowedSVG1.2anisThis + line-heightabsoluteWithtextflowedSVG1.2anisThis + height.linewithouttextflowedSVG1.2anisThis + This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + break.lineaWithtextregularaisThis + + transforms.someandbreaklineawithtextregularisThis + + text.thatinsidebreaklineaisThise) +size(inlintext.flowedSVG2anisThis + + it)doesInkscape(astspansinadjustedkernswithtextaisThis + + .541.03.45.02.43.01.01.01.05.0 + + direction:rtlwithtextaisThis + + inside)(shapetextflowedSVG2anisThis + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__ad318803d098b3903561d44825a36ea0.out b/share/extensions/tests/data/refs/text_split__ad318803d098b3903561d44825a36ea0.out new file mode 100644 index 0000000..ccd31f3 --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__ad318803d098b3903561d44825a36ea0.out @@ -0,0 +1,45 @@ + + + + + + + This is a regular textWith a line break.This is regular textwith a line breakand some transforms.This is an SVG2 flowed text. (inline size) +This is a line break inside that text.This is a text with kerns adjusted in tspans(as Inkscape does it)This is an SVG1.2 flowed text (flowroot)And this is a linebreak inside.And this is a linebreak inside.This is an SVG1.2 flowed text (flowroot) + + This is an SVG1.2 flowed textWith absolute line-heightWith absolute line-heightThis is an SVG1.2 flowed text + + This is an SVG1.2 flowed textwithout line height.without line height.This is an SVG1.2 flowed text + + 0.50.10.10.10.34.20.54.30.14.5This is a text with direction:rtl This is an SVG2 flowed text (shape inside)This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + With a line break.This is a regular text + + + + and some transforms.with a line breakThis is regular text + + + + text.break inside that This is a line (inline size) +flowed text. This is an SVG2 + + + + (as Inkscape does it)This is a text with kerns adjusted in tspans + + + + 0.50.10.10.10.34.20.54.30.14.5 + + + + This is a text with direction:rtl + + + + inside)flowed text (shape This is an SVG2 + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__c242adcac78228419d3c065a99727bfb.out b/share/extensions/tests/data/refs/text_split__c242adcac78228419d3c065a99727bfb.out new file mode 100644 index 0000000..f356a08 --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__c242adcac78228419d3c065a99727bfb.out @@ -0,0 +1,44 @@ + + + + + + + And this is a linebreak inside.This is an SVG1.2 flowed text (flowroot) + + With absolute line-heightThis is an SVG1.2 flowed text + + without line height.This is an SVG1.2 flowed text + + This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + With a line break.This is a regular text + + + + and some transforms.with a line breakThis is regular text + + + + text.break inside that This is a line (inline size) +flowed text. This is an SVG2 + + + + (as Inkscape does it)This is a text with kerns adjusted in tspans + + + + 0.50.10.10.10.34.20.54.30.14.5 + + + + This is a text with direction:rtl + + + + inside)flowed text (shape This is an SVG2 + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__d8b155ac58a7424471f416b64f21669f.out b/share/extensions/tests/data/refs/text_split__d8b155ac58a7424471f416b64f21669f.out new file mode 100644 index 0000000..6611d26 --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__d8b155ac58a7424471f416b64f21669f.out @@ -0,0 +1,27 @@ + + + + + + + inside.linebreakaisthisAnd(flowroot)textflowedSVG1.2anisThis + line-heightabsoluteWithtextflowedSVG1.2anisThis + height.linewithouttextflowedSVG1.2anisThis + This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + break.lineaWithtextregularaisThis + + transforms.someandbreaklineawithtextregularisThis + + text.thatinsidebreaklineaisThise) +size(inlintext.flowedSVG2anisThis + + it)doesInkscape(astspansinadjustedkernswithtextaisThis + + 4.50.14.30.54.20.30.10.10.10.5 + + direction:rtlwithtextaisThis + + inside)(shapetextflowedSVG2anisThis + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_split__dd77d3cc0134ad62833e05ca73e38896.out b/share/extensions/tests/data/refs/text_split__dd77d3cc0134ad62833e05ca73e38896.out new file mode 100644 index 0000000..f71324f --- /dev/null +++ b/share/extensions/tests/data/refs/text_split__dd77d3cc0134ad62833e05ca73e38896.out @@ -0,0 +1,27 @@ + + + + + + + .edisni kaerbenil a si siht dnA)toorwolf( txet dewolf 2.1GVS na si sihT + thgieh-enil etulosba htiWtxet dewolf 2.1GVS na si sihT + .thgieh enil tuohtiwtxet dewolf 2.1GVS na si sihT + This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + .kaerb enil a htiWtxet raluger a si sihT + + .smrofsnart emos dnakaerb enil a htiwtxet raluger si sihT + + .txet taht edisni kaerb enil a si sihT +)ezis enilni( .txet dewolf 2GVS na si sihT + + )ti seod epacsknI sa(snapst ni detsujda snrek htiw txet a si sihT + + 5.41.03.45.02.43.01.01.01.05.0 + + ltr:noitcerid htiw txet a si sihT + + )edisni epahs( txet dewolf 2GVS na si sihT + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_titlecase.out b/share/extensions/tests/data/refs/text_titlecase.out new file mode 100644 index 0000000..1e0b50f --- /dev/null +++ b/share/extensions/tests/data/refs/text_titlecase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + Format: Png +Dpi: 96 +Layout-disposition: Bg-el-norepeat +Layout-position-anchor: Tl + + + + + + + + + + + + + Hello World + Flow Text Which Wraps Upper + Multi LineTextFoo + + Grouped + Text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/text_uppercase.out b/share/extensions/tests/data/refs/text_uppercase.out new file mode 100644 index 0000000..9532266 --- /dev/null +++ b/share/extensions/tests/data/refs/text_uppercase.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + FORMAT: PNG +DPI: 96 +LAYOUT-DISPOSITION: BG-EL-NOREPEAT +LAYOUT-POSITION-ANCHOR: TL + + + + + + + + + + + + + HELLO WORLD + FLOW TEXT WHICH WRAPS UPPER + MULTI LINETEXTFOO + + GROUPED + TEXT + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/triangle.out b/share/extensions/tests/data/refs/triangle.out new file mode 100644 index 0000000..82ff731 --- /dev/null +++ b/share/extensions/tests/data/refs/triangle.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/triangle__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/triangle__--id__p1__--id__r3.out new file mode 100644 index 0000000..82ff731 --- /dev/null +++ b/share/extensions/tests/data/refs/triangle__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/ungroup_deep.out b/share/extensions/tests/data/refs/ungroup_deep.out new file mode 100644 index 0000000..738cc6b --- /dev/null +++ b/share/extensions/tests/data/refs/ungroup_deep.out @@ -0,0 +1,33 @@ + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + Grouped + text + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/ungroup_deep__--id__g13.out b/share/extensions/tests/data/refs/ungroup_deep__--id__g13.out new file mode 100644 index 0000000..87c089e --- /dev/null +++ b/share/extensions/tests/data/refs/ungroup_deep__--id__g13.out @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/ungroup_deep__--id__g1935__--id__g6577__--id__g115.out b/share/extensions/tests/data/refs/ungroup_deep__--id__g1935__--id__g6577__--id__g115.out new file mode 100644 index 0000000..ab21922 --- /dev/null +++ b/share/extensions/tests/data/refs/ungroup_deep__--id__g1935__--id__g6577__--id__g115.out @@ -0,0 +1,19 @@ + + + + + + + + + + + + Path with clip-path:none + Path with nested transforms + Transformed group withtransformed clip-path + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/ungroup_deep__--id__layer2.out b/share/extensions/tests/data/refs/ungroup_deep__--id__layer2.out new file mode 100644 index 0000000..41aa594 --- /dev/null +++ b/share/extensions/tests/data/refs/ungroup_deep__--id__layer2.out @@ -0,0 +1,39 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/voronoi2svg__--id__c1__--id__c2__--id__c3__--id__p1__--id__p2__--id__s1__--diagram-type__Voronoi__--clip-box__Page.out b/share/extensions/tests/data/refs/voronoi2svg__--id__c1__--id__c2__--id__c3__--id__p1__--id__p2__--id__s1__--diagram-type__Voronoi__--clip-box__Page.out new file mode 100644 index 0000000..04873fa --- /dev/null +++ b/share/extensions/tests/data/refs/voronoi2svg__--id__c1__--id__c2__--id__c3__--id__p1__--id__p2__--id__s1__--diagram-type__Voronoi__--clip-box__Page.out @@ -0,0 +1,79 @@ + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + + + + + + + + + + + + Hello World + + + + + + flow text which wraps + + + UPPER + + + Multi line + text + FOO + + + + Grouped + + + text + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/voronoi2svg__--id__r1__--id__r3__--id__c1__--id__c3__--id__s1__--diagram-type__Both__--delaunay-fill-options__delaunay-fill.out b/share/extensions/tests/data/refs/voronoi2svg__--id__r1__--id__r3__--id__c1__--id__c3__--id__s1__--diagram-type__Both__--delaunay-fill-options__delaunay-fill.out new file mode 100644 index 0000000..ee018dd --- /dev/null +++ b/share/extensions/tests/data/refs/voronoi2svg__--id__r1__--id__r3__--id__c1__--id__c3__--id__s1__--diagram-type__Both__--delaunay-fill-options__delaunay-fill.out @@ -0,0 +1,81 @@ + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + Hello World + + + + + + flow text which wraps + + + UPPER + + + Multi line + text + FOO + + + + Grouped + + + text + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/voronoi2svg__083b27d59093207e6210e1001eb9d5df.out b/share/extensions/tests/data/refs/voronoi2svg__083b27d59093207e6210e1001eb9d5df.out new file mode 100644 index 0000000..db6ced9 --- /dev/null +++ b/share/extensions/tests/data/refs/voronoi2svg__083b27d59093207e6210e1001eb9d5df.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/voronoi2svg__6d561032e7d7e60e607c75e562f677a4.out b/share/extensions/tests/data/refs/voronoi2svg__6d561032e7d7e60e607c75e562f677a4.out new file mode 100644 index 0000000..3843f9f --- /dev/null +++ b/share/extensions/tests/data/refs/voronoi2svg__6d561032e7d7e60e607c75e562f677a4.out @@ -0,0 +1,91 @@ + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hello World + + + + + + flow text which wraps + + + UPPER + + + Multi line + text + FOO + + + + Grouped + + + text + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/web_interactive_mockup__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/web_interactive_mockup__--id__p1__--id__r3.out new file mode 100644 index 0000000..76f7164 --- /dev/null +++ b/share/extensions/tests/data/refs/web_interactive_mockup__--id__p1__--id__r3.out @@ -0,0 +1,266 @@ + + +/* inkweb.js - InkWebEffect:AutoUpdate */ +/* +** InkWeb - Inkscape's Javscript features for the open vector web +** +** Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +** +** ********* Bugs and New Fetures ************************************* +** If you found any bug on this script or if you want to propose a +** new feature, please report it in the inkscape bug tracker +** https://inkscape.org/report . +** ******************************************************************** +** +** This program 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 3 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 Lesser 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, see <http://www.gnu.org/licenses/>. +*/ + +var InkWeb = { + + version: 0.04, + + NS: { + svg: "http://www.w3.org/2000/svg", + sodipodi: "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + inkscape: "http://www.inkscape.org/namespaces/inkscape", + cc: "http://creativecommons.org/ns#", + dc: "http://purl.org/dc/elements/1.1/", + rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace" + } + +}; + +InkWeb.el = function (tag, attributes) { + // A helper to create SVG elements + var element = document.createElementNS( this.NS.svg, tag ); + for ( var att in attributes ) { + switch ( att ) { + case "parent": + attributes.parent.appendChild( element ); + break; + case "text": + element.appendChild( document.createTextNode( attributes.text ) ); + break; + default: + element.setAttribute( att, attributes[att] ); + } + } + return element; +} + +InkWeb.reGetStyleAttVal = function (att) { + return new RegExp( "(^|.*;)[ ]*"+ att +":([^;]*)(;.*|$)" ) +} + +InkWeb.getStyle = function (el, att) { + // This method is needed because el.style is only working + // to HTML style in the Firefox 3.0 + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + var match = this.reGetStyleAttVal(att).exec(style); + if ( match ) { + return match[2]; + } else { + return false; + } +} + +InkWeb.setStyle = function (el, att, val) { + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + re = this.reGetStyleAttVal(att); + if ( re.test(style) ) { + style = style.replace( re, "$1"+ att +":"+ val +"$3" ); + } else { + style += ";"+ att +":"+ val; + } + el.setAttribute( "style", style ); + return val +} + +InkWeb.transmitAtt = function (conf) { + conf.att = conf.att.split( /\s+/ ); + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to.join ) + conf.to = [ conf.to ]; + for ( var toEl,elN=0; toEl=conf.to[elN]; elN++ ) { + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + for ( var i=0; i<conf.att.length; i++ ) { + var val = this.getStyle( conf.from, conf.att[i] ); + if ( val ) { + this.setStyle( toEl, conf.att[i], val ); + } else { + val = conf.from.getAttribute(conf.att[i]); + toEl.setAttribute( conf.att[i], val ); + } + } + } +} + +InkWeb.goto = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.to ; + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + toEl = document.getElementById( conf.to ); + document.getElementsByTagName("svg")[0].viewBox.baseVal.x = toEl.getAttribute("x"); + document.getElementsByTagName("svg")[0].viewBox.baseVal.y = toEl.getAttribute("y"); +} + +InkWeb.setAtt = function (conf) { + if ( ! conf.el.join ) + conf.to = [ conf.el ]; + conf.att = conf.att.split( /\s+/ ); + conf.val = conf.val.split( /\s+/ ); + for ( var el,elN=0; el=conf.el[elN]; elN++ ) { + if ( typeof(el) == "string" ) + el = document.getElementById( el ); + for ( var att,i=0; att=conf.att[i]; i++ ) { + if ( + att == "width" || + att == "height" || + att == "x" || + att == "y" || + att == "cx" || + att == "cy" || + att == "r" || + att == "rx" || + att == "ry" || + att == "transform" + ) { + el.setAttribute( att, conf.val[i] ); + } else { + this.setStyle( el, att, conf.val[i] ); + } + } + } +} + +InkWeb.moveElTo = function (startConf) { + if ( typeof(startConf) == "string" ) { + // startConf may be only a element Id, to timeout recursive calls. + var el = document.getElementById( startConf ); + } else { + if ( typeof(startConf.el) == "string" ) + startConf.el = document.getElementById( startConf.el ); + var el = startConf.el; + } + if ( ! el.inkWebMoving ) { + el.inkWebMoving = { + step: 0 + }; + } + var conf = el.inkWebMoving; + if ( conf.step == 0 ) { + conf.x = startConf.x; + conf.y = startConf.y; + // dur : duration of the animation in seconds + if ( startConf.dur ) { conf.dur = startConf.dur } + else { conf.dur = 1 } + // steps : animation steps in a second + if ( startConf.stepsBySec ) { conf.stepsBySec = startConf.stepsBySec } + else { conf.stepsBySec = 16 } + conf.sleep = Math.round( 1000 / conf.stepsBySec ); + conf.steps = conf.dur * conf.stepsBySec; + var startPos = el.getBBox(); + conf.xInc = ( conf.x - startPos.x ) / conf.steps; + conf.yInc = ( conf.y - startPos.y ) / conf.steps; + conf.transform = el.transform.baseVal.consolidate(); + if ( ! conf.transform ) { + conf.transform = el.ownerSVGElement.createSVGTransform(); + } + el.transform.baseVal.clear(); + el.transform.baseVal.appendItem(conf.transform); + } + if ( conf.step < conf.steps ) { + conf.step++; + conf.transform.matrix.e += conf.xInc; + conf.transform.matrix.f += conf.yInc; + try{ el.ownerSVGElement.forceRedraw() } + catch(e){ this.log(e, "this "+el.ownerSVGElement+" has no forceRedraw().") } + conf.timeout = setTimeout( 'InkWeb.moveElTo("'+el.id+'")', conf.sleep ); + } else { + delete el.inkWebMoving; + } +} + +InkWeb.moveViewbox = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.from ; + if ( typeof(conf.to) == "string" ) + conf.to = document.getElementById( conf.to ); + bbox = conf.to.getBBox(); + vbox = document.getElementsByTagName("svg")[0].viewBox; + document.getElementsByTagName("svg")[0].viewBox.baseVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.baseVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.baseVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.baseVal.height=bbox.height; + document.getElementsByTagName("svg")[0].viewBox.animVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.animVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.animVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.animVal.heigt=bbox.height; + vbox = document.getElementsByTagName("svg")[0].viewBox; +} + +InkWeb.log = function () { /* requires inkweb-debug.js, not included in Inkscape */ } + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/web_set_att__--id__p1__--id__r3__--att__fill__--val__red.out b/share/extensions/tests/data/refs/web_set_att__--id__p1__--id__r3__--att__fill__--val__red.out new file mode 100644 index 0000000..50d8f22 --- /dev/null +++ b/share/extensions/tests/data/refs/web_set_att__--id__p1__--id__r3__--att__fill__--val__red.out @@ -0,0 +1,266 @@ + + +/* inkweb.js - InkWebEffect:AutoUpdate */ +/* +** InkWeb - Inkscape's Javscript features for the open vector web +** +** Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +** +** ********* Bugs and New Fetures ************************************* +** If you found any bug on this script or if you want to propose a +** new feature, please report it in the inkscape bug tracker +** https://inkscape.org/report . +** ******************************************************************** +** +** This program 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 3 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 Lesser 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, see <http://www.gnu.org/licenses/>. +*/ + +var InkWeb = { + + version: 0.04, + + NS: { + svg: "http://www.w3.org/2000/svg", + sodipodi: "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + inkscape: "http://www.inkscape.org/namespaces/inkscape", + cc: "http://creativecommons.org/ns#", + dc: "http://purl.org/dc/elements/1.1/", + rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace" + } + +}; + +InkWeb.el = function (tag, attributes) { + // A helper to create SVG elements + var element = document.createElementNS( this.NS.svg, tag ); + for ( var att in attributes ) { + switch ( att ) { + case "parent": + attributes.parent.appendChild( element ); + break; + case "text": + element.appendChild( document.createTextNode( attributes.text ) ); + break; + default: + element.setAttribute( att, attributes[att] ); + } + } + return element; +} + +InkWeb.reGetStyleAttVal = function (att) { + return new RegExp( "(^|.*;)[ ]*"+ att +":([^;]*)(;.*|$)" ) +} + +InkWeb.getStyle = function (el, att) { + // This method is needed because el.style is only working + // to HTML style in the Firefox 3.0 + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + var match = this.reGetStyleAttVal(att).exec(style); + if ( match ) { + return match[2]; + } else { + return false; + } +} + +InkWeb.setStyle = function (el, att, val) { + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + re = this.reGetStyleAttVal(att); + if ( re.test(style) ) { + style = style.replace( re, "$1"+ att +":"+ val +"$3" ); + } else { + style += ";"+ att +":"+ val; + } + el.setAttribute( "style", style ); + return val +} + +InkWeb.transmitAtt = function (conf) { + conf.att = conf.att.split( /\s+/ ); + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to.join ) + conf.to = [ conf.to ]; + for ( var toEl,elN=0; toEl=conf.to[elN]; elN++ ) { + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + for ( var i=0; i<conf.att.length; i++ ) { + var val = this.getStyle( conf.from, conf.att[i] ); + if ( val ) { + this.setStyle( toEl, conf.att[i], val ); + } else { + val = conf.from.getAttribute(conf.att[i]); + toEl.setAttribute( conf.att[i], val ); + } + } + } +} + +InkWeb.goto = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.to ; + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + toEl = document.getElementById( conf.to ); + document.getElementsByTagName("svg")[0].viewBox.baseVal.x = toEl.getAttribute("x"); + document.getElementsByTagName("svg")[0].viewBox.baseVal.y = toEl.getAttribute("y"); +} + +InkWeb.setAtt = function (conf) { + if ( ! conf.el.join ) + conf.to = [ conf.el ]; + conf.att = conf.att.split( /\s+/ ); + conf.val = conf.val.split( /\s+/ ); + for ( var el,elN=0; el=conf.el[elN]; elN++ ) { + if ( typeof(el) == "string" ) + el = document.getElementById( el ); + for ( var att,i=0; att=conf.att[i]; i++ ) { + if ( + att == "width" || + att == "height" || + att == "x" || + att == "y" || + att == "cx" || + att == "cy" || + att == "r" || + att == "rx" || + att == "ry" || + att == "transform" + ) { + el.setAttribute( att, conf.val[i] ); + } else { + this.setStyle( el, att, conf.val[i] ); + } + } + } +} + +InkWeb.moveElTo = function (startConf) { + if ( typeof(startConf) == "string" ) { + // startConf may be only a element Id, to timeout recursive calls. + var el = document.getElementById( startConf ); + } else { + if ( typeof(startConf.el) == "string" ) + startConf.el = document.getElementById( startConf.el ); + var el = startConf.el; + } + if ( ! el.inkWebMoving ) { + el.inkWebMoving = { + step: 0 + }; + } + var conf = el.inkWebMoving; + if ( conf.step == 0 ) { + conf.x = startConf.x; + conf.y = startConf.y; + // dur : duration of the animation in seconds + if ( startConf.dur ) { conf.dur = startConf.dur } + else { conf.dur = 1 } + // steps : animation steps in a second + if ( startConf.stepsBySec ) { conf.stepsBySec = startConf.stepsBySec } + else { conf.stepsBySec = 16 } + conf.sleep = Math.round( 1000 / conf.stepsBySec ); + conf.steps = conf.dur * conf.stepsBySec; + var startPos = el.getBBox(); + conf.xInc = ( conf.x - startPos.x ) / conf.steps; + conf.yInc = ( conf.y - startPos.y ) / conf.steps; + conf.transform = el.transform.baseVal.consolidate(); + if ( ! conf.transform ) { + conf.transform = el.ownerSVGElement.createSVGTransform(); + } + el.transform.baseVal.clear(); + el.transform.baseVal.appendItem(conf.transform); + } + if ( conf.step < conf.steps ) { + conf.step++; + conf.transform.matrix.e += conf.xInc; + conf.transform.matrix.f += conf.yInc; + try{ el.ownerSVGElement.forceRedraw() } + catch(e){ this.log(e, "this "+el.ownerSVGElement+" has no forceRedraw().") } + conf.timeout = setTimeout( 'InkWeb.moveElTo("'+el.id+'")', conf.sleep ); + } else { + delete el.inkWebMoving; + } +} + +InkWeb.moveViewbox = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.from ; + if ( typeof(conf.to) == "string" ) + conf.to = document.getElementById( conf.to ); + bbox = conf.to.getBBox(); + vbox = document.getElementsByTagName("svg")[0].viewBox; + document.getElementsByTagName("svg")[0].viewBox.baseVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.baseVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.baseVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.baseVal.height=bbox.height; + document.getElementsByTagName("svg")[0].viewBox.animVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.animVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.animVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.animVal.heigt=bbox.height; + vbox = document.getElementsByTagName("svg")[0].viewBox; +} + +InkWeb.log = function () { /* requires inkweb-debug.js, not included in Inkscape */ } + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/web_transmit_att__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/web_transmit_att__--id__p1__--id__r3.out new file mode 100644 index 0000000..cd479bf --- /dev/null +++ b/share/extensions/tests/data/refs/web_transmit_att__--id__p1__--id__r3.out @@ -0,0 +1,266 @@ + + +/* inkweb.js - InkWebEffect:AutoUpdate */ +/* +** InkWeb - Inkscape's Javscript features for the open vector web +** +** Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +** +** ********* Bugs and New Fetures ************************************* +** If you found any bug on this script or if you want to propose a +** new feature, please report it in the inkscape bug tracker +** https://inkscape.org/report . +** ******************************************************************** +** +** This program 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 3 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 Lesser 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, see <http://www.gnu.org/licenses/>. +*/ + +var InkWeb = { + + version: 0.04, + + NS: { + svg: "http://www.w3.org/2000/svg", + sodipodi: "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd", + inkscape: "http://www.inkscape.org/namespaces/inkscape", + cc: "http://creativecommons.org/ns#", + dc: "http://purl.org/dc/elements/1.1/", + rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace" + } + +}; + +InkWeb.el = function (tag, attributes) { + // A helper to create SVG elements + var element = document.createElementNS( this.NS.svg, tag ); + for ( var att in attributes ) { + switch ( att ) { + case "parent": + attributes.parent.appendChild( element ); + break; + case "text": + element.appendChild( document.createTextNode( attributes.text ) ); + break; + default: + element.setAttribute( att, attributes[att] ); + } + } + return element; +} + +InkWeb.reGetStyleAttVal = function (att) { + return new RegExp( "(^|.*;)[ ]*"+ att +":([^;]*)(;.*|$)" ) +} + +InkWeb.getStyle = function (el, att) { + // This method is needed because el.style is only working + // to HTML style in the Firefox 3.0 + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + var match = this.reGetStyleAttVal(att).exec(style); + if ( match ) { + return match[2]; + } else { + return false; + } +} + +InkWeb.setStyle = function (el, att, val) { + if ( typeof(el) == "string" ) + el = document.getElementById(el); + var style = el.getAttribute("style"); + re = this.reGetStyleAttVal(att); + if ( re.test(style) ) { + style = style.replace( re, "$1"+ att +":"+ val +"$3" ); + } else { + style += ";"+ att +":"+ val; + } + el.setAttribute( "style", style ); + return val +} + +InkWeb.transmitAtt = function (conf) { + conf.att = conf.att.split( /\s+/ ); + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to.join ) + conf.to = [ conf.to ]; + for ( var toEl,elN=0; toEl=conf.to[elN]; elN++ ) { + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + for ( var i=0; i<conf.att.length; i++ ) { + var val = this.getStyle( conf.from, conf.att[i] ); + if ( val ) { + this.setStyle( toEl, conf.att[i], val ); + } else { + val = conf.from.getAttribute(conf.att[i]); + toEl.setAttribute( conf.att[i], val ); + } + } + } +} + +InkWeb.goto = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.to ; + if ( typeof(toEl) == "string" ) + toEl = document.getElementById( toEl ); + toEl = document.getElementById( conf.to ); + document.getElementsByTagName("svg")[0].viewBox.baseVal.x = toEl.getAttribute("x"); + document.getElementsByTagName("svg")[0].viewBox.baseVal.y = toEl.getAttribute("y"); +} + +InkWeb.setAtt = function (conf) { + if ( ! conf.el.join ) + conf.to = [ conf.el ]; + conf.att = conf.att.split( /\s+/ ); + conf.val = conf.val.split( /\s+/ ); + for ( var el,elN=0; el=conf.el[elN]; elN++ ) { + if ( typeof(el) == "string" ) + el = document.getElementById( el ); + for ( var att,i=0; att=conf.att[i]; i++ ) { + if ( + att == "width" || + att == "height" || + att == "x" || + att == "y" || + att == "cx" || + att == "cy" || + att == "r" || + att == "rx" || + att == "ry" || + att == "transform" + ) { + el.setAttribute( att, conf.val[i] ); + } else { + this.setStyle( el, att, conf.val[i] ); + } + } + } +} + +InkWeb.moveElTo = function (startConf) { + if ( typeof(startConf) == "string" ) { + // startConf may be only a element Id, to timeout recursive calls. + var el = document.getElementById( startConf ); + } else { + if ( typeof(startConf.el) == "string" ) + startConf.el = document.getElementById( startConf.el ); + var el = startConf.el; + } + if ( ! el.inkWebMoving ) { + el.inkWebMoving = { + step: 0 + }; + } + var conf = el.inkWebMoving; + if ( conf.step == 0 ) { + conf.x = startConf.x; + conf.y = startConf.y; + // dur : duration of the animation in seconds + if ( startConf.dur ) { conf.dur = startConf.dur } + else { conf.dur = 1 } + // steps : animation steps in a second + if ( startConf.stepsBySec ) { conf.stepsBySec = startConf.stepsBySec } + else { conf.stepsBySec = 16 } + conf.sleep = Math.round( 1000 / conf.stepsBySec ); + conf.steps = conf.dur * conf.stepsBySec; + var startPos = el.getBBox(); + conf.xInc = ( conf.x - startPos.x ) / conf.steps; + conf.yInc = ( conf.y - startPos.y ) / conf.steps; + conf.transform = el.transform.baseVal.consolidate(); + if ( ! conf.transform ) { + conf.transform = el.ownerSVGElement.createSVGTransform(); + } + el.transform.baseVal.clear(); + el.transform.baseVal.appendItem(conf.transform); + } + if ( conf.step < conf.steps ) { + conf.step++; + conf.transform.matrix.e += conf.xInc; + conf.transform.matrix.f += conf.yInc; + try{ el.ownerSVGElement.forceRedraw() } + catch(e){ this.log(e, "this "+el.ownerSVGElement+" has no forceRedraw().") } + conf.timeout = setTimeout( 'InkWeb.moveElTo("'+el.id+'")', conf.sleep ); + } else { + delete el.inkWebMoving; + } +} + +InkWeb.moveViewbox = function (conf) { + if ( typeof(conf.from) == "string" ) + conf.from = document.getElementById( conf.from ); + if ( ! conf.to ) + conf.to = conf.from ; + if ( typeof(conf.to) == "string" ) + conf.to = document.getElementById( conf.to ); + bbox = conf.to.getBBox(); + vbox = document.getElementsByTagName("svg")[0].viewBox; + document.getElementsByTagName("svg")[0].viewBox.baseVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.baseVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.baseVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.baseVal.height=bbox.height; + document.getElementsByTagName("svg")[0].viewBox.animVal.x=bbox.x; + document.getElementsByTagName("svg")[0].viewBox.animVal.y=bbox.y; + document.getElementsByTagName("svg")[0].viewBox.animVal.width=bbox.width; + document.getElementsByTagName("svg")[0].viewBox.animVal.heigt=bbox.height; + vbox = document.getElementsByTagName("svg")[0].viewBox; +} + +InkWeb.log = function () { /* requires inkweb-debug.js, not included in Inkscape */ } + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/webslicer_create_group__--id__slicerect1.out b/share/extensions/tests/data/refs/webslicer_create_group__--id__slicerect1.out new file mode 100644 index 0000000..ec3ec4c --- /dev/null +++ b/share/extensions/tests/data/refs/webslicer_create_group__--id__slicerect1.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/webslicer_create_rect.out b/share/extensions/tests/data/refs/webslicer_create_rect.out new file mode 100644 index 0000000..6f576e6 --- /dev/null +++ b/share/extensions/tests/data/refs/webslicer_create_rect.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + format: png + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/webslicer_create_rect__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/webslicer_create_rect__--id__p1__--id__r3.out new file mode 100644 index 0000000..6f576e6 --- /dev/null +++ b/share/extensions/tests/data/refs/webslicer_create_rect__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + format: png + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/webslicer_export__--dir__TMP_DIR.out b/share/extensions/tests/data/refs/webslicer_export__--dir__TMP_DIR.out new file mode 100644 index 0000000..e69de29 diff --git a/share/extensions/tests/data/refs/whirl__--id__p1__--id__r3__--whirl__1__0.out b/share/extensions/tests/data/refs/whirl__--id__p1__--id__r3__--whirl__1__0.out new file mode 100644 index 0000000..20b356f --- /dev/null +++ b/share/extensions/tests/data/refs/whirl__--id__p1__--id__r3__--whirl__1__0.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/wireframe_sphere.out b/share/extensions/tests/data/refs/wireframe_sphere.out new file mode 100644 index 0000000..1a6bac5 --- /dev/null +++ b/share/extensions/tests/data/refs/wireframe_sphere.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/wireframe_sphere__--id__p1__--id__r3.out b/share/extensions/tests/data/refs/wireframe_sphere__--id__p1__--id__r3.out new file mode 100644 index 0000000..1a6bac5 --- /dev/null +++ b/share/extensions/tests/data/refs/wireframe_sphere__--id__p1__--id__r3.out @@ -0,0 +1,41 @@ + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/refs/wmf_output.out b/share/extensions/tests/data/refs/wmf_output.out new file mode 100644 index 0000000..13d8ebb Binary files /dev/null and b/share/extensions/tests/data/refs/wmf_output.out differ diff --git a/share/extensions/tests/data/svg/clips_and_masks.svg b/share/extensions/tests/data/svg/clips_and_masks.svg new file mode 100644 index 0000000..4beccd4 --- /dev/null +++ b/share/extensions/tests/data/svg/clips_and_masks.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/colors.svg b/share/extensions/tests/data/svg/colors.svg new file mode 100644 index 0000000..026dc1a --- /dev/null +++ b/share/extensions/tests/data/svg/colors.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/complextransform.test.svg b/share/extensions/tests/data/svg/complextransform.test.svg new file mode 100644 index 0000000..478f850 --- /dev/null +++ b/share/extensions/tests/data/svg/complextransform.test.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/css.svg b/share/extensions/tests/data/svg/css.svg new file mode 100644 index 0000000..824ad65 --- /dev/null +++ b/share/extensions/tests/data/svg/css.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/curves.svg b/share/extensions/tests/data/svg/curves.svg new file mode 100644 index 0000000..6dc5ad8 --- /dev/null +++ b/share/extensions/tests/data/svg/curves.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/dash.svg b/share/extensions/tests/data/svg/dash.svg new file mode 100644 index 0000000..f131b78 --- /dev/null +++ b/share/extensions/tests/data/svg/dash.svg @@ -0,0 +1,40 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/dash_zerolength.svg b/share/extensions/tests/data/svg/dash_zerolength.svg new file mode 100644 index 0000000..a1745d0 --- /dev/null +++ b/share/extensions/tests/data/svg/dash_zerolength.svg @@ -0,0 +1,34 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/share/extensions/tests/data/svg/deep-ungroup-complex.svg b/share/extensions/tests/data/svg/deep-ungroup-complex.svg new file mode 100644 index 0000000..e47c0aa --- /dev/null +++ b/share/extensions/tests/data/svg/deep-ungroup-complex.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + Path with clip-path:none + Path with nested transforms + Transformed group withtransformed clip-path + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/default-inkscape-SVG.svg b/share/extensions/tests/data/svg/default-inkscape-SVG.svg new file mode 100644 index 0000000..259e13c --- /dev/null +++ b/share/extensions/tests/data/svg/default-inkscape-SVG.svg @@ -0,0 +1,37 @@ + + + + + + + + + image/svg+xml + + + + + + diff --git a/share/extensions/tests/data/svg/default-inkscape-SVG_scoured.svg b/share/extensions/tests/data/svg/default-inkscape-SVG_scoured.svg new file mode 100644 index 0000000..f46f0b3 --- /dev/null +++ b/share/extensions/tests/data/svg/default-inkscape-SVG_scoured.svg @@ -0,0 +1,12 @@ + + + + + + + image/svg+xml + + + + + diff --git a/share/extensions/tests/data/svg/default-plain-SVG.svg b/share/extensions/tests/data/svg/default-plain-SVG.svg new file mode 100644 index 0000000..9c08847 --- /dev/null +++ b/share/extensions/tests/data/svg/default-plain-SVG.svg @@ -0,0 +1,29 @@ + + + + + + + + + image/svg+xml + + + + + + + diff --git a/share/extensions/tests/data/svg/diff.svg b/share/extensions/tests/data/svg/diff.svg new file mode 100644 index 0000000..cf7f6f3 --- /dev/null +++ b/share/extensions/tests/data/svg/diff.svg @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + *Hello World* + flaw tux whatch wryps *PER + Multi*textFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/svg/doc_ai_conv_m_in.svg b/share/extensions/tests/data/svg/doc_ai_conv_m_in.svg new file mode 100644 index 0000000..f32fbfb --- /dev/null +++ b/share/extensions/tests/data/svg/doc_ai_conv_m_in.svg @@ -0,0 +1,24 @@ + + + Illustrator Import test document + This document should import as 8.5 x 11 inches. Illustrator uses a fixedresolution of 72 px per inch. + Text in Layer 1 + + + + + + Stroke only + Fill + stroke + Fill only + + + Three squares, each1 inch (2.54 cm) to a side.Objects do not changesize when stroke is added. + + + Text in Layer 2 + + Text in Layer 2A, a sub-layerof layer 2 + + + diff --git a/share/extensions/tests/data/svg/doc_ai_conv_mm_in.svg b/share/extensions/tests/data/svg/doc_ai_conv_mm_in.svg new file mode 100644 index 0000000..23b5359 --- /dev/null +++ b/share/extensions/tests/data/svg/doc_ai_conv_mm_in.svg @@ -0,0 +1,24 @@ + + + Illustrator Import test document + This document should import as 8.5 x 11 inches. Illustrator uses a fixedresolution of 72 px per inch. + Text in Layer 1 + + + + + + Stroke only + Fill + stroke + Fill only + + + Three squares, each1 inch (2.54 cm) to a side.Objects do not changesize when stroke is added. + + + Text in Layer 2 + + Text in Layer 2A, a sub-layerof layer 2 + + + diff --git a/share/extensions/tests/data/svg/dpiswitcher_96dpi.svg b/share/extensions/tests/data/svg/dpiswitcher_96dpi.svg new file mode 100644 index 0000000..c123ded --- /dev/null +++ b/share/extensions/tests/data/svg/dpiswitcher_96dpi.svg @@ -0,0 +1,169 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/dxf_nested_transforms.svg b/share/extensions/tests/data/svg/dxf_nested_transforms.svg new file mode 100644 index 0000000..4e80043 --- /dev/null +++ b/share/extensions/tests/data/svg/dxf_nested_transforms.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/edge3d.svg b/share/extensions/tests/data/svg/edge3d.svg new file mode 100644 index 0000000..cfb8570 --- /dev/null +++ b/share/extensions/tests/data/svg/edge3d.svg @@ -0,0 +1,31 @@ + + + + + + + image/svg+xml + + + + + + + diff --git a/share/extensions/tests/data/svg/ellipse_group_comment.svg b/share/extensions/tests/data/svg/ellipse_group_comment.svg new file mode 100644 index 0000000..285276f --- /dev/null +++ b/share/extensions/tests/data/svg/ellipse_group_comment.svg @@ -0,0 +1,21 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/svg/embed.svg b/share/extensions/tests/data/svg/embed.svg new file mode 100644 index 0000000..325f19e --- /dev/null +++ b/share/extensions/tests/data/svg/embed.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + some + different + fonts + + diff --git a/share/extensions/tests/data/svg/empty.svg b/share/extensions/tests/data/svg/empty.svg new file mode 100644 index 0000000..d6c680b --- /dev/null +++ b/share/extensions/tests/data/svg/empty.svg @@ -0,0 +1,13 @@ + + + + + diff --git a/share/extensions/tests/data/svg/empty_mm.svg b/share/extensions/tests/data/svg/empty_mm.svg new file mode 100644 index 0000000..c6c7af8 --- /dev/null +++ b/share/extensions/tests/data/svg/empty_mm.svg @@ -0,0 +1,14 @@ + + + + + diff --git a/share/extensions/tests/data/svg/empty_multipage.svg b/share/extensions/tests/data/svg/empty_multipage.svg new file mode 100644 index 0000000..7758938 --- /dev/null +++ b/share/extensions/tests/data/svg/empty_multipage.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/extrude.svg b/share/extensions/tests/data/svg/extrude.svg new file mode 100644 index 0000000..1d1d167 --- /dev/null +++ b/share/extensions/tests/data/svg/extrude.svg @@ -0,0 +1,129 @@ + + + + + + + + Test for extensions#190 + + + Test automatic conversion to Path + + + Test on open paths + + + Test on multiple subpaths and transform + + + + diff --git a/share/extensions/tests/data/svg/font.svg b/share/extensions/tests/data/svg/font.svg new file mode 100644 index 0000000..cc2b68f --- /dev/null +++ b/share/extensions/tests/data/svg/font.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/font_layers.svg b/share/extensions/tests/data/svg/font_layers.svg new file mode 100644 index 0000000..251e025 --- /dev/null +++ b/share/extensions/tests/data/svg/font_layers.svg @@ -0,0 +1,3 @@ + + + diff --git a/share/extensions/tests/data/svg/font_layers_apostrophe.svg b/share/extensions/tests/data/svg/font_layers_apostrophe.svg new file mode 100644 index 0000000..6105214 --- /dev/null +++ b/share/extensions/tests/data/svg/font_layers_apostrophe.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/share/extensions/tests/data/svg/gradient_with_mixed_offsets.svg b/share/extensions/tests/data/svg/gradient_with_mixed_offsets.svg new file mode 100644 index 0000000..7b322e6 --- /dev/null +++ b/share/extensions/tests/data/svg/gradient_with_mixed_offsets.svg @@ -0,0 +1,26 @@ + + + + Example radgrad01 - fill a rectangle by referencing a + radial gradient paint server + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/svg/group_interpolate.svg b/share/extensions/tests/data/svg/group_interpolate.svg new file mode 100644 index 0000000..c3d9f44 --- /dev/null +++ b/share/extensions/tests/data/svg/group_interpolate.svg @@ -0,0 +1,110 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/guides.svg b/share/extensions/tests/data/svg/guides.svg new file mode 100644 index 0000000..f67b40d --- /dev/null +++ b/share/extensions/tests/data/svg/guides.svg @@ -0,0 +1,233 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/guides_millimeter.svg b/share/extensions/tests/data/svg/guides_millimeter.svg new file mode 100644 index 0000000..1dd1cc1 --- /dev/null +++ b/share/extensions/tests/data/svg/guides_millimeter.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + Hello World! + + + diff --git a/share/extensions/tests/data/svg/hershey_input.svg b/share/extensions/tests/data/svg/hershey_input.svg new file mode 100755 index 0000000..e5ee87a --- /dev/null +++ b/share/extensions/tests/data/svg/hershey_input.svg @@ -0,0 +1,1082 @@ + + + + + + + + + image/svg+xml + + + + + + + test + This text has both a smaller bounding box, a smaller font size, and a large line spacing. The software must handle unusual cases like this.The real problem is that flowing into a text box (flowroot region) is SVG-renderer dependent-- even different web browsers may render flowed text differently. In this particular case, we're dealing with an Inkscape extension which does not have access to information about how the text was flowed before we got to it, so we essentially have to re-flow it from scratch. This data,is also text. However, it hasmany returnseachonitsownlinein order to makeit take up more verticalspace so that wecan see how it handlesweird edge caseslikethisone. +     We are testing an Inkscape extension called Hershey Text 3.0. The purpose of this extension is to take a block of flowed text, and replace it with stroke-based engraving fonts. We've got a number of different single-stroke fonts built in as well, that help to provide some options. However, we need to test that it handles a variety of different formats of text including different input fonts, alignment, flowed and regular text, variations of font size with a given span, returns, non-breaking spaces, transforms, nested groups and so forth. SVG allows text to be formatted in many different ways.This text is in Layer 1. Text, non-flowed,align left. However, it hasmany returnseachonitsownlinein order to makeit take up more verticalspace so that wecan see how it handlesweird edge caseslikethisone. + Text, non-flowed,align center However, it hasmany returnseachonitsownlinein order to makeit take up more verticalspace so that wecan see how it handlesweird edge caseslikethisone. + Text, non-flowed,align right. However, it hasmany returnseachonitsownlinein order to makeit take up more verticalspace so that wecan see how it handlesweird edge caseslikethisone. + Test: Flowed text, aligned left. Can we handle text that is aligned left, aligned right, centered, justified and so forth? Not all of these cases are necessarily useful for all applications (for example justified with stroke based fonts in the styles of handwriting), but that's not really for us to decide.Rather, we need to handle these cases because the text that is handed to us just might be in some unusual format.. This transformed text... is text with a gap... + Test: Flowed text, aligned center. Can we handle text that is aligned left, aligned right, centered, justified and so forth? Not all of these cases are necessarily useful for all applications (for example justified with stroke based fonts in the styles of handwriting), but that's not really for us to decide.Rather, we need to handle these cases because the text that is handed to us just might be in some unusual format.. Test: Flowed text, aligned right. Can we handle text that is aligned left, aligned right, centered, justified and so forth? Not all of these cases are necessarily useful for all applications (for example justified with stroke based fonts in the styles of handwriting), but that's not really for us to decide.Rather, we need to handle these cases because the text that is handed to us just might be in some unusual format.. Test: Flowed text, justified. Can we handle text that is aligned left, aligned right, centered, justified and so forth? Not all of these cases are necessarily useful for all applications (for example justified with stroke based fonts in the styles of handwriting), but that's not really for us to decide.Rather, we need to handle these cases because the text that is handed to us just might be in some unusual format.. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tests of font face mapping: + + + Tests of non-text objects: + + + This is a test of centered text, one long line of text flowed into a box, centered, and in a different font. flowStylesToCheck    Flowed text object with multiple returns before start and also       additional sections with more returnsThat was just one return, since the paragraph above this one.That was two returns, since the paragraph above this one.And that, that was three returns.Just for good measure, this paragraph had a return before the word "just" above. And, we're going to finish with a few returns as well. Bold Serif Text Dear Mike,Thanks for pointing out that we need to handle textthat is shaped like this as well.Have a great day! + Flowed text object with multiple sizes before the start and also       additional sections with more returns and non-breaking spaces, which need to be tested.Hershey Text v 3.0 for Inkscape This is an SVG document provided as an input for testing the Hershey Text extension.The purpose of this new extension is to take a block of flowed text, and replace it with stroke-based engraving fonts. It includes a small selection of such fonts, which need to be in the SVG format. Technically, it can work with any SVG font, even ones that are not stroke-based.This text is in the DOCUMENT ROOT. Scripty text Hand-written text Non-FlowedStylesToCheck + Multi-lineText createdWithout x and ybut with sodipodi:roleattributes instead. + Multi-lineText createdwith tspan elementsand x and ypositions + diff --git a/share/extensions/tests/data/svg/hershey_trivial_input.svg b/share/extensions/tests/data/svg/hershey_trivial_input.svg new file mode 100755 index 0000000..946a616 --- /dev/null +++ b/share/extensions/tests/data/svg/hershey_trivial_input.svg @@ -0,0 +1,124 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + Flow Text + + + + diff --git a/share/extensions/tests/data/svg/hpgl_multipen.svg b/share/extensions/tests/data/svg/hpgl_multipen.svg new file mode 100644 index 0000000..d27add9 --- /dev/null +++ b/share/extensions/tests/data/svg/hpgl_multipen.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/images.svg b/share/extensions/tests/data/svg/images.svg new file mode 100644 index 0000000..3af6c56 --- /dev/null +++ b/share/extensions/tests/data/svg/images.svg @@ -0,0 +1,73 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/images_multiple.svg b/share/extensions/tests/data/svg/images_multiple.svg new file mode 100644 index 0000000..53b14f2 --- /dev/null +++ b/share/extensions/tests/data/svg/images_multiple.svg @@ -0,0 +1,31 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/img/color_overlay_a.png b/share/extensions/tests/data/svg/img/color_overlay_a.png new file mode 100644 index 0000000..6a4382c Binary files /dev/null and b/share/extensions/tests/data/svg/img/color_overlay_a.png differ diff --git a/share/extensions/tests/data/svg/img/color_overlay_b.png b/share/extensions/tests/data/svg/img/color_overlay_b.png new file mode 100644 index 0000000..a231a52 Binary files /dev/null and b/share/extensions/tests/data/svg/img/color_overlay_b.png differ diff --git a/share/extensions/tests/data/svg/img/color_pad_a.png b/share/extensions/tests/data/svg/img/color_pad_a.png new file mode 100644 index 0000000..437f6a3 Binary files /dev/null and b/share/extensions/tests/data/svg/img/color_pad_a.png differ diff --git a/share/extensions/tests/data/svg/img/color_pad_b.png b/share/extensions/tests/data/svg/img/color_pad_b.png new file mode 100644 index 0000000..32f6bfc Binary files /dev/null and b/share/extensions/tests/data/svg/img/color_pad_b.png differ diff --git a/share/extensions/tests/data/svg/img/color_pad_c.png b/share/extensions/tests/data/svg/img/color_pad_c.png new file mode 100644 index 0000000..7f550cc Binary files /dev/null and b/share/extensions/tests/data/svg/img/color_pad_c.png differ diff --git a/share/extensions/tests/data/svg/img/green.png b/share/extensions/tests/data/svg/img/green.png new file mode 100644 index 0000000..bb606ff Binary files /dev/null and b/share/extensions/tests/data/svg/img/green.png differ diff --git a/share/extensions/tests/data/svg/img/linecap.png b/share/extensions/tests/data/svg/img/linecap.png new file mode 100644 index 0000000..5ffc248 Binary files /dev/null and b/share/extensions/tests/data/svg/img/linecap.png differ diff --git a/share/extensions/tests/data/svg/img/subfolder/linecap.png b/share/extensions/tests/data/svg/img/subfolder/linecap.png new file mode 100644 index 0000000..5ffc248 Binary files /dev/null and b/share/extensions/tests/data/svg/img/subfolder/linecap.png differ diff --git a/share/extensions/tests/data/svg/inkweb-debug.js b/share/extensions/tests/data/svg/inkweb-debug.js new file mode 100644 index 0000000..a79c460 --- /dev/null +++ b/share/extensions/tests/data/svg/inkweb-debug.js @@ -0,0 +1,367 @@ +/* +** InkWeb Debugger - help the development with InkWeb. +** +** Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +** +** ********* Bugs and New Fetures ************************************* +** If you found any bug on this script or if you want to propose a +** new feature, please report it in the inkscape bug tracker +** https://bugs.launchpad.net/inkscape/+filebug +** and assign that to Aurium. +** ******************************************************************** +** +** This program 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 3 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 Lesser 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, see . +** +** ******************************************************************** +** +** This script extends InkWeb with methods like log() and viewProperties(). +** So, you must to call this script after the inkweb.js load. +*/ + +InkWeb.debugVersion = 0.1; + +// Prepare InkWeb Debug: +(function (bli, xyz) { + // Add logging calls to all InkWeb methods: + for ( var att in InkWeb ) { + if ( typeof(InkWeb[att]) == "function" ) { + var code = InkWeb[att].toString() + beforeCode = 'this.log(this.__callMethodInfo("'+att+'", arguments));\ntry {'; + afterCode = '} catch(e) { this.log( e, "Ups... There is a problem in InkWeb.'+att+'()" ) }'; + code = code + .replace( /^(function [^{]+[{])/, "$1\n"+ beforeCode +"\n" ) + .replace( /[}]$/, ";\n"+ afterCode +"\n}" ); + eval( "InkWeb."+att+" = "+ code ); + //alert( InkWeb[att] ) + } + } +})(123,456); + +InkWeb.__callMethodInfo = function (funcName, arg) { + var func = arg.callee; + var str = 'Called InkWeb.'+funcName+'() with:' + if ( ! func.argList ) { + func.argList = func.toString() + .replace( /^function [^(]*\(([^)]*)\)(.|\s)*$/, "$1" ) + .split( /,\s*/ ); + } + for ( var a,i=0; a=func.argList[i]; i++ ) { + str += "\n"+ a +" = "+ this.serialize( arg[i], {recursionLimit:2} ); + } + return str; +} + + +InkWeb.copySerializeConf = function (conf) { + return { + recursionStep: conf.recursionStep, + recursionLimit: conf.recursionLimit, + showTagElements: conf.showTagElements + } +} + +InkWeb.serialize = function (v, conf) { + try { + if ( ! conf ) { conf = {} } + if ( ! conf.showTagElements ) { conf.showTagElements = false } + if ( ! conf.recursionLimit ) { conf.recursionLimit = 10 } + if ( ! conf.recursionStep ) { conf.recursionStep = 0 } + if ( conf.recursionLimit == 0 ) { + return '"<>"'; + } + conf.recursionLimit--; + conf.recursionStep++; + switch ( typeof(v) ) { + case "undefined": + v = "undefined"; + break; + case "string": + v = '"'+ v + .replace( /\n/g, "\\n" ) + .replace( /\r/g, "\\r" ) + .replace( /\t/g, "\\t" ) + .replace( /"/g, '"' ) + + '"'; + break; + case "boolean": + case "number": + case "function": + v = v.toString(); + break; + case "object": + if ( v == null ) { + v = "null"; + } else { + if ( v.constructor == Array ) { + try { + v = this.__serializeArray(v, conf); + } catch(e) { + this.log( e, "InkWeb.serialize(): Forced recursion limit in" + + " recursionLimit="+ conf.recursionLimit + + " and recursionStep="+ conf.recursionStep + ); + v += '"<>"' + } + } else { + // A Hash Object + if ( v.tagName && ! conf.showTagElements ) { + // Tags are not allowed. + v = '"<'+ v.tagName +' id=\\"'+ v.id +'\\">"'; + } else { + // Ok, serialize this object: + try { + v = this.__serializeObject(v, conf); + } catch(e) { + this.log( e, "InkWeb.serialize(): Forced recursion limit in" + + " recursionLimit="+ conf.recursionLimit + + " and recursionStep="+ conf.recursionStep + ); + v += '"<>"' + } + } + } + } + break; + default: + v = '"<>"'; + } + return v; + } catch(e) { + this.log( e, "Ups... There is a problem in InkWeb.serialize()." ); + } +} + +InkWeb.__serializeArray = function (v, conf) { + try { + var vStr = "[ "; + var size = v.length; + for ( var i=0; i0 ) { vStr += ", " } + vStr += this.serialize(v[i], this.copySerializeConf(conf)); + } + return vStr +" ]"; + } catch(e) { + this.log( e, "Ups... There is a problem in InkWeb.__serializeArray()." ); + } +} + +InkWeb.__serializeObject = function (obj, conf) { + try { + var vStr = "{ "; + var first = true; + for ( var att in obj ) { + if ( !first ) { vStr += ", " } + vStr += this.serialize(att) +':'+ + this.serialize( obj[att], this.copySerializeConf(conf) ); + first = false; + } + return vStr +" }"; + } catch(e) { + this.log( e, "Ups... There is a problem in InkWeb.__serializeObject()." ); + } +} + +// Allow log configuration: +InkWeb.mustLog = { + error: true, + warning: true, + sequence: true + }; + +// This will keep the log information: +InkWeb.__log__ = []; + +InkWeb.log = function (type, msg) { + /* This method register what was happen with InkWeb + ** ( if mustLog allows that ) + ** + ** --- Usage --- + ** this.log( <"sequence"|"warning"|"warn"|errorObject>, <"logMessage"> ); + ** this.log( <"logMessage"> ); // only for sequences + ** + ** --- Examples --- + ** Sequence log: + ** function foo (bar) { + ** InkWeb.log( 'Call function foo with argument bar="'+bar+'"' ); + ** + ** Warning log: + ** if ( foo == bar ) { + ** foo = other; + ** InkWeb.log( "warn", "foo must not be bar." ); + ** + ** Error log: + ** try { ... some hard thing ... } + ** catch (e) { InkWeb.log( e, "Trying to do some hard thing." ) } + */ + if ( this.mustLog ) { + if( type.constructor == ReferenceError ) { + // in a error logging the type argument is the error object. + var error = type; + type = "error"; + this.addViewLogBt(); + } + if( type == "warn" ) { + // that allows a little simplify in the log call. + type = "warning"; + } + if( msg == undefined ) { + // that allows to log a sequence without tos say the type. + msg = type; + type = "sequence"; + } + var logSize = this.__log__.length + if ( logSize > 0 && + this.__log__[logSize-1].type == type && + this.__log__[logSize-1].msg == msg ) { + this.__log__[logSize-1].happens++ + } else { + if ( type == "error" && this.mustLog.error ) { + this.__log__[logSize] = this.__logError( error, msg ) + } + if ( type == "warning" && this.mustLog.warning ) { + this.__log__[logSize] = this.__logWarning( msg ) + } + if ( type == "sequence" && this.mustLog.sequence ) { + this.__log__[logSize] = this.__logSequence( msg ) + } + } + } +} + +InkWeb.__logError = function ( error, msg ) { + return { type:"error", date:new Date(), msg:msg, error:error, happens:1 }; +} + +InkWeb.__logWarning = function ( msg ) { + return { type:"warning", date:new Date(), msg:msg, happens:1 }; +} + +InkWeb.__logSequence = function ( msg ) { + return { type:"sequence", date:new Date(), msg:msg, happens:1 }; +} + +InkWeb.logToString = function (conf) { + /* Show the log in a formatted string. + ** conf attributes: + ** format: a string to format the log items. + ** formatError: to format the error log items. + ** sep: the log items separator string. + ** format variables: + ** $F: the item date in the format YYYY-MM-DD + ** $T: the item time in the format HH:MM:SS + ** $type: the log type + ** $logmsg: the text argument in the log call + ** $times: how much times this item happens in sequence + ** $error: the error text (if this is a error item) + ** $index: the position of the item in the log list + ** $oddeven: return odd or even based in the index. + */ + if (!conf) { conf = {} } + if (!conf.sep) { conf.sep = "\n\n" } + if (!conf.format) { conf.format = "$F $T - $type - $logmsg - Happens $times." } + if (!conf.formatError) { conf.formatError = "$F $T - ERROR - $logmsg - Happens $times.\n$error" } + /* * * Helper * * */ + function _2d(num) { + return ( ( num < 10 )? "0"+num : ""+num ) + } + function _2dMonth(date) { + var m = date.getMonth() + 1; + return _2d( m ) + } + var str = ""; + var logSize = this.__log__.length; + if ( logSize == 0 ) { + str = "There are no errors."; + } + // View all items to mount the log string: + for ( var item,pos=0; item=this.__log__[pos]; pos++ ) { + var d = item.date; + // Add log line, converting variables: + var line = ( (item.type=="error")? conf.formatError : conf.format ); + str += line + .replace( /\$index/g, pos ) + .replace( /\$oddeven/g, (pos%2 == 1)? "odd" : "even" ) + .replace( /\$type/g, item.type ) + .replace( /\$logmsg/g, item.msg ) + .replace( /\$error/g, (item.error)? item.error.message : "" ) + .replace( /\$times/g, (item.happens>1)? item.happens+" times" : "one time" ) + .replace( /\$F/g, d.getFullYear() +"-"+ _2dMonth(d) +"-"+ _2d(d.getDate()) ) + .replace( /\$T/g, _2d(d.getHours()) +":"+ _2d(d.getMinutes()) +":"+ _2d(d.getSeconds()) ) + // Add separator: + if ( pos < (logSize-1) ) { str += conf.sep } + } + return str; +} + +InkWeb.addViewLogBt = function () { + var svg = document.getElementsByTagName("svg")[0]; + if ( this.__viewLogBt ) { + svg.appendChild( this.__viewLogBt ); + } else { + var g = this.el( "g", { onclick: "InkWeb.openLogWindow()", parent: svg } ); + var rect = this.el( "rect", { x: 10, y: 10, width: 60, height: 17, ry: 5, + style: "fill:#C00; stroke:#800; stroke-width:2", + parent: g } ); + var text = this.el( "text", { x: 40, y: 22, text: "View Log", + style: "fill:#FFF; font-size:10px;" + + "font-family:sans-serif;" + + "text-anchor:middle; text-align:center", + parent: g } ); + this.__viewLogBt = g; + } +} + +InkWeb.__openFormatedWindow = function (bodyHTML) { + var win = window.open("","_blank","width=500,height=500,scrollbars=yes"); + var html = + 'InkWeb' + + ''+ bodyHTML +''; + win.document.write(html); + win.document.close(); + return win; +} + +InkWeb.openLogWindow = function () { + var html = '

InkWeb Log

\n' + + '\n' + + '\n' + + this.logToString({ + format: '' + + '', + formatError: '' + + '\n'+ + '', + sep: '\n\n' + }) + + '\n
TimeMessageHappens
$T$logmsg$times
$T$logmsg$times
$error
' + var win = this.__openFormatedWindow( html ); + win.document.title = "InkWeb Log" +} + + +InkWeb.viewProperties = function () { + // Display object properties. + this.__openFormatedWindow( "coming soon..." ); +} diff --git a/share/extensions/tests/data/svg/inkwebjs-move.svg b/share/extensions/tests/data/svg/inkwebjs-move.svg new file mode 100644 index 0000000..b4aa50f --- /dev/null +++ b/share/extensions/tests/data/svg/inkwebjs-move.svg @@ -0,0 +1,128 @@ + + + + + + + + + + Test 1 - from left to right + Start + + End + + + + + + + + Test 2 - from right to left + Start + + End + + + + + + + + Test 3 - pre-translated + Start + + End + + + + + + + + Test 4 - pre-translated and scaled + Start + + End + + + + + + + + Test 5 - pre-translated and rotated + Start + + End + + + + + + + + Test 6 - with a transformation matrix + Start + + End + + + + + + + + + diff --git a/share/extensions/tests/data/svg/interp_shapes.svg b/share/extensions/tests/data/svg/interp_shapes.svg new file mode 100644 index 0000000..eaff106 --- /dev/null +++ b/share/extensions/tests/data/svg/interp_shapes.svg @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/markers.svg b/share/extensions/tests/data/svg/markers.svg new file mode 100644 index 0000000..bf9ca6f --- /dev/null +++ b/share/extensions/tests/data/svg/markers.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + diff --git a/share/extensions/tests/data/svg/mesh.svg b/share/extensions/tests/data/svg/mesh.svg new file mode 100644 index 0000000..cbf42af --- /dev/null +++ b/share/extensions/tests/data/svg/mesh.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/minimal-blank-prepare.svg b/share/extensions/tests/data/svg/minimal-blank-prepare.svg new file mode 100644 index 0000000..1fc27fb --- /dev/null +++ b/share/extensions/tests/data/svg/minimal-blank-prepare.svg @@ -0,0 +1 @@ + diff --git a/share/extensions/tests/data/svg/minimal-blank.svg b/share/extensions/tests/data/svg/minimal-blank.svg new file mode 100644 index 0000000..1fc27fb --- /dev/null +++ b/share/extensions/tests/data/svg/minimal-blank.svg @@ -0,0 +1 @@ + diff --git a/share/extensions/tests/data/svg/motion_tests.svg b/share/extensions/tests/data/svg/motion_tests.svg new file mode 100644 index 0000000..3491d6f --- /dev/null +++ b/share/extensions/tests/data/svg/motion_tests.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/multilayered-test.svg b/share/extensions/tests/data/svg/multilayered-test.svg new file mode 100644 index 0000000..c02d4ee --- /dev/null +++ b/share/extensions/tests/data/svg/multilayered-test.svg @@ -0,0 +1,156 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + Bottom layer + + + + + + Middle sublayer + + + + Middle layer + + + + Top layer + + + diff --git a/share/extensions/tests/data/svg/multiple_closed_subpaths.svg b/share/extensions/tests/data/svg/multiple_closed_subpaths.svg new file mode 100644 index 0000000..1548b50 --- /dev/null +++ b/share/extensions/tests/data/svg/multiple_closed_subpaths.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/paths_open_closed.svg b/share/extensions/tests/data/svg/paths_open_closed.svg new file mode 100644 index 0000000..95c2d88 --- /dev/null +++ b/share/extensions/tests/data/svg/paths_open_closed.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/pattern_along_path.svg b/share/extensions/tests/data/svg/pattern_along_path.svg new file mode 100644 index 0000000..8a2bf20 --- /dev/null +++ b/share/extensions/tests/data/svg/pattern_along_path.svg @@ -0,0 +1,498 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + Settings: Repeated, Stretched, Ribbon, Vertical. Tests a group pattern with multiple nested transforms + Settings: Repeated, Stretched, Ribbon. Tests a group pattern with multiple nested clones + Settings: Single, Stretched, Snake. Tests putting a text (converted to a path) on a path and stretching it to fit its length + + Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. Tests putting a path with multiple subpaths with a gradient on a closed path + Settings: Single, Stretched, Snake. Tests selecting multiple sceleton paths, one consisting of multiple subpaths + + diff --git a/share/extensions/tests/data/svg/pattern_along_path_clone_transform.svg b/share/extensions/tests/data/svg/pattern_along_path_clone_transform.svg new file mode 100644 index 0000000..2aa033e --- /dev/null +++ b/share/extensions/tests/data/svg/pattern_along_path_clone_transform.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/perspective.svg b/share/extensions/tests/data/svg/perspective.svg new file mode 100644 index 0000000..47a6f99 --- /dev/null +++ b/share/extensions/tests/data/svg/perspective.svg @@ -0,0 +1,33 @@ + + + + + + + diff --git a/share/extensions/tests/data/svg/perspective_groups.svg b/share/extensions/tests/data/svg/perspective_groups.svg new file mode 100644 index 0000000..33acaa2 --- /dev/null +++ b/share/extensions/tests/data/svg/perspective_groups.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/pixelsnap_simple.svg b/share/extensions/tests/data/svg/pixelsnap_simple.svg new file mode 100644 index 0000000..a25eaa7 --- /dev/null +++ b/share/extensions/tests/data/svg/pixelsnap_simple.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/preserved-transforms.svg b/share/extensions/tests/data/svg/preserved-transforms.svg new file mode 100644 index 0000000..db4eaa7 --- /dev/null +++ b/share/extensions/tests/data/svg/preserved-transforms.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/restack_grouped.svg b/share/extensions/tests/data/svg/restack_grouped.svg new file mode 100644 index 0000000..aee5629 --- /dev/null +++ b/share/extensions/tests/data/svg/restack_grouped.svg @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Ungrouped objects + Grouped objects + + + + + + + + diff --git a/share/extensions/tests/data/svg/rubber-stretch-test.svg b/share/extensions/tests/data/svg/rubber-stretch-test.svg new file mode 100644 index 0000000..ac8cf25 --- /dev/null +++ b/share/extensions/tests/data/svg/rubber-stretch-test.svg @@ -0,0 +1,66 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/share/extensions/tests/data/svg/scale_not_unity.svg b/share/extensions/tests/data/svg/scale_not_unity.svg new file mode 100644 index 0000000..2a4341a --- /dev/null +++ b/share/extensions/tests/data/svg/scale_not_unity.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/scatter.svg b/share/extensions/tests/data/svg/scatter.svg new file mode 100644 index 0000000..0a3ff5d --- /dev/null +++ b/share/extensions/tests/data/svg/scatter.svg @@ -0,0 +1,106 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/shapes-clipboard.svg b/share/extensions/tests/data/svg/shapes-clipboard.svg new file mode 100644 index 0000000..86b674d --- /dev/null +++ b/share/extensions/tests/data/svg/shapes-clipboard.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/svg/shapes.svg b/share/extensions/tests/data/svg/shapes.svg new file mode 100644 index 0000000..eb9caed --- /dev/null +++ b/share/extensions/tests/data/svg/shapes.svg @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/svg/shapes_cmyk.svg b/share/extensions/tests/data/svg/shapes_cmyk.svg new file mode 100644 index 0000000..bc35be8 --- /dev/null +++ b/share/extensions/tests/data/svg/shapes_cmyk.svg @@ -0,0 +1,302 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + format: png +dpi: 96 +layout-disposition: bg-el-norepeat +layout-position-anchor: tl + + + + + + + + + + + + + Hello World + flow text which wraps + UPPER + Multi linetextFOO + + Grouped + text + + + + + + + diff --git a/share/extensions/tests/data/svg/simple_patterns.svg b/share/extensions/tests/data/svg/simple_patterns.svg new file mode 100644 index 0000000..66d8fd9 --- /dev/null +++ b/share/extensions/tests/data/svg/simple_patterns.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/simpletransform.test.svg b/share/extensions/tests/data/svg/simpletransform.test.svg new file mode 100644 index 0000000..62876ee --- /dev/null +++ b/share/extensions/tests/data/svg/simpletransform.test.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/share/extensions/tests/data/svg/single_box.svg b/share/extensions/tests/data/svg/single_box.svg new file mode 100644 index 0000000..094233d --- /dev/null +++ b/share/extensions/tests/data/svg/single_box.svg @@ -0,0 +1,62 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/share/extensions/tests/data/svg/slicer.svg b/share/extensions/tests/data/svg/slicer.svg new file mode 100644 index 0000000..a485c35 --- /dev/null +++ b/share/extensions/tests/data/svg/slicer.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/style_inheritance.svg b/share/extensions/tests/data/svg/style_inheritance.svg new file mode 100644 index 0000000..d80e78f --- /dev/null +++ b/share/extensions/tests/data/svg/style_inheritance.svg @@ -0,0 +1,75 @@ + + + + + + + 1. Using style attribute + directly + + + + + 2. Using class "shape_direct" + directly on path and rect + + + + + 3. Using class "shape_under_group" + which inherits from class "group" + + + + + 4. Inheriting from "group", but + referencing square by id + + + + + 5. Apply style rules at grouplevel + + + + + 6. Apply style rules to groupand force inheritance + + \ No newline at end of file diff --git a/share/extensions/tests/data/svg/styling-css-04-f.svg b/share/extensions/tests/data/svg/styling-css-04-f.svg new file mode 100755 index 0000000..e405b04 --- /dev/null +++ b/share/extensions/tests/data/svg/styling-css-04-f.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + This purpose of the file is to test some of the CSS2 selector syntax. + A UA supporting CSS selectors should render an image identical to the referenced image. + + For a full analysis of this test, please see + this explanation. + + + styling-css-04-f.svg + Tests CSS2 selectors + + + + + CSS selector test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A + B + C + D + E + F + 1 + 2 + 3 + + + $Revision: 1.13 $ + + diff --git a/share/extensions/tests/data/svg/styling-inherit-01-b.svg b/share/extensions/tests/data/svg/styling-inherit-01-b.svg new file mode 100755 index 0000000..2620107 --- /dev/null +++ b/share/extensions/tests/data/svg/styling-inherit-01-b.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + Verify property inheritance as required by 6.15 "Property + inheritance". Since all implementations are required to do this, only + presentation attributes are used. + + At the center right, there is an ellipse. The fill color is not + specified on that element but on its parent. The ellipse should be filled a solid yellow + + At the top left, an oval shape is formed from a rectangle + with a radial gradient. The color of the middle stop uses the keyword 'inherit' + and thus takes its parent's value of green, giving a yellow, green, white gradient. + At the bottom left, an oval shape is formed from a rectangle + with a radial gradient. The color of the middle stop uses the value 'currentColor' + and thus takes the value its parent's color property, a dark red, + giving a yellow, dark red, white gradient. + + + styling-inherit-01-b + Verify property inheritance + + + + + + + + + + + + + + + + + + + + + + + + $Revision: 1.2 $ + + diff --git a/share/extensions/tests/data/svg/symbol.svg b/share/extensions/tests/data/svg/symbol.svg new file mode 100644 index 0000000..a8e20f3 --- /dev/null +++ b/share/extensions/tests/data/svg/symbol.svg @@ -0,0 +1,46 @@ + + + + + + + Air Transportation + + + + + + + + diff --git a/share/extensions/tests/data/svg/text_on_arc.svg b/share/extensions/tests/data/svg/text_on_arc.svg new file mode 100644 index 0000000..337831b --- /dev/null +++ b/share/extensions/tests/data/svg/text_on_arc.svg @@ -0,0 +1,19 @@ + + + + + + + + + image/svg+xml + + + + + + + + Curved Text + + \ No newline at end of file diff --git a/share/extensions/tests/data/svg/text_types.svg b/share/extensions/tests/data/svg/text_types.svg new file mode 100644 index 0000000..191623f --- /dev/null +++ b/share/extensions/tests/data/svg/text_types.svg @@ -0,0 +1,256 @@ + + + + + + + + + + This is a regular textWith a line break. + This is regular textwith a line breakand some transforms. + This is an SVG2 flowed text. (inline size) +This is a line break inside that text. + This is a text with kerns adjusted in tspans(as Inkscape does it) + This is an SVG1.2 flowed text (flowroot)And this is a linebreak inside. + This is an SVG1.2 flowed textWith absolute line-height + This is an SVG1.2 flowed textwithout line height. + 0.50.10.10.10.34.20.54.30.14.5 + This is a text with direction:rtl + This is an SVG2 flowed text (shape inside) + This is a test document containing different transformed text elements that were created using different methods.The containing layer has a transform applied as well. + + diff --git a/share/extensions/tests/data/svg/three_pages_and_two_grids.svg b/share/extensions/tests/data/svg/three_pages_and_two_grids.svg new file mode 100644 index 0000000..959a923 --- /dev/null +++ b/share/extensions/tests/data/svg/three_pages_and_two_grids.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/share/extensions/tests/data/svg/transformed-layer.svg b/share/extensions/tests/data/svg/transformed-layer.svg new file mode 100644 index 0000000..6148ea2 --- /dev/null +++ b/share/extensions/tests/data/svg/transformed-layer.svg @@ -0,0 +1,19 @@ + + + + + + + diff --git a/share/extensions/tests/data/svg/with-lpe.svg b/share/extensions/tests/data/svg/with-lpe.svg new file mode 100644 index 0000000..89d590e --- /dev/null +++ b/share/extensions/tests/data/svg/with-lpe.svg @@ -0,0 +1,30 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/share/extensions/tests/data/ui/app-test.ui b/share/extensions/tests/data/ui/app-test.ui new file mode 100644 index 0000000..e53129b --- /dev/null +++ b/share/extensions/tests/data/ui/app-test.ui @@ -0,0 +1,50 @@ + + + + + + False + + + True + False + vertical + + + + gtk-apply + False + True + True + True + True + + + + False + True + 8 + 0 + + + + + gtk-quit + False + True + True + True + True + + + + False + True + 8 + 1 + + + + + + diff --git a/share/extensions/tests/data/ui/listing-app.ui b/share/extensions/tests/data/ui/listing-app.ui new file mode 100644 index 0000000..71710ab --- /dev/null +++ b/share/extensions/tests/data/ui/listing-app.ui @@ -0,0 +1,71 @@ + + + + + + False + + + True + False + vertical + 10 + + + True + True + + + + + + + True + True + 0 + + + + + True + False + + + False + True + 1 + + + + + True + True + 6 + + + True + True + 2 + + + + + gtk-quit + False + True + True + True + True + + + + False + True + 8 + 3 + + + + + + diff --git a/share/extensions/tests/data/ui/window-test.ui b/share/extensions/tests/data/ui/window-test.ui new file mode 100644 index 0000000..158df06 --- /dev/null +++ b/share/extensions/tests/data/ui/window-test.ui @@ -0,0 +1,91 @@ + + + + + + False + + + True + False + vertical + + + gtk-apply + False + True + True + True + True + + + False + True + 8 + 0 + + + + + gtk-quit + False + True + True + True + True + + + + False + True + 8 + 1 + + + + + + + False + + + True + False + vertical + + + gtk-apply + False + True + True + True + True + + + False + True + 8 + 0 + + + + + gtk-close + False + True + True + True + True + + + + False + True + 8 + 1 + + + + + + diff --git a/share/extensions/tests/test_addnodes.py b/share/extensions/tests/test_addnodes.py new file mode 100644 index 0000000..2797caa --- /dev/null +++ b/share/extensions/tests/test_addnodes.py @@ -0,0 +1,47 @@ +# coding=utf-8 +from addnodes import AddNodes +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class SplitItBasicTest(ComparisonMixin, TestCase): + effect_class = AddNodes + comparisons = [ + ( + "--id=p1", + "--id=r3", + "--max=2.0", + ) + ] + compare_filters = [ + CompareWithPathSpace(), + CompareNumericFuzzy(), + ] + + def test_basic(self): + args = ["--id=dashme", self.data_file("svg", "dash.svg")] + effect = self.effect_class() + effect.run(args) + old_path = effect.original_document.getroot().getElement("//svg:path").path + new_path = effect.svg.getElement("//svg:path").path + assert len(new_path) > len(old_path) + + +class SplitNodesClosedTest(ComparisonMixin, TestCase): + effect_class = AddNodes + comparisons = [ + ( + "--id=rect723", + "--id=rect723-5", + "--id=path747", + "--id=path1080", + "--id=path1115", + "--method=bynum", + "--segments=3", + ) + ] + compare_filters = [ + CompareWithPathSpace(), + CompareNumericFuzzy(), + ] + compare_file = "svg/paths_open_closed.svg" diff --git a/share/extensions/tests/test_color_HSL_adjust.py b/share/extensions/tests/test_color_HSL_adjust.py new file mode 100644 index 0000000..640a468 --- /dev/null +++ b/share/extensions/tests/test_color_HSL_adjust.py @@ -0,0 +1,33 @@ +# coding=utf-8 +from color_hsl_adjust import HslAdjust +from .test_inkex_extensions import ColorBaseCase + + +class ColorHSLAdjustTest(ColorBaseCase): + effect_class = HslAdjust + color_tests = [ + ("none", "none"), + ((255, 255, 255), "#ffffff"), + ((0, 0, 0), "#000000"), + ((0, 128, 0), "#008000"), + ((91, 166, 176), "#5a98af", ["-x 10"]), + ((91, 166, 176), "#5aaf80", ["-x 320"]), + ((91, 166, 176), "#5ba6b0", ["-x 0"]), + ((91, 166, 176), "#af5a78", ["-x 12345"]), + ((91, 166, 176), "#5aa8af", ["-x -1"]), + ((91, 166, 176), "#4eafbb", ["-s 10"]), + ((91, 166, 176), "#0be5fe", ["-s 90"]), + ((91, 166, 176), "#5ba6b0", ["-s 0"]), + ((91, 166, 176), "#0be5fe", ["-s 100"]), + ((91, 166, 176), "#0be5fe", ["-s 12345"]), + ((91, 166, 176), "#5ba5ae", ["-s -1"]), + ((91, 166, 176), "#7cb8bf", ["-l 10"]), + ((91, 166, 176), "#ffffff", ["-l 90"]), + ((91, 166, 176), "#5ba6b0", ["-l 0"]), + ((91, 166, 176), "#ffffff", ["-l 100"]), + ((91, 166, 176), "#ffffff", ["-l 12345"]), + ((91, 166, 176), "#56a4ad", ["-l -1"]), + ((91, 166, 176), "#5a86af", ["--random_h=true"]), + ((91, 166, 176), "#cde4e6", ["--random_l=true"]), + ((91, 166, 176), "#43b8c6", ["--random_s=true"]), + ] diff --git a/share/extensions/tests/test_color_blackandwhite.py b/share/extensions/tests/test_color_blackandwhite.py new file mode 100644 index 0000000..5f54481 --- /dev/null +++ b/share/extensions/tests/test_color_blackandwhite.py @@ -0,0 +1,33 @@ +# coding=utf-8 +from color_blackandwhite import BlackAndWhite +from .test_inkex_extensions import ColorBaseCase + + +class ColorBlackAndWhiteTest(ColorBaseCase): + effect_class = BlackAndWhite + color_tests = [ + # When converting to black and white the color white should be unchanged + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#ffffff"), + ((128, 128, 128), "#ffffff"), + ((128, 0, 0), "#000000"), + ((255, 0, 0), "#000000"), + ((128, 128, 0), "#000000"), + ((255, 255, 0), "#ffffff"), + ((0, 128, 0), "#000000"), + ((0, 255, 0), "#ffffff"), + ((0, 128, 128), "#000000"), + ((0, 255, 255), "#ffffff"), + ((0, 0, 128), "#000000"), + ((0, 0, 255), "#000000"), + ((128, 0, 128), "#000000"), + ((255, 0, 255), "#000000"), + # Increasing the threshold means more colors will be black + ((255, 0, 255), "#000000", ["-t 240"]), + ((192, 192, 192), "#000000", ["-t 240"]), + # Decreasing the threshold means more colors will be white + ((255, 0, 255), "#ffffff", ["-t 80"]), + ((192, 192, 192), "#ffffff", ["-t 80"]), + ] diff --git a/share/extensions/tests/test_color_brighter.py b/share/extensions/tests/test_color_brighter.py new file mode 100644 index 0000000..0d73eb6 --- /dev/null +++ b/share/extensions/tests/test_color_brighter.py @@ -0,0 +1,27 @@ +# coding=utf-8 +from color_brighter import Brighter +from .test_inkex_extensions import ColorBaseCase + + +class ColorBrighterTest(ColorBaseCase): + effect_class = Brighter + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#0a0a0a"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#d5d5d5"), + ((128, 128, 128), "#8e8e8e"), + ((128, 0, 0), "#8e0000"), + ((255, 0, 0), "#ff0000"), + ((128, 128, 0), "#8e8e00"), + ((255, 255, 0), "#ffff00"), + ((0, 128, 0), "#008e00"), + ((0, 255, 0), "#00ff00"), + ((0, 128, 128), "#008e8e"), + ((0, 255, 255), "#00ffff"), + ((0, 0, 128), "#00008e"), + ((0, 0, 255), "#0000ff"), + ((128, 0, 128), "#8e008e"), + ((255, 0, 255), "#ff00ff"), + ("hsl(33, 92, 128)", "hsl(33, 92, 142)"), + ] diff --git a/share/extensions/tests/test_color_custom.py b/share/extensions/tests/test_color_custom.py new file mode 100644 index 0000000..75b444f --- /dev/null +++ b/share/extensions/tests/test_color_custom.py @@ -0,0 +1,50 @@ +# coding=utf-8 + +import inkex +from color_custom import Custom +from .test_inkex_extensions import ColorBaseCase + + +class ColorCustomTest(ColorBaseCase): + effect_class = Custom + color_tests = [ + # The default ranges are set to 0, and thus the color should not change. + ("none", "none"), + ((255, 255, 255), "#ffffff"), + ((100, 0, 0), "#c80000", ["-r r*2"]), + ((12, 34, 56), "#0c3822", ["-g b", "-b g"]), + ((12, 34, 56), "#183822", ["-g b", "-b g", "-r r*2"]), + ((0, 0, 0), "#100000", ["-s 255", "-r 16"]), + ((0, 0, 0), "#0f0000", ["-s 1", "-r 0.0625"]), + ((0, 0, 0), "#ff0000", ["-r 400"]), + ((0, 0, 0), "#000000", ["-r -400"]), + ("red", "#fe0000", ["-s 400"]), + ] + + def test_evil_fails(self): + """ + eval shouldn't allow for evil things to happen + + Here we try and check if a file exists but it could just as easily + overwrite or delete the file + + """ + args = ["-r __import__('os').path.exists('__init__.py')", self.empty_svg] + self.effect.run(args) + + with self.assertRaises(TypeError): + self.effect.modify_color("fill", inkex.Color("black")) + + def test_invalid_operator(self): + args = ["-r r % 100", self.empty_svg] + self.effect.run(args) + + with self.assertRaises(KeyError): + self.effect.modify_color("fill", inkex.Color("black")) + + def test_bad_syntax(self): + args = ["-r r + 100)", self.empty_svg] + self.effect.run(args) + + with self.assertRaises(SyntaxError): + self.effect.modify_color("fill", inkex.Color("black")) diff --git a/share/extensions/tests/test_color_darker.py b/share/extensions/tests/test_color_darker.py new file mode 100644 index 0000000..b3eb632 --- /dev/null +++ b/share/extensions/tests/test_color_darker.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_darker import Darker +from .test_inkex_extensions import ColorBaseCase + + +class ColorDarkerTest(ColorBaseCase): + effect_class = Darker + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#e6e6e6"), + ((192, 192, 192), "#adadad"), + ((128, 128, 128), "#737373"), + ((128, 0, 0), "#730000"), + ((255, 0, 0), "#e60000"), + ((128, 128, 0), "#737300"), + ((255, 255, 0), "#e6e600"), + ((0, 128, 0), "#007300"), + ((0, 255, 0), "#00e600"), + ((0, 128, 128), "#007373"), + ((0, 255, 255), "#00e6e6"), + ((0, 0, 128), "#000073"), + ((0, 0, 255), "#0000e6"), + ((128, 0, 128), "#730073"), + ((255, 0, 255), "#e600e6"), + ("hsl(25, 14, 128)", "hsl(25, 14, 115)"), + ("red", "#e60000"), + ] diff --git a/share/extensions/tests/test_color_desaturate.py b/share/extensions/tests/test_color_desaturate.py new file mode 100644 index 0000000..a49cf5c --- /dev/null +++ b/share/extensions/tests/test_color_desaturate.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_desaturate import Desaturate +from .test_inkex_extensions import ColorBaseCase + + +class ColorDesaturateTest(ColorBaseCase): + effect_class = Desaturate + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#404040"), + ((255, 0, 0), "#7f7f7f"), + ((128, 128, 0), "#404040"), + ((255, 255, 0), "#7f7f7f"), + ((0, 128, 0), "#404040"), + ((0, 255, 0), "#7f7f7f"), + ((0, 128, 128), "#404040"), + ((0, 255, 255), "#7f7f7f"), + ((0, 0, 128), "#404040"), + ((0, 0, 255), "#7f7f7f"), + ((128, 0, 128), "#404040"), + ((255, 0, 255), "#7f7f7f"), + ] diff --git a/share/extensions/tests/test_color_grayscale.py b/share/extensions/tests/test_color_grayscale.py new file mode 100644 index 0000000..2979262 --- /dev/null +++ b/share/extensions/tests/test_color_grayscale.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_grayscale import Grayscale +from .test_inkex_extensions import ColorBaseCase + + +class ColorGrayscaleTest(ColorBaseCase): + effect_class = Grayscale + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#262626"), + ((255, 0, 0), "#4c4c4c"), + ((128, 128, 0), "#717171"), + ((255, 255, 0), "#e2e2e2"), + ((0, 128, 0), "#4b4b4b"), + ((0, 255, 0), "#969696"), + ((0, 128, 128), "#5a5a5a"), + ((0, 255, 255), "#b3b3b3"), + ((0, 0, 128), "#0f0f0f"), + ((0, 0, 255), "#1d1d1d"), + ((128, 0, 128), "#353535"), + ((255, 0, 255), "#696969"), + ] diff --git a/share/extensions/tests/test_color_lesshue.py b/share/extensions/tests/test_color_lesshue.py new file mode 100644 index 0000000..e86b54d --- /dev/null +++ b/share/extensions/tests/test_color_lesshue.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_lesshue import LessHue +from .test_inkex_extensions import ColorBaseCase + + +class ColorLessHueTest(ColorBaseCase): + effect_class = LessHue + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(243, 0, 0)"), + ("hsl(255, 255, 255)", "hsl(243, 255, 255)"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#800024"), + ((255, 0, 0), "#fe0047"), + ((128, 128, 0), "#805a00"), + ((255, 255, 0), "#feb300"), + ((0, 128, 0), "#248000"), + ((0, 255, 0), "#47fe00"), + ((0, 128, 128), "#00805a"), + ((0, 255, 255), "#00feb3"), + ((0, 0, 128), "#002480"), + ((0, 0, 255), "#0047fe"), + ((128, 0, 128), "#5a0080"), + ((255, 0, 255), "#b300fe"), + ] diff --git a/share/extensions/tests/test_color_lesslight.py b/share/extensions/tests/test_color_lesslight.py new file mode 100644 index 0000000..c35c38f --- /dev/null +++ b/share/extensions/tests/test_color_lesslight.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_lesslight import LessLight +from .test_inkex_extensions import ColorBaseCase + + +class ColorLessLightTest(ColorBaseCase): + effect_class = LessLight + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(0, 0, 0)"), + ("hsl(255, 255, 255)", "hsl(255, 255, 243)"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#f3f3f3"), + ((192, 192, 192), "#b4b4b4"), + ((128, 128, 128), "#747474"), + ((128, 0, 0), "#680000"), + ((255, 0, 0), "#e60000"), + ((128, 128, 0), "#686600"), + ((255, 255, 0), "#e6e300"), + ((0, 128, 0), "#006800"), + ((0, 255, 0), "#00e600"), + ((0, 128, 128), "#006866"), + ((0, 255, 255), "#00e6e3"), + ((0, 0, 128), "#000068"), + ((0, 0, 255), "#0000e6"), + ((128, 0, 128), "#660068"), + ((255, 0, 255), "#e300e6"), + ] diff --git a/share/extensions/tests/test_color_lesssaturation.py b/share/extensions/tests/test_color_lesssaturation.py new file mode 100644 index 0000000..6396e4b --- /dev/null +++ b/share/extensions/tests/test_color_lesssaturation.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_lesssaturation import LessSaturation +from .test_inkex_extensions import ColorBaseCase + + +class ColorLessSaturationTest(ColorBaseCase): + effect_class = LessSaturation + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(0, 0, 0)"), + ("hsl(255, 255, 255)", "hsl(255, 243, 255)"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#7c0303"), + ((255, 0, 0), "#f80505"), + ((128, 128, 0), "#7c7b03"), + ((255, 255, 0), "#f8f505"), + ((0, 128, 0), "#037c03"), + ((0, 255, 0), "#05f805"), + ((0, 128, 128), "#037c7b"), + ((0, 255, 255), "#05f8f5"), + ((0, 0, 128), "#03037c"), + ((0, 0, 255), "#0505f8"), + ((128, 0, 128), "#7b037c"), + ((255, 0, 255), "#f505f8"), + ] diff --git a/share/extensions/tests/test_color_list.py b/share/extensions/tests/test_color_list.py new file mode 100644 index 0000000..21e1e89 --- /dev/null +++ b/share/extensions/tests/test_color_list.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from color_list import ListColours +from .test_inkex_extensions import ColorEffectTest +from inkex.tester.filters import WindowsTextCompat + + +class ColorListTest(ColorEffectTest): + effect_class = ListColours + effect_name = "test_color_list" + stderr_output = True + compare_filters = [WindowsTextCompat()] + color_tests = [] diff --git a/share/extensions/tests/test_color_morehue.py b/share/extensions/tests/test_color_morehue.py new file mode 100644 index 0000000..ae4c6e8 --- /dev/null +++ b/share/extensions/tests/test_color_morehue.py @@ -0,0 +1,29 @@ +# coding=utf-8 + +from color_morehue import MoreHue +from .test_inkex_extensions import ColorBaseCase + + +class ColorMoreHueTest(ColorBaseCase): + effect_class = MoreHue + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(12, 0, 0)"), + ("hsl(255, 255, 255)", "hsl(12, 255, 255)"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#802400"), + ((255, 0, 0), "#fe4700"), + ((128, 128, 0), "#5d8000"), + ((255, 255, 0), "#b9fe00"), + ((0, 128, 0), "#008024"), + ((0, 255, 0), "#00fe47"), + ((0, 128, 128), "#005d80"), + ((0, 255, 255), "#00b9fe"), + ((0, 0, 128), "#240080"), + ((0, 0, 255), "#4700fe"), + ((128, 0, 128), "#80005d"), + ((255, 0, 255), "#fe00b9"), + ] diff --git a/share/extensions/tests/test_color_morelight.py b/share/extensions/tests/test_color_morelight.py new file mode 100644 index 0000000..c0e227c --- /dev/null +++ b/share/extensions/tests/test_color_morelight.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_morelight import MoreLight +from .test_inkex_extensions import ColorBaseCase + + +class ColorMoreLightTest(ColorBaseCase): + effect_class = MoreLight + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(0, 0, 12)"), + ("hsl(255, 255, 255)", "hsl(255, 255, 255)"), + ((0, 0, 0), "#0c0c0c"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#cccccc"), + ((128, 128, 128), "#8c8c8c"), + ((128, 0, 0), "#980000"), + ((255, 0, 0), "#fe1717"), + ((128, 128, 0), "#989600"), + ((255, 255, 0), "#fefc17"), + ((0, 128, 0), "#009800"), + ((0, 255, 0), "#17fe17"), + ((0, 128, 128), "#009896"), + ((0, 255, 255), "#17fefc"), + ((0, 0, 128), "#000098"), + ((0, 0, 255), "#1717fe"), + ((128, 0, 128), "#960098"), + ((255, 0, 255), "#fc17fe"), + ] diff --git a/share/extensions/tests/test_color_moresaturation.py b/share/extensions/tests/test_color_moresaturation.py new file mode 100644 index 0000000..5a3c196 --- /dev/null +++ b/share/extensions/tests/test_color_moresaturation.py @@ -0,0 +1,28 @@ +# coding=utf-8 +from color_moresaturation import MoreSaturation +from .test_inkex_extensions import ColorBaseCase + + +class ColorMoreSaturationTest(ColorBaseCase): + effect_class = MoreSaturation + color_tests = [ + ("none", "none"), + ("hsl(0, 0, 0)", "hsl(0, 12, 0)"), + ("hsl(255, 255, 255)", "hsl(255, 255, 255)"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c2bdbd"), + ((128, 128, 128), "#857a7a"), + ((128, 0, 0), "#800000"), + ((255, 0, 0), "#fe0000"), + ((128, 128, 0), "#807e00"), + ((255, 255, 0), "#fefb00"), + ((0, 128, 0), "#008000"), + ((0, 255, 0), "#00fe00"), + ((0, 128, 128), "#00807e"), + ((0, 255, 255), "#00fefb"), + ((0, 0, 128), "#000080"), + ((0, 0, 255), "#0000fe"), + ((128, 0, 128), "#7e0080"), + ((255, 0, 255), "#fb00fe"), + ] diff --git a/share/extensions/tests/test_color_negative.py b/share/extensions/tests/test_color_negative.py new file mode 100644 index 0000000..bf84bfc --- /dev/null +++ b/share/extensions/tests/test_color_negative.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_negative import Negative +from .test_inkex_extensions import ColorBaseCase + + +class ColorNegativeTest(ColorBaseCase): + effect_class = Negative + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#ffffff"), + ((255, 255, 255), "#000000"), + ((192, 192, 192), "#3f3f3f"), + ((128, 128, 128), "#7f7f7f"), + ((128, 0, 0), "#7fffff"), + ((255, 0, 0), "#00ffff"), + ((128, 128, 0), "#7f7fff"), + ((255, 255, 0), "#0000ff"), + ((0, 128, 0), "#ff7fff"), + ((0, 255, 0), "#ff00ff"), + ((0, 128, 128), "#ff7f7f"), + ((0, 255, 255), "#ff0000"), + ((0, 0, 128), "#ffff7f"), + ((0, 0, 255), "#ffff00"), + ((128, 0, 128), "#7fff7f"), + ((255, 0, 255), "#00ff00"), + ] diff --git a/share/extensions/tests/test_color_randomize.py b/share/extensions/tests/test_color_randomize.py new file mode 100644 index 0000000..496e741 --- /dev/null +++ b/share/extensions/tests/test_color_randomize.py @@ -0,0 +1,93 @@ +# coding=utf-8 +from color_randomize import Randomize +from .test_inkex_extensions import ColorBaseCase +from inkex.tester import ComparisonMixin, TestCase + +Randomize.deterministic_output = True + + +class ColorRandomizeTest(ColorBaseCase): + effect_class = Randomize + python3_only = True + color_tests = [ + # "hsl(191, 122, 150)" = rgb(150, 100, 200) + ("none", "none"), + # The default ranges are set to 0, and thus the color and opacity should not change (except + # for rounding errors) + ("hsl(191, 122, 150)", "hsl(191, 122, 149)"), + # The user selected 0% values, and thus the color should not change. + ("hsl(191, 122, 150)", "hsl(191, 122, 149)", ["-y 0", "-t 0", "-m 0"]), + # Random hue only. Saturation and lightness not changed. + ("hsl(191, 122, 150)", "hsl(223, 122, 149)", ["-y 50", "-t 0", "-m 0"]), + # Same settings, test stationarity of output. + ("hsl(191, 122, 150)", "hsl(223, 122, 149)", ["-y 50", "-t 0", "-m 0"]), + # Random saturation only. Hue and lightness not changed. + ("hsl(191, 122, 150)", "hsl(191, 146, 149)", ["-y 0", "-t 30", "-m 0"]), + # Random lightness only. Hue and saturation not changed. + ("hsl(191, 122, 150)", "hsl(190, 120, 190)", ["-y 0", "-t 0", "-m 50"]), + # The maximum hsl values should be between 0 and 100% of their maximum + ("hsl(190, 122, 150)", "hsl(81, 126, 209)", ["-y 100", "-t 100", "-m 100"]), + ] + + opacity_tests = [ + (5, 5), + # The user selected 0% opacity range, and thus the opacity should not change. + (0.15, 0.15, ["-o 0"]), + # The opacity value should be greater than 0 + (0.0, 0.84, ["-o 100"]), + # The opacity value should be lesser than 1 + (1.0, 0.77, ["-o 100"]), + # Other units are available + ("0.5", 0.654, ["-o 54"]), + # test that output is deterministic + ("0.500001", 0.654, ["-o 54"]), + # Test no opacity + # The opacity value should be lesser than 1 + ] + + def test_bad_opacity(self): + """Bad opacity error handled""" + self.effect.modify_opacity("opacity", "hello") + + +class TestRandomizeGradients(ComparisonMixin, TestCase): + """Direct tests for color mechanisms""" + + effect_class = Randomize + compare_file = "svg/colors.svg" + python3_only = True + + comparisons = [ + ( + "-y 50", + "-t 50", + "-m 50", + "-o 100", + "--id=r1", + "--id=r2", + "--id=r3", + "--id=r4", + "--id=r5", + "--id=r6", + ), + ] + + +class TestRandomizeOpacity(ComparisonMixin, TestCase): + """Direct tests for color mechanisms""" + + effect_class = Randomize + compare_file = "svg/dpiswitcher_96dpi.svg" + python3_only = True + + comparisons = [ + ( + "-y 0", + "-t 0", + "-m 0", + "-o 100", + "--id=layer_group_rect_uu2", + "--id=layer_group_path", + "--id=root_rect_uu", + ), + ] diff --git a/share/extensions/tests/test_color_removeblue.py b/share/extensions/tests/test_color_removeblue.py new file mode 100644 index 0000000..2d4c8c6 --- /dev/null +++ b/share/extensions/tests/test_color_removeblue.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_removeblue import RemoveBlue +from .test_inkex_extensions import ColorBaseCase + + +class ColorRemoveBlueTest(ColorBaseCase): + effect_class = RemoveBlue + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffff00"), + ((192, 192, 192), "#c0c000"), + ((128, 128, 128), "#808000"), + ((128, 0, 0), "#800000"), + ((255, 0, 0), "#ff0000"), + ((128, 128, 0), "#808000"), + ((255, 255, 0), "#ffff00"), + ((0, 128, 0), "#008000"), + ((0, 255, 0), "#00ff00"), + ((0, 128, 128), "#008000"), + ((0, 255, 255), "#00ff00"), + ((0, 0, 128), "#000000"), + ((0, 0, 255), "#000000"), + ((128, 0, 128), "#800000"), + ((255, 0, 255), "#ff0000"), + ] diff --git a/share/extensions/tests/test_color_removegreen.py b/share/extensions/tests/test_color_removegreen.py new file mode 100644 index 0000000..a00a4da --- /dev/null +++ b/share/extensions/tests/test_color_removegreen.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_removegreen import RemoveGreen +from .test_inkex_extensions import ColorBaseCase + + +class ColorRemoveGreenTest(ColorBaseCase): + effect_class = RemoveGreen + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ff00ff"), + ((192, 192, 192), "#c000c0"), + ((128, 128, 128), "#800080"), + ((128, 0, 0), "#800000"), + ((255, 0, 0), "#ff0000"), + ((128, 128, 0), "#800000"), + ((255, 255, 0), "#ff0000"), + ((0, 128, 0), "#000000"), + ((0, 255, 0), "#000000"), + ((0, 128, 128), "#000080"), + ((0, 255, 255), "#0000ff"), + ((0, 0, 128), "#000080"), + ((0, 0, 255), "#0000ff"), + ((128, 0, 128), "#800080"), + ((255, 0, 255), "#ff00ff"), + ] diff --git a/share/extensions/tests/test_color_removered.py b/share/extensions/tests/test_color_removered.py new file mode 100644 index 0000000..56758ab --- /dev/null +++ b/share/extensions/tests/test_color_removered.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from color_removered import RemoveRed +from .test_inkex_extensions import ColorBaseCase + + +class ColorRemoveRedTest(ColorBaseCase): + effect_class = RemoveRed + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#00ffff"), + ((192, 192, 192), "#00c0c0"), + ((128, 128, 128), "#008080"), + ((128, 0, 0), "#000000"), + ((255, 0, 0), "#000000"), + ((128, 128, 0), "#008000"), + ((255, 255, 0), "#00ff00"), + ((0, 128, 0), "#008000"), + ((0, 255, 0), "#00ff00"), + ((0, 128, 128), "#008080"), + ((0, 255, 255), "#00ffff"), + ((0, 0, 128), "#000080"), + ((0, 0, 255), "#0000ff"), + ((128, 0, 128), "#000080"), + ((255, 0, 255), "#0000ff"), + ] diff --git a/share/extensions/tests/test_color_replace.py b/share/extensions/tests/test_color_replace.py new file mode 100644 index 0000000..082e8c1 --- /dev/null +++ b/share/extensions/tests/test_color_replace.py @@ -0,0 +1,39 @@ +# coding=utf-8 +from color_replace import ReplaceColor +from .test_inkex_extensions import ColorBaseCase +from inkex import Color +from inkex.tester import ComparisonMixin, TestCase + + +class ColorReplaceTest(ColorBaseCase): + effect_class = ReplaceColor + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#ff0000", []), + ((128, 0, 0), "#800000", []), + ((0, 0, 0), "#696969", ["-t1768516095"]), + ((0, 0, 0), "#000000", ["-f1", "-t1768516095", "-i=False"]), + ((18, 52, 86), "#696969", ["-f305420031", "-t1768516095"]), + ((18, 52, 86), "#ff0000", ["-f305420031"]), + ( + Color([10, 20, 30, 0.2], space="rgba"), + Color([255, 0, 0, 20 / 255], space="rgba"), + ["-f169090611", "-t4278190100"], + ), + ( + Color([10, 20, 30, 0.5], space="rgba"), + Color([10, 20, 30, 0.5], space="rgba"), + ["-f169090611", "-t4278190100", "-i=False"], + ), + ( + Color([10, 20, 30, 0.5], space="rgba"), + Color([255, 0, 0, 20 / 255], space="rgba"), + ["-f169090611", "-t4278190100"], + ), + ] + + +class ColorReplacePatternTest(ComparisonMixin, TestCase): + effect_class = ReplaceColor + compare_file = "svg/simple_patterns.svg" + comparisons = [("--id=rect184",), ("--id=rect184", "--id=rect184-8")] diff --git a/share/extensions/tests/test_color_rgbbarrel.py b/share/extensions/tests/test_color_rgbbarrel.py new file mode 100644 index 0000000..a59d1d9 --- /dev/null +++ b/share/extensions/tests/test_color_rgbbarrel.py @@ -0,0 +1,27 @@ +# coding=utf-8 +from color_rgbbarrel import RgbBarrel +from .test_inkex_extensions import ColorBaseCase + + +class ColorBarrelTest(ColorBaseCase): + effect_class = RgbBarrel + color_tests = [ + ("none", "none"), + ((0, 0, 0), "#000000"), + ((255, 255, 255), "#ffffff"), + ((192, 192, 192), "#c0c0c0"), + ((128, 128, 128), "#808080"), + ((128, 0, 0), "#008000"), + ((255, 0, 0), "#00ff00"), + ((128, 128, 0), "#008080"), + ((255, 255, 0), "#00ffff"), + ((0, 128, 0), "#000080"), + ((0, 255, 0), "#0000ff"), + ((0, 128, 128), "#800080"), + ((0, 255, 255), "#ff00ff"), + ((0, 0, 128), "#800000"), + ((0, 0, 255), "#ff0000"), + ((128, 0, 128), "#808000"), + ((255, 0, 255), "#ffff00"), + ("hsl(25, 14, 128)", "#798681"), + ] diff --git a/share/extensions/tests/test_convert2dashes.py b/share/extensions/tests/test_convert2dashes.py new file mode 100644 index 0000000..1aaa7d4 --- /dev/null +++ b/share/extensions/tests/test_convert2dashes.py @@ -0,0 +1,23 @@ +# coding=utf-8 +from convert2dashes import Dashit +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class DashitBasicTest(ComparisonMixin, TestCase): + comparisons = ([],) + effect_class = Dashit + + def test_basic(self): + args = ["--id=dashme", self.data_file("svg", "dash.svg")] + self.effect.run(args) + old_dashes = ( + self.effect.original_document.getroot().getElement("//svg:path").path + ) + new_dashes = self.effect.svg.getElement("//svg:path").path + assert len(new_dashes) > len(old_dashes) + + +class DashitCommaTest(ComparisonMixin, TestCase): + comparisons = (["--id=dashme2"],) + effect_class = Dashit + compare_file = ["svg/dash.svg", "svg/dash_zerolength.svg"] diff --git a/share/extensions/tests/test_deprecated_simple.py b/share/extensions/tests/test_deprecated_simple.py new file mode 100644 index 0000000..f878ad2 --- /dev/null +++ b/share/extensions/tests/test_deprecated_simple.py @@ -0,0 +1,216 @@ +# coding=utf-8 +"""Test deprecated-simple modules""" +from __future__ import absolute_import, print_function + +import warnings +import math +import os +import re + +from pytest import approx + +import inkex +from inkex.tester import TestCase + + +class DeprecatedTest(TestCase): + """Tests for Deprecated API (Inkscape 0.92 and below)""" + + def setUp(self): + # All the functions in this test suite are deprecated, so + # we don't need the warnings here. + self.warner = warnings.catch_warnings() + self.warner.__enter__() + warnings.simplefilter("ignore", category=DeprecationWarning) + + def tearDown(self): + self.warner.__exit__() + + def test_simple_imports(self): + """Can import each module""" + # TODO add tests for these modules + import bezmisc + import cspsubdiv + import cubicsuperpath + import ffgeom + + # pylint: disable=unused-variable + from inkex import debug, errormsg, localize + + def test_simplepath(self): + """Test simplepath API""" + import simplepath + + data = "M12 34L56 78Z" + path = simplepath.parsePath(data) + self.assertEqual(path, [["M", [12.0, 34.0]], ["L", [56.0, 78.0]], ["Z", []]]) + + d_out = simplepath.formatPath(path) + d_out = d_out.replace(".0", "") + self.assertEqual(data.replace(" ", ""), d_out.replace(" ", "")) + + simplepath.translatePath(path, -3, -4) + self.assertEqual(path, [["M", [9.0, 30.0]], ["L", [53.0, 74.0]], ["Z", []]]) + + simplepath.scalePath(path, 10, 20) + self.assertEqual( + path, [["M", [90.0, 600.0]], ["L", [530.0, 1480.0]], ["Z", []]] + ) + + simplepath.rotatePath(path, math.pi / 2.0, cx=5, cy=7) + approxed = [[code, approx(coords)] for (code, coords) in path] + self.assertEqual( + approxed, [["M", [-588.0, 92.0]], ["L", [-1468.0, 532.0]], ["Z", []]] + ) + + def test_simplepath_shorthand(self): + """simplepath with shorthand notation""" + import simplepath + + data = ( + "M10 20v30V30h40H40c 1 2 3 4 5 6S7 8 9 10s7 8 9 10q11 12 13 14t15 16T15 16" + ) + path = simplepath.parsePath(data) + self.assertEqual( + path, + [ + ["M", [10.0, 20.0]], + ["L", [10.0, 50.0]], + ["L", [10.0, 30.0]], + ["L", [50.0, 30.0]], + ["L", [40.0, 30.0]], + ["C", [41.0, 32.0, 43.0, 34.0, 45.0, 36.0]], + ["C", [47.0, 38.0, 7.0, 8.0, 9.0, 10.0]], + ["C", [11.0, 12.0, 16.0, 18.0, 18.0, 20.0]], + ["Q", [29.0, 32.0, 31.0, 34.0]], + ["Q", [33.0, 36.0, 46.0, 50.0]], + ["Q", [59.0, 64.0, 15.0, 16.0]], + ], + ) + + def test_simplestyle(self): + """Test simplestyle API""" + import simplestyle + + self.assertEqual(simplestyle.svgcolors["blue"], "#0000ff") + self.assertEqual( + simplestyle.parseStyle("foo: bar; abc-def: 123em"), + {"foo": "bar", "abc-def": "123em"}, + ) + self.assertEqual(simplestyle.formatStyle({"foo": "bar"}), "foo:bar") + self.assertTrue(simplestyle.isColor("#ff0000")) + self.assertTrue(simplestyle.isColor("#f00")) + self.assertTrue(simplestyle.isColor("blue")) + self.assertFalse(simplestyle.isColor("none")) + self.assertFalse(simplestyle.isColor("nosuchcolor")) + self.assertEqual(simplestyle.parseColor("#0000ff"), (0, 0, 0xFF)) + self.assertEqual(simplestyle.parseColor("red"), (0xFF, 0, 0)) + self.assertEqual(simplestyle.formatColoria([0, 0x99, 0]), "#009900") + self.assertEqual(simplestyle.formatColor3i(0, 0x99, 0), "#009900") + self.assertEqual(simplestyle.formatColorfa([0, 1.0, 0]), "#00ff00") + self.assertEqual(simplestyle.formatColor3f(0, 1.0, 0), "#00ff00") + + def test_simpletransform(self): + """Test simpletransform API""" + import simpletransform + + self.assertEqual( + simpletransform.parseTransform("scale(10)"), [[10, 0, 0], [0, 10, 0]] + ) + self.assertEqual( + simpletransform.parseTransform("translate(2,3)"), [[1, 0, 2], [0, 1, 3]] + ) + self.assertEqual( + simpletransform.parseTransform("translate(2,3) rotate(90)"), + [approx([0, -1, 2]), approx([1, 0, 3])], + ) + m = simpletransform.formatTransform([[0, -1, 2], [1, 0, 3]]) + self.assertEqual( + re.sub(r",", " ", re.sub(r"\.0*\b", "", m)), "matrix(0 1 -1 0 2 3)" + ) + self.assertEqual( + simpletransform.invertTransform([[1, 0, 2], [0, 1, 3]]), + [[1, 0, -2], [0, 1, -3]], + ) + self.assertEqual( + simpletransform.composeTransform( + [[1, 0, 2], [0, 1, 3]], [[0, -1, 0], [1, 0, 0]] + ), + [[0, -1, 2], [1, 0, 3]], + ) + + pt = [4, 5] + self.assertEqual( + simpletransform.applyTransformToPoint([[0, -1, 2], [1, 0, 3]], pt), None + ) + self.assertEqual(pt, [-3, 7]) + + self.assertEqual( + simpletransform.boxunion([3, 5, 2, 4], [4, 6, 1, 3]), (3, 6, 1, 4) + ) + self.assertEqual(simpletransform.cubicExtrema(1, 2, 3, 4), (1, 4)) + + # TODO need cubic superpath + self.assertTrue(simpletransform.applyTransformToPath) + self.assertTrue(simpletransform.roughBBox) + self.assertTrue(simpletransform.refinedBBox) + + # TODO need node + self.assertTrue(simpletransform.fuseTransform) + self.assertTrue(simpletransform.composeParents) + self.assertTrue(simpletransform.applyTransformToNode) + self.assertTrue(simpletransform.computeBBox) + self.assertTrue(simpletransform.computePointInNode) + + def test_inkex_effect(self): + """Test original Effect base class""" + from inkex import Effect + + args = [ + "--id", + "curve", + os.path.join(os.path.dirname(__file__), "data", "svg/curves.svg"), + ] + + e = Effect() + e.affect(args) + + # assigned in __init__ + self.assertNotEqual(e.document.getroot(), None) + self.assertTrue(isinstance(e.selected, dict)) + self.assertEqual(list(e.selected), ["curve"]) + self.assertTrue(isinstance(e.doc_ids, dict)) + self.assertTrue(isinstance(e.options.ids, list)) + self.assertEqual(e.args, args[-1:]) + self.assertNotEqual(e.OptionParser.add_option, None) + + # methods + self.assertEqual(e.getselected(), None) + self.assertEqual(e.getdocids(), None) + node = e.getElementById("arc") + self.assertEqual(node.tag, "{http://www.w3.org/2000/svg}path") + self.assertEqual(node.get("id"), "arc") + self.assertEqual(e.getParentNode(node).tag, "{http://www.w3.org/2000/svg}g") + self.assertEqual( + e.getNamedView().tag, + "{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}namedview", + ) + self.assertEqual( + e.createGuide(10, 20, 45).tag, + "{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}guide", + ) + self.assertTrue(e.uniqueId("foo").startswith("foo")) + self.assertEqual( + e.xpathSingle("//svg:path").tag, "{http://www.w3.org/2000/svg}path" + ) + self.assertEqual(e.getDocumentWidth(), "1000") + self.assertEqual(e.getDocumentHeight(), "1000") + self.assertEqual(e.getDocumentUnit(), "px") + self.assertEqual(e.unittouu("1in"), 96) + self.assertEqual(e.uutounit(192, "in"), 2) + self.assertEqual(e.addDocumentUnit("3"), "3px") + + # skip: + # - e.ctx + # - e.getposinlayer + # - e.original_document diff --git a/share/extensions/tests/test_dhw_input.py b/share/extensions/tests/test_dhw_input.py new file mode 100644 index 0000000..facf02a --- /dev/null +++ b/share/extensions/tests/test_dhw_input.py @@ -0,0 +1,18 @@ +# coding=utf-8 + +from dhw_input import DhwInput + +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class TestDxfInput(ComparisonMixin, TestCase): + effect_class = DhwInput + compare_file = [ + "io/PAGE_001.DHW", + "io/PGLT_161.DHW", + "io/PGLT_162.DHW", + "io/PGLT_163.DHW", + ] + compare_filters = [CompareNumericFuzzy()] + comparisons = [()] diff --git a/share/extensions/tests/test_dimension.py b/share/extensions/tests/test_dimension.py new file mode 100644 index 0000000..34af0d3 --- /dev/null +++ b/share/extensions/tests/test_dimension.py @@ -0,0 +1,17 @@ +# coding=utf-8 +from dimension import Dimension +from inkex.tester import ComparisonMixin, TestCase + + +class TestDimensionBasic(ComparisonMixin, TestCase): + effect_class = Dimension + comparisons = [ + ("--id=p1", "--id=r3", "--xoffset=100.0", "--yoffset=100.0"), + ("--id=p1", "--id=r3", "--type=visual", "--xoffset=100.0", "--yoffset=100.0"), + ] + + +class TestDimensionMillimeters(ComparisonMixin, TestCase): + effect_class = Dimension + compare_file = "svg/css.svg" + comparisons = [("--id=circle1",)] diff --git a/share/extensions/tests/test_doc_ai_convert.py b/share/extensions/tests/test_doc_ai_convert.py new file mode 100644 index 0000000..91ccf69 --- /dev/null +++ b/share/extensions/tests/test_doc_ai_convert.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding=utf-8 + +from doc_ai_convert import DocAiConvert +from inkex.tester import ComparisonMixin, TestCase + + +class DocAIConvertTest(ComparisonMixin, TestCase): + effect_class = DocAiConvert + compare_file = [ + "svg/shapes.svg", + "svg/doc_ai_conv_mm_in.svg", + "svg/doc_ai_conv_m_in.svg", + ] + comparisons = [()] diff --git a/share/extensions/tests/test_docinfo.py b/share/extensions/tests/test_docinfo.py new file mode 100644 index 0000000..bbf0b7c --- /dev/null +++ b/share/extensions/tests/test_docinfo.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from docinfo import DocInfo +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import WindowsTextCompat + + +class TestDocInfo(ComparisonMixin, TestCase): + compare_file = ["svg/guides.svg", "svg/three_pages_and_two_grids.svg"] + effect_class = DocInfo + stderr_output = True + comparisons = [()] + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_dpiswitcher.py b/share/extensions/tests/test_dpiswitcher.py new file mode 100644 index 0000000..923bcfd --- /dev/null +++ b/share/extensions/tests/test_dpiswitcher.py @@ -0,0 +1,33 @@ +# coding=utf-8 +""" +Tests for DPISwitcher extensions + +python3 -m pytest tests/test_dpiswitcher.py + +Generate references: +python3 dpiswitcher.py tests/data/svg/shapes.svg > tests/data/refs/dpiswitcher.out +python3 dpiswitcher.py --switcher=0 tests/data/svg/dpiswitcher_96dpi.svg > + tests/data/refs/dpiswitcher__--switcher__0.out +python3 dpiswitcher.py --switcher=1 tests/data/svg/dpiswitcher_96dpi.svg > + tests/data/refs/dpiswitcher__--switcher__1.out + +""" +from dpiswitcher import DPISwitcher +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class TestDPISwitcherBasic(ComparisonMixin, TestCase): + """Default Test with shapes.svg""" + + effect_class = DPISwitcher + compare_filters = [CompareNumericFuzzy()] + + +class TestDPIto90to96(ComparisonMixin, TestCase): + """Test file with transformed objects in root""" + + compare_file = "svg/dpiswitcher_96dpi.svg" + comparisons = [("--switcher=0",), ("--switcher=1",)] + compare_filters = [CompareNumericFuzzy()] + effect_class = DPISwitcher diff --git a/share/extensions/tests/test_draw_from_triangle.py b/share/extensions/tests/test_draw_from_triangle.py new file mode 100644 index 0000000..4c092ae --- /dev/null +++ b/share/extensions/tests/test_draw_from_triangle.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from draw_from_triangle import DrawFromTriangle +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class DrawFromTriangleBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = DrawFromTriangle + comparisons = [ + ("--id=p1", "--id=r3"), + ] diff --git a/share/extensions/tests/test_dxf12_outlines.py b/share/extensions/tests/test_dxf12_outlines.py new file mode 100644 index 0000000..5c231c6 --- /dev/null +++ b/share/extensions/tests/test_dxf12_outlines.py @@ -0,0 +1,17 @@ +# coding=utf-8 +from dxf12_outlines import DxfTwelve +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import WindowsTextCompat + + +class TestDXF12OutlinesBasic(ComparisonMixin, TestCase): + compare_file = [ + "svg/shapes.svg", + "svg/preserved-transforms.svg", + "svg/dxf_nested_transforms.svg", + "svg/clips_and_masks.svg", + "svg/scale_not_unity.svg", + ] + comparisons = [()] + effect_class = DxfTwelve + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_dxf_input.py b/share/extensions/tests/test_dxf_input.py new file mode 100644 index 0000000..2f4bcbb --- /dev/null +++ b/share/extensions/tests/test_dxf_input.py @@ -0,0 +1,71 @@ +# coding=utf-8 + +from dxf_input import DxfInput + +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class TestDxfInputBasic(ComparisonMixin, TestCase): + compare_file = [ + "io/test_r12.dxf", + "io/test_r14.dxf", + # Unit test for https://gitlab.com/inkscape/extensions/-/issues/355 + "io/dxf_with_arc.dxf", + # test polylines + "io/dxf_polylines.dxf", + # File missing a BLOCKS session + "io/no_block_section.dxf", + # test placement of graphical objects from BLOCKS section + # ellipses currently are too large + "io/dxf_multiple_inserts.dxf", + # test correct colors generated + # currently BYLAYER and BYBLOCK colors in inserted block are wrong + "io/color.dxf", + ] + compare_filters = [CompareNumericFuzzy()] + comparisons = [()] + effect_class = DxfInput + + def _apply_compare_filters(self, data, is_saving=None): + """Remove the full pathnames""" + if is_saving is True: + return data + data = super()._apply_compare_filters(data) + return data.replace((self.datadir() + "/").encode("utf-8"), b"") + + +class TestDxfInputBasicError(ComparisonMixin, TestCase): + TestCase.stderr_protect = False + # sample uses POLYLINE,TEXT (R12), LWPOLYLINE,MTEXT (R13, R14) + # however has warnings when handling points with a display mode + compare_file = [ + "io/test2_r12.dxf", + "io/test2_r13.dxf", + "io/test2_r14.dxf", + "io/test_extrude.dxf", + ] + compare_filters = [CompareNumericFuzzy()] + comparisons = [()] + effect_class = DxfInput + + def _apply_compare_filters(self, data, is_saving=None): + """Remove the full pathnames""" + if is_saving is True: + return data + data = super()._apply_compare_filters(data) + return data.replace((self.datadir() + "/").encode("utf-8"), b"") + + +class TestDxfInputTextHeight(ComparisonMixin, TestCase): + compare_file = ["io/CADTextHeight.dxf"] + compare_filters = [CompareNumericFuzzy()] + comparisons = [(), ("--textscale=1.411",)] + effect_class = DxfInput + + def _apply_compare_filters(self, data, is_saving=None): + """Remove the full pathnames""" + if is_saving is True: + return data + data = super()._apply_compare_filters(data) + return data.replace((self.datadir() + "/").encode("utf-8"), b"") diff --git a/share/extensions/tests/test_dxf_outlines.py b/share/extensions/tests/test_dxf_outlines.py new file mode 100644 index 0000000..9639c28 --- /dev/null +++ b/share/extensions/tests/test_dxf_outlines.py @@ -0,0 +1,76 @@ +# coding=utf-8 +from io import BytesIO +from dxf_outlines import DxfOutlines +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import WindowsTextCompat +from inkex.elements._parser import load_svg + +from inkex.utils import AbortExtension +from inkex.base import SvgOutputMixin +from inkex.elements import Rectangle + + +class DFXOutlineBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = DxfOutlines + comparisons = [ + (), + ("--id=p1", "--id=r3"), + ("--POLY=true",), + ("--ROBO=true",), + ] + compare_filters = [WindowsTextCompat()] + + +def run_extension(document, *args) -> str: + output = BytesIO() + ext = DxfOutlines() + ext.parse_arguments([*args]) + ext.svg = document.getroot() + ext.document = document + ext.effect() + ext.save(output) + output.seek(0) + return output.read() + + +class DXFDeeplyNestedTest(TestCase): + """Check that a deeply nested SVG raises an AbortExtension""" + + @staticmethod + def create_deep_svg(amount): + """Create a very deep svg and test getting ancestors""" + svg = '' + for i in range(amount): + svg += f'' + svg = load_svg(svg + ("" * amount) + "") + return svg + + def test_deeply_nested(self): + "Run test" + with self.assertRaisesRegex(AbortExtension, "Deep Ungroup"): + run_extension(self.create_deep_svg(1500)) + + +class TestDxfUnits(TestCase): + """Test ensuring that units work properly""" + + def test_mm(self): + """Test that the documents created with/without scaling and base units are + identical.""" + document = SvgOutputMixin.get_template(width=210, height=297, unit="mm") + document.getroot().namedview.set("inkscape:document-units", "mm") + document.getroot().add(Rectangle.new(200, 0, 10, 16)) + out1 = run_extension(document) + + document = SvgOutputMixin.get_template(width=210, height=297, unit="mm") + document.getroot().add(Rectangle.new(200, 0, 10, 16)) + out2 = run_extension(document, "--unit_from_document=False", "--units=mm") + + self.assertEqual(out1, out2) + # Now with scaling - should result in the same document + document = SvgOutputMixin.get_template(width=210, height=297, unit="mm") + document.getroot().set("viewBox", "0 0 105 148.5") + document.getroot().add(Rectangle.new(100, 0, 5, 8)) + out3 = run_extension(document, "--unit_from_document=False", "--units=mm") + + self.assertEqual(out1, out3) diff --git a/share/extensions/tests/test_edge3d.py b/share/extensions/tests/test_edge3d.py new file mode 100644 index 0000000..ad1dce2 --- /dev/null +++ b/share/extensions/tests/test_edge3d.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# coding=utf-8 +import inkex +from edge3d import Edge3D +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class Edge3dBasicTest(ComparisonMixin, TestCase): + effect_class = Edge3D + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [ + ("--id=p1", "--id=r3"), + ] + + def test_basic(self): + args = ["--id=edgeme", self.data_file("svg", "edge3d.svg")] + self.effect.run(args) + old_paths = self.effect.original_document.getroot().xpath( + '//svg:path[@id="edgeme"]' + ) + new_paths = self.effect.svg.xpath('//svg:path[@id="edgeme"]') + self.assertEqual(len(old_paths), 1) + self.assertEqual(len(new_paths), 1) + old_paths = self.effect.original_document.getroot().xpath("//svg:path") + new_paths = self.effect.svg.xpath("//svg:path") + self.assertEqual(len(old_paths), 1) + self.assertEqual(len(new_paths), 4) diff --git a/share/extensions/tests/test_export_gimp_palette.py b/share/extensions/tests/test_export_gimp_palette.py new file mode 100644 index 0000000..b81cbc9 --- /dev/null +++ b/share/extensions/tests/test_export_gimp_palette.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from export_gimp_palette import ExportGimpPalette +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import WindowsTextCompat + + +class TestExportGplBasic(ComparisonMixin, TestCase): + effect_class = ExportGimpPalette + compare_file = "svg/colors.svg" + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_extrude.py b/share/extensions/tests/test_extrude.py new file mode 100644 index 0000000..7c38c38 --- /dev/null +++ b/share/extensions/tests/test_extrude.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# coding=utf-8 +from extrude import Extrude +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import ( + CompareOrderIndependentStyleAndPath, + CompareWithPathSpace, +) + + +class ExtrudeBasicTest(ComparisonMixin, TestCase): + effect_class = Extrude + comparisons = [("--id=p1", "--id=p2")] + compare_filters = [CompareWithPathSpace(), CompareOrderIndependentStyleAndPath()] + + +class ExtrudeCircleTest(ComparisonMixin, TestCase): + effect_class = Extrude + compare_file = "svg/extrude.svg" + comparisons = [ + ("--id=c1", "--id=c2"), + ("--id=c1", "--id=c2", "-m=snug"), + ("--id=c1", "--id=c2", "-m=polygons"), + ] + + +class ExtrudePathConversionTest(ComparisonMixin, TestCase): + effect_class = Extrude + compare_file = "svg/extrude.svg" + comparisons = [ + ("--id=r1", "--id=r2"), + ("--id=r1", "--id=r2", "-s=False"), + ("--id=r1", "--id=r2", "-m=snug"), + ] + + +class ExtrudeOpenPathTest(ComparisonMixin, TestCase): + effect_class = Extrude + compare_file = "svg/extrude.svg" + comparisons = [ + ("--id=p1", "--id=p2", "-m=lines"), + ("--id=p1", "--id=p2", "-m=snug"), + ] + + +class ExtrudeMultipleSubpathTest(ComparisonMixin, TestCase): + effect_class = Extrude + compare_file = "svg/extrude.svg" + comparisons = [ + ("--id=p3", "--id=p4", "-m=snug"), + ("--id=p3", "--id=p4", "-m=lines"), + ("--id=p3", "--id=p4", "-m=polygons"), + ] diff --git a/share/extensions/tests/test_fig_input.py b/share/extensions/tests/test_fig_input.py new file mode 100644 index 0000000..f1c1718 --- /dev/null +++ b/share/extensions/tests/test_fig_input.py @@ -0,0 +1,11 @@ +# coding=utf-8 + +from fig_input import FigInput + +from inkex.tester import ComparisonMixin, TestCase + + +class TestFigInput(ComparisonMixin, TestCase): + effect_class = FigInput + compare_file = "io/test.fig" + comparisons = [()] diff --git a/share/extensions/tests/test_flatten.py b/share/extensions/tests/test_flatten.py new file mode 100644 index 0000000..f0a32ce --- /dev/null +++ b/share/extensions/tests/test_flatten.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from flatten import Flatten +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class FlattenBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + effect_class = Flatten diff --git a/share/extensions/tests/test_foldablebox.py b/share/extensions/tests/test_foldablebox.py new file mode 100644 index 0000000..48990d4 --- /dev/null +++ b/share/extensions/tests/test_foldablebox.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from foldablebox import FoldableBox +from inkex.tester import ComparisonMixin, TestCase + + +class FoldableBoxArguments(ComparisonMixin, TestCase): + effect_class = FoldableBox + compare_file = "svg/empty.svg" + comparisons = [ + ("--width=20", "--height=20", "--depth=2.2", "--unit=cm"), + ("--proportion=0.5", "--guide=true", "--unit=cm"), + ] diff --git a/share/extensions/tests/test_fractalize.py b/share/extensions/tests/test_fractalize.py new file mode 100644 index 0000000..f705e28 --- /dev/null +++ b/share/extensions/tests/test_fractalize.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from fractalize import Fractalize +from inkex.tester import ComparisonMixin, TestCase + + +class PathFractalizeBasicTest(ComparisonMixin, TestCase): + effect_class = Fractalize + comparisons = [("--id=p1", "--id=p2")] diff --git a/share/extensions/tests/test_frame.py b/share/extensions/tests/test_frame.py new file mode 100644 index 0000000..db97e3f --- /dev/null +++ b/share/extensions/tests/test_frame.py @@ -0,0 +1,200 @@ +# coding=utf-8 +# +# Copyright (C) 2016 Richard White, rwhite8282@gmail.com +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" +An Inkscape frame extension test class. +""" +from __future__ import absolute_import, print_function, unicode_literals + +import inkex +from frame import Frame +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class FrameTest(TestCase): + """tests for the Frame extension""" + + effect_class = Frame + + @staticmethod + def get_frame(svg): + """Find the frame in the document tree""" + return svg.getElement( + '//svg:g[@id="layer1"]//svg:rect[@inkscape:label="Frame"] | ' + '//svg:g[@id="layer1"]//svg:ellipse[@inkscape:label="Frame"]' + ) + + def test_single_frame(self): + """Test a simple frame.""" + args = [ + "--corner_radius=20", + "--fill_color=-16777124", + "--id=rect3006", + "--z_position=top", + "--stroke_color=255", + '--tab="stroke"', + "--width=10", + self.data_file("svg", "single_box.svg"), + ] + uut = Frame() + uut.run(args) + new_frame = self.get_frame(uut.svg) + self.assertIsNotNone(new_frame) + self.assertEqual("{http://www.w3.org/2000/svg}rect", new_frame.tag) + new_frame_style = new_frame.attrib["style"].lower() + self.assertTrue( + "fill-opacity:0.36" in new_frame_style, + 'Invalid fill-opacity in "' + new_frame_style + '".', + ) + self.assertTrue( + "stroke:#000000" in new_frame_style, + 'Invalid stroke in "' + new_frame_style + '".', + ) + self.assertTrue( + "stroke-width:10.0" in new_frame_style, + 'Invalid stroke-width in "' + new_frame_style + '".', + ) + self.assertTrue( + "fill:#ff0000" in new_frame_style, + 'Invalid fill in "' + new_frame_style + '".', + ) + + def test_single_frame_grouped(self): + """Test a grouped frame""" + args = [ + "--corner_radius=20", + "--fill_color=-16777124", + "--group=True", + "--id=rect3006", + "--z_position=top", + "--stroke_color=255", + '--tab="stroke"', + "--width=10", + self.data_file("svg", "single_box.svg"), + ] + uut = Frame() + uut.run(args) + new_frame = self.get_frame(uut.svg) + self.assertIsNotNone(new_frame) + self.assertEqual("{http://www.w3.org/2000/svg}rect", new_frame.tag) + group = new_frame.getparent() + self.assertEqual("{http://www.w3.org/2000/svg}g", group.tag) + self.assertEqual("{http://www.w3.org/2000/svg}rect", group[0].tag) + self.assertEqual("{http://www.w3.org/2000/svg}rect", group[1].tag) + self.assertEqual("Frame", group[1].label) + + def test_single_frame_clipped(self): + """Test a clipped frame""" + uut = self.assertEffect( + "svg", + "single_box.svg", + clip=True, + corner_radius=20, + fill_color=-16777124, + id="rect3006", + stroke_color=255, + tab="stroke", + width=10, + ) + new_frame = self.get_frame(uut.svg) + self.assertIsNotNone(new_frame) + self.assertEqual("{http://www.w3.org/2000/svg}rect", new_frame.tag) + orig = list(uut.svg.selection.values())[0] + self.assertEqual("url(#clipPath5815)", orig.get("clip-path")) + clip_path = uut.svg.getElement("//svg:defs/svg:clipPath") + self.assertEqual("{http://www.w3.org/2000/svg}clipPath", clip_path.tag) + + def test_frame_split(self): + """Test a frame that is split between bottom and top""" + args = [ + "--type=ellipse", + "--fill_color=#AAA", + "--group=True", + "--id=rect3006", + "--z_position=split", + "--stroke_color=#F00", + "--offset_relative=-10", + "--width=2", + self.data_file("svg", "single_box.svg"), + ] + uut = Frame() + uut.run(args) + new_frame = self.get_frame(uut.svg) + top_frame = new_frame.getparent()[2] + self.assertIsNotNone(new_frame) + self.assertIsInstance(new_frame, inkex.Ellipse) + self.assertIsInstance(new_frame.getparent(), inkex.Group) + self.assertIsInstance(new_frame.getparent()[1], inkex.Rectangle) + self.assertIsInstance(top_frame, inkex.Ellipse) + + self.assertIn("stroke", top_frame.style) + self.assertNotIn("stroke", new_frame.style) + self.assertIn("fill", top_frame.style) + self.assertEqual(top_frame.style("fill"), None) + + +class TestFrameInOut(ComparisonMixin, TestCase): + """Test some full runs of Frame""" + + effect_class = Frame + comparisons = [ + ( # test relative offset + "--id=c2", + "--id=c1", + "--type=ellipse", + "--offset_relative=10", + "--fill_color=#AAA", + "--stroke_color=#F00", + "--z_position=split", + ), + ( # test absolute offset + "--id=c2", + "--id=c1", + "--type=ellipse", + "--offset_absolute=20", + "--fill_color=#AAA", + "--stroke_color=#F00", + "--z_position=split", + ), + ( # test asgroup + "--id=c2", + "--id=c1", + "--id=p1", + "--type=rect", + "--group=True", + "--asgroup=True", + "--offset_relative=-10", + "--fill_color=#AAA", + "--stroke_color=#F00", + "--z_position=bottom", + "--clip=True", + ), + ( # test text bbox querying + "--id=t3", + "--type=rect", + "--offset_relative=10", + "--fill_color=#AAA", + "--stroke_color=#F00", + "--z_position=split", + ), + ( # Test clip on a transformed element + "--id=u1", + "--fill_color=#AAA", + "--stroke_color=#F00", + "--clip=True", + ), + ] diff --git a/share/extensions/tests/test_funcplot.py b/share/extensions/tests/test_funcplot.py new file mode 100644 index 0000000..c76f121 --- /dev/null +++ b/share/extensions/tests/test_funcplot.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from funcplot import FuncPlot, math_eval +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy +import math + + +class FuncPlotBasicTest(ComparisonMixin, TestCase): + effect_class = FuncPlot + compare_filters = [CompareNumericFuzzy()] + comparisons = [ + ("--id=p1", "--id=r3", "--times2pi=True", "--ybottom=-1.0", "--drawaxis=True"), + ] diff --git a/share/extensions/tests/test_generate_voronoi.py b/share/extensions/tests/test_generate_voronoi.py new file mode 100644 index 0000000..2b0711f --- /dev/null +++ b/share/extensions/tests/test_generate_voronoi.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from generate_voronoi import GenerateVoronoi +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class TestPatternBasic(ComparisonMixin, TestCase): + effect_class = GenerateVoronoi + comparisons = [ + ("--id=r3", "--id=p1"), + ] + compare_filters = [CompareOrderIndependentStyle()] diff --git a/share/extensions/tests/test_gimp_xcf.py b/share/extensions/tests/test_gimp_xcf.py new file mode 100644 index 0000000..ee70ea8 --- /dev/null +++ b/share/extensions/tests/test_gimp_xcf.py @@ -0,0 +1,26 @@ +# coding=utf-8 +""" +Unit test file for ../gimp_xcf.py +Revision history: + * 2012-01-26 (jazzynico): checks defaulf parameters and file handling. +""" + +from gimp_xcf import GimpXcf +from inkex.tester import ComparisonMixin, TestCase + + +class GimpXcfBasicTest(ComparisonMixin, TestCase): + """Test the Gimp XCF file saving functionality""" + + effect_class = GimpXcf + comparisons = [()] + + +class GimpXcfGuidesTest(ComparisonMixin, TestCase): + """Test that Gimp XCF output can include guides and grids""" + + effect_class = GimpXcf + compare_file = "svg/guides.svg" + comparisons = [ + ("-d=true", "-r=true"), + ] diff --git a/share/extensions/tests/test_grid_cartesian.py b/share/extensions/tests/test_grid_cartesian.py new file mode 100644 index 0000000..cdd8fd1 --- /dev/null +++ b/share/extensions/tests/test_grid_cartesian.py @@ -0,0 +1,31 @@ +# coding=utf-8 +from grid_cartesian import GridCartesian +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class GridCartesianBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = GridCartesian + compare_filters = [CompareOrderIndependentStyle()] + old_defaults = [ + "--border_th=3", + "--border_th_unit=cm", + "--dx=100.0", + "--dx_unit=cm", + "--x_subdivs=2", + "--x_subsubdivs=5", + "--x_half_freq=4", + "--x_divs_th=2", + "--x_subdivs_th=1", + "--x_div_unit=cm", + "--dy=100.0", + "--dy_unit=cm", + "--y_half_freq=4", + "--y_divs_th=2", + "--y_subdivs_th=1", + "--y_div_unit=cm", + ] + comparisons = [ + tuple(old_defaults), + tuple(old_defaults + ["--id=p1", "--id=r3"]), + ] diff --git a/share/extensions/tests/test_grid_isometric.py b/share/extensions/tests/test_grid_isometric.py new file mode 100644 index 0000000..19be08f --- /dev/null +++ b/share/extensions/tests/test_grid_isometric.py @@ -0,0 +1,11 @@ +# coding=utf-8 + +from grid_isometric import GridIsometric +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle, CompareWithPathSpace + + +class TestGridIsometricBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + compare_filters = [CompareOrderIndependentStyle(), CompareWithPathSpace()] + effect_class = GridIsometric + comparisons = [("--dx=10.0", "--subdivs_th=1", "--subsubdivs_th=0.3")] diff --git a/share/extensions/tests/test_grid_polar.py b/share/extensions/tests/test_grid_polar.py new file mode 100644 index 0000000..3a52452 --- /dev/null +++ b/share/extensions/tests/test_grid_polar.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from grid_polar import GridPolar +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class GridPolarBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + compare_filters = [CompareOrderIndependentStyle()] + effect_class = GridPolar + comparisons = [ + ("--a_subdivs_cent=1", "--a_labels=deg"), + ("--id=p1", "--id=r3", "--a_subdivs_cent=1", "--a_labels=deg"), + ] diff --git a/share/extensions/tests/test_guides_creator.py b/share/extensions/tests/test_guides_creator.py new file mode 100644 index 0000000..4bb66b1 --- /dev/null +++ b/share/extensions/tests/test_guides_creator.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# coding=utf-8 +from guides_creator import GuidesCreator +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class GuidesCreatorBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + """Basic tests for GuidesCreator""" + + effect_class = GuidesCreator + compare_file = "svg/guides.svg" + compare_filters = [ + CompareNumericFuzzy(), + ] + old_defaults = ( + "--vertical_guides=3", + "--ul=True", + "--ur=True", + "--ll=True", + "--lr=True", + "--header_margin=6", + "--footer_margin=6", + "--left_margin=6", + "--right_margin=6", + ) + comparisons = [ + old_defaults + ("--tab=regular_guides", "--guides_preset=custom"), + old_defaults + + ("--tab=regular_guides", "--guides_preset=golden", "--delete=True"), + old_defaults + + ("--tab=regular_guides", "--guides_preset=5;5", "--start_from_edges=True"), + old_defaults + ("--tab=diagonal_guides", "--nodup=False"), + old_defaults + + ("--tab=margins", "--start_from_edges=True", "--margins_preset=custom"), + old_defaults + + ("--tab=margins", "--start_from_edges=True", "--margins_preset=book_left"), + old_defaults + + ("--tab=margins", "--start_from_edges=True", "--margins_preset=book_right"), + ] + + +class GuidesCreatorMillimeterTest(ComparisonMixin, TestCase): + """Test that guides are correctly created in a mm based document""" + + effect_class = GuidesCreator + compare_file = "svg/complextransform.test.svg" + compare_filters = [CompareNumericFuzzy()] + comparisons = [ + ("--vertical_guides=6", "--horizontal_guides=8"), + ("--tab=regular_guides", "--start_from_edges=True", "--guides_preset=golden"), + ( + "--tab=regular_guides", + "--start_from_edges=True", + "--guides_preset=custom", + "--vertical_guides=4", + "--horizontal_guides=5", + ), + ( + "--tab=margins", + "--start_from_edges=False", + "--margins_preset=book_right", + "--vert=3", + "--horz=2", + ), + ] + + +class GuidesTestMulitpage(ComparisonMixin, TestCase): + """Test multipage functionality""" + + effect_class = GuidesCreator + compare_file = "svg/empty_multipage.svg" + compare_filters = [CompareNumericFuzzy()] + comparisons = [ + (), # by default, all pages + # selection of pages + ("--vertical_guides=4", "--horizontal_guides=3", "--pages=1,,3-7,12"), + # diagonal guides + ( + "--tab=diagonal_guides", + "--nodup=False", + "--pages=1-3", + "--ul=True", + "--ur=True", + "--ll=True", + "--lr=True", + ), + # There is one diagonal guide already in the file, it should be unchanged + ( + "--tab=diagonal_guides", + "--nodup=True", + "--pages=1-3", + "--ul=True", + "--ur=True", + "--ll=True", + "--lr=True", + ), + ( + "--tab=margins", + "--start_from_edges=True", + "--margins_preset=book_alternating_left", + ), + ( + "--tab=margins", + "--start_from_edges=False", + "--margins_preset=book_alternating_right", + ), + ] diff --git a/share/extensions/tests/test_guillotine.py b/share/extensions/tests/test_guillotine.py new file mode 100644 index 0000000..b4ec342 --- /dev/null +++ b/share/extensions/tests/test_guillotine.py @@ -0,0 +1,75 @@ +# coding=utf-8 +import os +import tarfile +from guillotine import Guillotine +from inkex.tester import ComparisonMixin, TestCase + + +class GuillotineTester(ComparisonMixin): + """Test the Guillotine extension""" + + effect_class = Guillotine + + def test_all_comparisons(self): + """Images are extracted to a file directory""" + for args in self.comparisons: + # Create a landing directory for generated images + outdir = os.path.join(self.tempdir, "img") + args += ("--directory={}/".format(outdir),) + + # But also set this directory into the compare file + compare_file = os.path.join(self.tempdir, "compare_file.svg") + with open(self.data_file(self.compare_file), "rb") as rhl: + with open(compare_file, "wb") as whl: + whl.write(rhl.read().replace(b"{tempdir}", outdir.encode("utf8"))) + + self.assertEffect(compare_file, args=args) + self.assertTrue(os.path.isdir(outdir)) + + infile = self.get_compare_cmpfile(args) + if os.environ.get("EXPORT_COMPARE", False): + self.export_comparison(outdir, infile) + + with tarfile.open(infile) as tar_handle: + for item in tar_handle: + fileobj = tar_handle.extractfile(item) + with open(os.path.join(outdir, item.name), "rb") as fhl: + self.assertEqual( + fileobj.read(), fhl.read(), "File '{}'".format(item.name) + ) + + @staticmethod + def export_comparison(outdir, cmpfile): + """Export the files as a tar file for manual comparison""" + tarname = cmpfile + ".export" + tar = tarfile.open(tarname, "w|") + + # We make a tar archive so we can test it. + for name in sorted(os.listdir(outdir)): + with open(os.path.join(outdir, name), "rb") as fhl: + fhl.seek(0, 2) + info = tarfile.TarInfo(name) + info.size = fhl.tell() + fhl.seek(0) + tar.addfile(info, fhl) + tar.close() + print("Written output: {}.export".format(cmpfile)) + + +class TestGuillotineBasic(GuillotineTester, TestCase): + stderr_protect = False + effect_class = Guillotine + compare_file = "svg/guides.svg" + comparisons = [ + ("--image=f{}oo",), + ("--ignore=true",), + ] + + +class TestGuillotineMillimeter(GuillotineTester, TestCase): + stderr_protect = False + effect_class = Guillotine + compare_file = "svg/guides_millimeter.svg" + comparisons = [ + ("--image=output",), + ] diff --git a/share/extensions/tests/test_handles.py b/share/extensions/tests/test_handles.py new file mode 100644 index 0000000..e6492f5 --- /dev/null +++ b/share/extensions/tests/test_handles.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# coding=utf-8 +from handles import Handles +from inkex.tester import ComparisonMixin, TestCase + + +class HandlesBasicTest(ComparisonMixin, TestCase): + effect_class = Handles + compare_file = "svg/curves.svg" + comparisons = (("--id=curve", "--id=quad"),) diff --git a/share/extensions/tests/test_hershey.py b/share/extensions/tests/test_hershey.py new file mode 100644 index 0000000..f698982 --- /dev/null +++ b/share/extensions/tests/test_hershey.py @@ -0,0 +1,77 @@ +# coding=utf-8 +# tests for the hershey-text extension (hershey.py and hershey.inx) +from lxml import etree + +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareOrderIndependentStyle + +from hershey import Hershey + + +class HersheyComparisonMixin(ComparisonMixin): + comparisons_cmpfile_dict = {} # pairs of args and expected outputs + + def setUp(self): + self.effect_class = Hershey + self.compare_filters = [CompareNumericFuzzy(), CompareOrderIndependentStyle()] + + self.comparisons = self.comparisons_cmpfile_dict.keys() + + def get_compare_cmpfile(self, args, addout=None): + """get the correct cmpfile to compare from comparisons_dict;""" + return self.data_file("refs", self.comparisons_cmpfile_dict[args]) + + +class TestHersheyBasic(InkscapeExtensionTestMixin, HersheyComparisonMixin, TestCase): + compare_file = "svg/hershey_input.svg" # a huge number of inputs + comparisons_cmpfile_dict = { + # default parameters: + (): "hershey.out", + # same as above, but explicit parameters. same output: + ( + '--tab="render"', + '--fontface="HersheySans1"', + '--preserve="False"', + ): "hershey.out", + } + + +class TestHersheyTrivialInput( + InkscapeExtensionTestMixin, HersheyComparisonMixin, TestCase +): + compare_file = "svg/hershey_trivial_input.svg" + comparisons_cmpfile_dict = { + # loading a different font: + ('--fontface="EMSAllure"',): "hershey_loadfont.out", + # using the "other font" option. same output as above: + ('--fontface="other"', '--otherfont="EMSAllure"'): "hershey_loadfont.out", + # tests preserve text option + ('--fontface="EMSOsmotron"', "--preserve=true"): "hershey_preservetext.out", + # tests when just part of the input file is selected + ("--id=A",): "hershey_partialselection.out", + } + + +class TestHersheyTables(InkscapeExtensionTestMixin, HersheyComparisonMixin, TestCase): + compare_file = "svg/default-inkscape-SVG.svg" + comparisons_cmpfile_dict = { + # generates a simple font table: + ( + '--tab="utilities"', + '--action="sample"', + '--text="I am a quick brown fox"', + ): "hershey_fonttable.out", + # generates a simple font table, while testing UTF-8 input + ( + '--tab="utilities"', + '--action="sample"', + '--text="Î âm å qù¡çk brõwñ fø×"', + ): "hershey_encoding.out", + # generates a glyph table in the font "EMSOsmotron" + ( + '--tab="utilities"', + '--action="table"', + '--fontface="other"', + '--otherfont="EMSOsmotron"', + ): "hershey_glyphtable.out", + } diff --git a/share/extensions/tests/test_hpgl_decoder.py b/share/extensions/tests/test_hpgl_decoder.py new file mode 100644 index 0000000..d9c701f --- /dev/null +++ b/share/extensions/tests/test_hpgl_decoder.py @@ -0,0 +1,25 @@ +# coding=utf-8 +from hpgl_decoder import hpglDecoder + + +class Options(object): + """ + A dummy class because hpglDecoder expects an object as it's second argument + TODO: This requirement probably needs to be factored out of the original code. + """ + + def __init__(self): + self.resolutionX = None + self.resolutionY = None + self.docHeight = None + + +class TesthpglDecoderBasic(object): + def test_init_values_scale(self): + x = Options() + x.resolutionX = 25.4 + x.resolutionY = 25.4 + h = hpglDecoder("", x) + + assert h.scaleX == 1 + assert h.scaleY == 1 diff --git a/share/extensions/tests/test_hpgl_input.py b/share/extensions/tests/test_hpgl_input.py new file mode 100644 index 0000000..5f476a9 --- /dev/null +++ b/share/extensions/tests/test_hpgl_input.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from hpgl_input import HpglInput +from inkex.tester import ComparisonMixin, TestCase + + +class TestHpglFileBasic(ComparisonMixin, TestCase): + effect_class = HpglInput + compare_file = "io/test.hpgl" + comparisons = [()] diff --git a/share/extensions/tests/test_hpgl_output.py b/share/extensions/tests/test_hpgl_output.py new file mode 100644 index 0000000..0be89b2 --- /dev/null +++ b/share/extensions/tests/test_hpgl_output.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from hpgl_output import HpglOutput +from inkex.tester import ComparisonMixin, TestCase + + +class HPGLOutputBasicTest(ComparisonMixin, TestCase): + effect_class = HpglOutput + compare_file = ["svg/shapes.svg", "svg/hpgl_multipen.svg"] + comparisons = [("--force=24", "--speed=20", "--orientation=90")] diff --git a/share/extensions/tests/test_image_attributes.py b/share/extensions/tests/test_image_attributes.py new file mode 100644 index 0000000..634a69f --- /dev/null +++ b/share/extensions/tests/test_image_attributes.py @@ -0,0 +1,17 @@ +# coding=utf-8 +from image_attributes import ImageAttributes +from inkex.tester import ComparisonMixin, TestCase + + +class TestSetAttrImageBasic(ComparisonMixin, TestCase): + effect_class = ImageAttributes + compare_file = "svg/images.svg" + comparisons = [ + (), # All images in the document (basic) + ("--id=image174", "--aspect_ratio=xMinYMin", '--tab="tab_aspect_ratio"'), + ( + "--id=embeded_image01", + "--image_rendering=optimizeSpeed", + '--tab="tab_image_rendering"', + ), + ] diff --git a/share/extensions/tests/test_image_embed.py b/share/extensions/tests/test_image_embed.py new file mode 100644 index 0000000..3163d63 --- /dev/null +++ b/share/extensions/tests/test_image_embed.py @@ -0,0 +1,15 @@ +# coding=utf-8 +from image_embed import EmbedImage +from inkex.tester import ComparisonMixin, TestCase + + +class EmbedderBasicTest(ComparisonMixin, TestCase): + effect_class = EmbedImage + compare_file = "svg/images.svg" + comparisons = [ + (), + ( + "--id=image174", + "--selectedonly=True", + ), + ] diff --git a/share/extensions/tests/test_image_extract.py b/share/extensions/tests/test_image_extract.py new file mode 100644 index 0000000..6b8656a --- /dev/null +++ b/share/extensions/tests/test_image_extract.py @@ -0,0 +1,196 @@ +# coding=utf-8 + +import os, sys + +import pytest +from image_extract import ExtractImage +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.mock import Capture, MockCommandMixin +import inkex + + +class ExtractImageBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + """Comparison tests of ExtractImage""" + + stderr_protect = False + effect_class = ExtractImage + compare_file = "svg/images.svg" + compare_file_extension = "png" + comparisons = [ + ("--selectedonly=False",), + ("--selectedonly=True", "--id=embeded_image01"), + ] + + def test_all_comparisons(self): + """Images are extracted to a file directory""" + for args in self.comparisons: + args += (f"--filepath={self.tempdir}/",) + self.assertCompare(self.compare_file, None, args, "embeded_image01.png") + + +class ExtractImageComponentTests(TestCase, MockCommandMixin): + """Test some functions of ExtractImage""" + + mocks = [(sys, "exit", lambda status: None)] # type:ignore + + def test_extract_multiple(self): + """test extraction in a multi-image file""" + args = [ + self.data_file("svg", "images_multiple.svg"), + f"--directory={self.tempdir}/", + f"--output={self.tempdir}/out.svg", + "--selectedonly=True", + "--id=embedded_image01", + "--id=embedded_image02", + "--basename=image.jpg", # test that bad file extensions are corrected + "--linkextracted=false", + ] + + ext = ExtractImage() + + def run_test(outexists): + with Capture("stderr") as stderr: + ext.run(args) + # There should be two images saved to the tempdir + self.assertListEqual( + sorted(os.listdir(self.tempdir)), + ["image_1.png", "image_2.png"] + (["out.svg"] if outexists else []), + ) + self.assertEqual(len(stderr.getvalue().split("extracted")), 3) + self.assertEqual(ext.errcount, 0) + + # the out file only exists if it was changed, in this case, no change should + # be made + run_test(False) + for file in os.scandir(self.tempdir): + os.remove(file.path) + # We can do the same test again, because of linkextracted=False, the file is + # unchaged when running it on the output file. + args[-1] = "--linkextracted=true" + run_test(True) + + # Now save all images again from the temp file, two images will raise an error + # because they are already embedded + + # we also test that that relative target directories are interpreted relative to + # the input file stored in DOCUMENT_PATH (and not the actual input file name) + + args[0] = f"{self.tempdir}/out.svg" + args[3] = "--selectedonly=False" + os.environ["DOCUMENT_PATH"] = os.path.abspath("images_multiple.svg") + args[1] = "--directory=" + os.path.relpath(self.tempdir, "images_multiple.svg") + + with Capture("stderr") as stderr: + ext.run(args) + # There should be three images saved to the tempdir + self.assertListEqual( + sorted(os.listdir(self.tempdir)), + ["image_1.png", "image_2.png", "image_3.png", "out.svg"], + ) + self.assertEqual(len(stderr.getvalue().split("extracted")), 2) + self.assertEqual(len(stderr.getvalue().split("Unable")), 4) + self.assertEqual(ext.errcount, 3) + + def test_extract_single_contextmenu(self): + """test extraction in a multi-image file, called from the extensions menu, + but with only one selected image""" + args = [ + self.data_file("svg", "images_multiple.svg"), + f"--directory={self.tempdir}/", + "--selectedonly=True", + "--id=embedded_image01", + "--basename=image", + ] + ext = ExtractImage() + + with Capture("stderr") as stderr: + ext.run(args) + + self.assertListEqual(sorted(os.listdir(self.tempdir)), ["image.png"]) + + self.assertEqual(len(stderr.getvalue().split("extracted")), 2) + self.assertEqual(ext.errcount, 0) + + @pytest.mark.skipif(sys.platform == "win32", reason="all directories writeable") + def test_extract_badpath(self): + """Test writing to an unwriteable directory""" + + args = [ + self.data_file("svg", "images_multiple.svg"), + "--directory=/proc", + "--id=embedded_image01", + "--basename=image", + ] + with Capture("stderr") as stderr: + ext = ExtractImage() + ext.run(args) + + self.assertIn("Unable to write to", stderr.getvalue()) + self.assertEqual(ext.errcount, 1) + + args = [ + self.data_file("svg", "images_multiple.svg"), + "--directory=/proc/test", + "--id=embedded_image01", + "--basename=image", + ] + ext = ExtractImage() + + with Capture("stderr") as stderr: + # The extension aborts + ext.run(args) + self.assertIn("Unable to create", stderr.getvalue()) + + def test_extract_badfilename(self): + """Test writing to an unwriteable directory""" + + if sys.platform == "win32": + filename = "<" + else: + filename = "a\x00" # null bytes are invalid + args = [ + self.data_file("svg", "images_multiple.svg"), + "--directory=" + self.tempdir, + "--id=embedded_image01", + "--basename=" + filename, + ] + with Capture("stderr") as stderr: + ext = ExtractImage() + + if sys.version_info > (3, 8, 0) or filename == "<": + ext.run(args) + + self.assertIn("Unable to write to", stderr.getvalue()) + self.assertEqual(ext.errcount, 1) + else: + with self.assertRaises(ValueError) as __: + ext.run(args) + + def test_extract_bad_data(self): + """Extract bad data""" + + svg = inkex.load_svg(self.data_file("svg", "images_multiple.svg")).getroot() + + svg.getElementById("embedded_image01").set("xlink:href", "data:svg+xml;base64,") + svg.getElementById("embedded_image02").set( + "xlink:href", "data:image/abc;base32," + ) + + temppath = os.path.join(self.tempdir, "temp.svg") + + with open(temppath, "wb") as f: + f.write(svg.tostring()) + args = [ + self.data_file("svg", temppath), + "--directory=" + self.tempdir, + "--id=embedded_image01", + "--id=embedded_image02", + "--basename=badimage", + ] + ext = ExtractImage() + with Capture("stderr") as stderr: + ext.run(args) + + self.assertIn("Invalid image format", stderr.getvalue()) + self.assertIn("encoding", stderr.getvalue()) + self.assertEqual(ext.errcount, 2) diff --git a/share/extensions/tests/test_ink2canvas_svg.py b/share/extensions/tests/test_ink2canvas_svg.py new file mode 100644 index 0000000..ae7a16d --- /dev/null +++ b/share/extensions/tests/test_ink2canvas_svg.py @@ -0,0 +1,38 @@ +#!/usr/bin/en +# coding=utf-8 +from ink2canvas import Html5Canvas +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentLines +from inkex.tester.filters import WindowsTextCompat + + +class Ink2CanvasBasicTest(ComparisonMixin, TestCase): + effect_class = Html5Canvas + compare_file = "svg/shapes-clipboard.svg" + compare_filters = [CompareOrderIndependentLines()] + comparisons = [()] + + +class Ink2CanvasTestTextPath(ComparisonMixin, TestCase): + effect_class = Html5Canvas + compare_file = "svg/multilayered-test.svg" + # This file contains a textPath + compare_filters = [CompareOrderIndependentLines()] + # We don't need a selection for this case, but we need unique filenames for the tester + comparisons = [("--id=rect3898",)] + + +class Ink2CanvasTestClosedPath(ComparisonMixin, TestCase): + effect_class = Html5Canvas + compare_file = "svg/multiple_closed_subpaths.svg" + comparisons = [("--id=path31",)] + compare_filters = [WindowsTextCompat()] + + +class Ink2CanvasTestCSS(ComparisonMixin, TestCase): + """Test CSS styles""" + + effect_class = Html5Canvas + compare_file = "svg/styling-css-04-f.svg" + comparisons = [("--id=alpha",)] + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_inkex.py b/share/extensions/tests/test_inkex.py new file mode 100644 index 0000000..6a0a597 --- /dev/null +++ b/share/extensions/tests/test_inkex.py @@ -0,0 +1,73 @@ +# +# Copyright (C) 2020 Martin Owens +# +# 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, USA. +# +""" +Test API collisions and other inkex portions that don't fit elsewhere. +""" + +from unittest import TestCase as BaseCase + +import inkex +import inkex.paths +import inkex.elements +from inkex.utils import PY3 + + +class ProtectiveGlobals(dict): + """Python 3.3 and above globals dictionary""" + + def __setitem__(self, name, value): + # This only works because setitem is called during construction It + # does not work for getitem and that's why the python docs discourage + # the use of an inherited dictionary class for exec globals. + if name in self and value is not self[name]: + assert value is self[name], ( + "While importing {} the API name `{}` was re-defined:" + "\n\t1. {}" + "\n\t2. {}" + ).format(self["__name__"], name, repr(value), repr(self[name])) + super(ProtectiveGlobals, self).__setitem__(name, value) + + +class TestModuleCollisions(BaseCase): + """Test imports to make sure the API is clean""" + + def assertNoCollisions(self, module): # pylint: disable=invalid-name + """Make sure there are no API collisions in the give module on import""" + if not PY3: + self.skipTest("API testing python 3.3 and above only.") + + with open(module.__file__, "r") as fhl: + # name and package are esential to the exec pretending to + # be an actual module during import (and not a script) + exec( + fhl.read(), + ProtectiveGlobals( + { # pylint: disable=exec-used + "__name__": module.__name__, + "__package__": module.__package__, + } + ), + ) + + def test_inkex(self): + """Test inkex API have no collisions""" + self.assertNoCollisions(inkex) + + def test_inkex_elements(self): + """Test elements API have no collisions""" + self.assertNoCollisions(inkex.elements) diff --git a/share/extensions/tests/test_inkex_base.py b/share/extensions/tests/test_inkex_base.py new file mode 100644 index 0000000..5faf7e2 --- /dev/null +++ b/share/extensions/tests/test_inkex_base.py @@ -0,0 +1,210 @@ +# coding=utf-8 +"""Test base inkex module functionality""" +from __future__ import absolute_import, print_function, unicode_literals + +import os +import sys + +from io import BytesIO + +from inkex import AbortExtension, SvgDocumentElement +from inkex.base import InkscapeExtension, SvgThroughMixin +from inkex.tester import TestCase +from inkex.tester.mock import Capture + + +class ModExtension(InkscapeExtension): + """A non-svg extension that loads, saves and flipples""" + + def effect(self): + self.document += b">flipple" + + def load(self, stream): + return stream.read() + + def save(self, stream): + stream.write(self.document) + + +class NoModSvgExtension(SvgThroughMixin, InkscapeExtension): + """Test the loading and not-saving of non-modified svg files""" + + def effect(self): + return True + + +class ModSvgExtension(SvgThroughMixin, InkscapeExtension): + """Test the loading and saving of svg files""" + + def effect(self): + self.svg.set("attr", "foo") + + +class InkscapeExtensionTest(TestCase): + """Tests for Inkscape Extensions""" + + effect_class = InkscapeExtension + + def setUp(self): + self.e = self.effect_class() + + def test_bare_bones(self): + """What happens when we don't inherit""" + with self.assertRaises(NotImplementedError): + self.e.run([]) + with self.assertRaises(NotImplementedError): + prevarg = sys.argv + sys.argv = ["pytest"] + try: + self.e.run() + finally: + sys.argv = prevarg + with self.assertRaises(NotImplementedError): + self.e.effect() + with self.assertRaises(NotImplementedError): + self.e.load(sys.stdin) + with self.assertRaises(NotImplementedError): + self.e.save(sys.stdout) + self.assertEqual(self.e.name, "InkscapeExtension") + + def test_compat(self): + """Test a few old functions and how we handle them""" + with self.assertRaises(AttributeError): + self.assertEqual(self.e.OptionParser, None) + with self.assertRaises(AttributeError): + self.assertEqual(self.e.affect(), None) + + def test_arg_parser_defaults(self): + """Test arguments for the base class are given defaults""" + options = self.e.arg_parser.parse_args([]) + self.assertEqual(options.input_file, None) + self.assertEqual(options.output, None) + + def test_arg_parser_passed(self): + """Test arguments for the base class are parsed""" + options = self.e.arg_parser.parse_args(["--output", "foo.txt", self.empty_svg]) + self.assertEqual(options.input_file, self.empty_svg) + self.assertEqual(options.output, "foo.txt") + + def test_get_resource(self): + """We can get a resource path, based on where the extension is located""" + ext = ModExtension() + self.assertRaises(AbortExtension, ext.get_resource, "sir-not-apearing.py") + + # Test relative filename, which fails with AbortExtension if not found. + ret = ext.get_resource(__file__) + # Test absolute filename, which we already have, so just feed it back. + self.assertEqual(ext.get_resource(ret), ret) + + def test_svg_path(self): + """Can get the svg file location""" + output = os.path.join(self.tempdir, "output.tmp") + ext = ModExtension() + os.environ["DOCUMENT_PATH"] = self.empty_svg + self.assertEqual(ext.svg_path(), os.path.join(self.datadir(), "svg")) + self.assertIn(ext.absolute_href("/foo"), ["/foo", "C:\\foo"]) + self.assertEqual( + ext.absolute_href("./foo"), os.path.join(self.datadir(), "svg", "foo") + ) + self.assertEqual( + ext.absolute_href("~/foo"), os.path.realpath(os.path.expanduser("~/foo")) + ) + + def test_svg_no_path(self): + tmp_foo = os.path.realpath("/tmp/foo") + os.environ["DOCUMENT_PATH"] = "" + ext = ModExtension() + # Default results in home dir + self.assertEqual( + ext.absolute_href("./foo"), os.path.realpath(os.path.expanduser("~/foo")) + ) + # Or override the default + self.assertEqual(ext.absolute_href("./foo", "/tmp/"), tmp_foo) + # But we can ask for errors too, this one for "document not saved" + self.assertRaises(AbortExtension, ext.absolute_href, "./foo", default=None) + # This covers inkscape old versions + del os.environ["DOCUMENT_PATH"] + self.assertRaises(AbortExtension, ext.absolute_href, "./foo", default=None) + + +class TestArgumentDatatypes(TestCase): + """Test special argument types for the dataparser""" + + def test_page_descriptor(self): + """Test that page descriptions are parsed correctly""" + + def parsetest(string, length, comparison, startvalue=1): + result = InkscapeExtension.arg_number_ranges() + self.assertTupleEqual( + result(string)(length, startvalue=startvalue), comparison + ) + + parsetest("1, 2,3", 10, (1, 2, 3)) + parsetest("1-3, 5, 10", 10, (1, 2, 3, 5, 10)) + parsetest("2, 4-, 6, 7-", 10, (2, 4, 5, 6, 7, 8, 9, 10)) + parsetest("2-5, 7-9, 10-", 12, (2, 3, 4, 5, 7, 8, 9, 10, 11, 12)) + parsetest("6, 7, 8", 3, tuple()) + parsetest("2, 216-218, 10", 300, (2, 10, 216, 217, 218)) + parsetest("-3,10-,5", 12, (1, 2, 3, 5, 10, 11, 12)) + parsetest("-5, 7-", 7, (3, 4, 5, 7), 3) + parsetest("-", 7, (), 3) + + +class SvgInputOutputTest(TestCase): + """Test SVG Input Mixin""" + + def test_input_mixin(self): + """Test svg input gets loaded""" + obj = NoModSvgExtension() + obj.run([self.empty_svg]) + self.assertNotEqual(obj.document, None) + self.assertNotEqual(obj.original_document, None) + + def test_no_output(self): + """Test svg output isn't saved when not modified""" + obj = NoModSvgExtension() + filename = self.temp_file(suffix=".svg") + obj.run(["--output", filename, self.empty_svg]) + self.assertEqual(type(obj.document).__name__, "_ElementTree") + self.assertEqual(type(obj.svg).__name__, "SvgDocumentElement") + self.assertFalse(os.path.isfile(filename)) + + def test_svg_output(self): + """Test svg output is saved""" + obj = ModSvgExtension() + filename = self.temp_file(suffix=".svg") + obj.run(["--output", filename, self.empty_svg]) + self.assertTrue(os.path.isfile(filename)) + with open(filename, "r") as fhl: + self.assertIn("' + '' + ) + filename = self.temp_file(suffix=".svg") + with open(filename, "w") as file: + file.write(svg) + with Capture("stderr") as stderr: + obj = NoModSvgExtension() + obj.run([filename]) + # Test that the extension runs completely, and the document gets loaded + self.assertTrue(isinstance(obj.svg, SvgDocumentElement)) + # Test that the error is presented to the user + self.assertIn("is not a valid URI", stderr.getvalue()) diff --git a/share/extensions/tests/test_inkex_bezier.py b/share/extensions/tests/test_inkex_bezier.py new file mode 100644 index 0000000..b271233 --- /dev/null +++ b/share/extensions/tests/test_inkex_bezier.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from inkex.bezier import pointdistance + + +class TestPointDistance(object): + def test_points_on_horizontal_line(self): + p1 = (0, 0) + p2 = (10, 0) + + assert 10 == pointdistance(p1, p2) diff --git a/share/extensions/tests/test_inkex_bounding_box.py b/share/extensions/tests/test_inkex_bounding_box.py new file mode 100644 index 0000000..4c8159f --- /dev/null +++ b/share/extensions/tests/test_inkex_bounding_box.py @@ -0,0 +1,699 @@ +# coding=utf-8 +"""Test inkex `.bounding_box()` method functionality""" +from copy import deepcopy +import os +import subprocess + +import pytest +from inkex import ( + BoundingBox, + SvgDocumentElement, + Circle, + Rectangle, + Group, + PathElement, + Transform, + Path, + Style, +) +from inkex.tester import TestCase +from tempfile import TemporaryDirectory +from inkex.command import is_inkscape_available +from inkex.tester.decorators import requires_inkscape + +try: + from typing import Optional, Tuple +except ImportError: + pass + +DISABLE_STROKE_TESTS = True +DISABLE_STROKE_CAP_TESTS = True +DISABLE_INKSCAPE_QUERY_CHECK = not is_inkscape_available() + +skip_stroke_tests = pytest.mark.skipif( # pylint: disable=invalid-name + DISABLE_STROKE_TESTS, reason="Bounding box tests with stroke are disabled" +) + +skip_stroke_cap_tests = pytest.mark.skipif( # pylint: disable=invalid-name + DISABLE_STROKE_TESTS or DISABLE_STROKE_CAP_TESTS, + reason="Bounding box tests with stroke-cap are disabled", +) + + +class BoundingBoxTest(TestCase): + """Test BoundingBox functionality""" + + atol = 3e-3 + + def assert_bounding_box_is_equal( + self, obj, xscale, yscale, disable_inkscape_check=DISABLE_INKSCAPE_QUERY_CHECK + ): + """ + Assert: bounding box of object is exactly expected_box or is close to it + + :param (ShapeElement) obj: object to calculate bounding box + :param (Optional[Tuple[float,float]]) xscale: expected values of (xmin, xmax) + :param (Optional[Tuple[float,float]]) yscale: expected values of (ymin, ymax) + + """ + bounding_box = obj.bounding_box() + + if bounding_box is None: + self.assertEqual((None, None), (xscale, yscale)) + return + + box_array = list(bounding_box) + expected_array = xscale, yscale + + def cmp(a, b, msg=None): + self.assertEqual(len(a), len(b), msg=msg) + for x, y, label in zip(a, b, ("x", "y")): + self.assertDeepAlmostEqual( + tuple(x), tuple(y), delta=self.atol, msg=msg + " (%s)" % label + ) + + if not disable_inkscape_check: + inkscape_array = self.get_inkscape_bounding_box(obj) + + if None not in inkscape_array: + cmp(expected_array, inkscape_array, "expected != inkscape calculation") + + cmp(box_array, expected_array, "inkex.bounding_box != expected") + + def get_inkscape_bounding_box(self, obj): + """ + + :param (ShapeElement) obj: + :return: (xmin, xmax, ymin, ymax) parsed from `inkscape --query` output + """ + svg = SvgDocumentElement() + obj = deepcopy(obj) + obj_id = "testing-query-id" + obj.set("id", obj_id) + root = deepcopy(obj.getroottree().getroot()) + svg.add(root) + with TemporaryDirectory() as tmp: + + temp_svg = os.path.join(tmp, "tmp.svg") + + with open(temp_svg, "wb") as out: + out.write(svg.tostring()) + + with open(os.devnull, "w") as devnull: + output = subprocess.check_output( + [ + "inkscape", + "--query-all", + temp_svg, + ], + stderr=devnull, + ) + + out_lines = output.decode("utf-8").split("\n") + for line in out_lines: + if line.startswith(obj_id): + x, y, w, h = list(map(float, line.split(",")[1:])) + return (x, x + w), (y, y + h) + return None, None, None, None + + def test_bbox_empty_is_false(self): + self.assertFalse(bool(BoundingBox())) + + def test_bbox_nonempty_is_true(self): + self.assertTrue(bool(BoundingBox((0, 0), (0, 0)))) + + def test_bbox_empty_is_identity_for_addition(self): + bbox = BoundingBox((0, 1), (2, 3)) + self.assertEqual(BoundingBox() + bbox, bbox) + + def test_bbox_empty_is_zero_for_intersection(self): + bbox = BoundingBox((0, 1), (2, 3)) + self.assertEqual(BoundingBox() & bbox, BoundingBox()) + + def test_bbox_nonintersection_is_empty(self): + bbox1 = BoundingBox((0, 1), (2, 3)) + bbox2 = BoundingBox((2, 3), (1, 2)) + self.assertEqual(bbox1 & bbox2, BoundingBox()) + + def test_bbox_empty_equivalent_to_none(self): + bbox = BoundingBox((0, 1), (2, 3)) + self.assertEqual(bbox + None, bbox + BoundingBox()) + self.assertEqual(bbox & None, bbox & BoundingBox()) + self.assertEqual(None + bbox, BoundingBox() + bbox) + self.assertEqual(None & bbox, BoundingBox() & bbox) + + def test_circle_without_attributes(self): + circle = Circle() + self.assert_bounding_box_is_equal(circle, (0, 0), (0, 0)) + + def test_circle_with_radius(self): + r = 10 + circle = Circle(r=str(r)) + self.assert_bounding_box_is_equal(circle, (-r, r), (-r, r)) + + def test_circle_with_cx(self): + cx = 10 + circle = Circle(cx=str(cx)) + self.assert_bounding_box_is_equal(circle, (cx, cx), (0, 0)) + + def test_circle_with_cy(self): + cy = 10 + circle = Circle(cy=str(cy)) + self.assert_bounding_box_is_equal(circle, (0, 0), (cy, cy)) + + def test_circle_without_center(self): + r = 10 + circle = Circle(r=str(r)) + self.assert_bounding_box_is_equal(circle, (-r, r), (-r, r)) + + def test_regular_circle(self): + r = 5 + cx = 10 + cy = 20 + + circle = Circle(r=str(r), cx=str(cx), cy=str(cy)) + + self.assert_bounding_box_is_equal(circle, (cx - r, cx + r), (cy - r, cy + r)) + + @skip_stroke_tests + def test_circle_with_stroke(self): + r = 5 + cx = 10 + cy = 20 + + stroke_half_width = 1.0 + + circle = Circle(r=str(r), cx=str(cx), cy=str(cy)) + + circle.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + + self.assert_bounding_box_is_equal( + circle, + (cx - (r + stroke_half_width), cx + (r + stroke_half_width)), + (cy - (r + stroke_half_width), cy + (r + stroke_half_width)), + ) + + @skip_stroke_tests + def test_circle_with_stroke_scaled(self): + r = 5 + cx = 10 + cy = 20 + + scale_x = 2 + scale_y = 3 + + stroke_half_width = 1.0 + + circle = Circle(r=str(r), cx=str(cx), cy=str(cy)) + + circle.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + + circle.transform = Transform(scale=(scale_x, scale_y)) + + self.assert_bounding_box_is_equal( + circle, + ( + scale_x * (cx - (r + stroke_half_width)), + scale_x * (cx + (r + stroke_half_width)), + ), + ( + scale_y * (cy - (r + stroke_half_width)), + scale_y * (cy + (r + stroke_half_width)), + ), + ) + + def test_rectangle_without_attributes(self): + rect = Rectangle() + + self.assert_bounding_box_is_equal(rect, (0, 0), (0, 0)) + + def test_rectangle_without_dimensions(self): + + x, y = 10, 15 + w, h = 0, 0 + + rect = Rectangle(x=str(x), y=str(y)) + + self.assert_bounding_box_is_equal(rect, (x, x + w), (y, y + h)) + + def test_rectangle_without_coordinates(self): + + x, y = 0, 0 + w, h = 7, 20 + + rect = Rectangle(width=str(w), height=str(h)) + + self.assert_bounding_box_is_equal(rect, (x, x + w), (y, y + h)) + + def test_regular_rectangle(self): + + x, y = 10, 20 + w, h = 7, 20 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + self.assert_bounding_box_is_equal(rect, (x, x + w), (y, y + h)) + + def test_regular_rectangle_scaled(self): + + x, y = 10, 20 + w, h = 7, 20 + + scale_x = 2 + scale_y = 3 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + rect.transform = Transform(scale=(scale_x, scale_y)) + + self.assert_bounding_box_is_equal( + rect, (scale_x * x, scale_x * (x + w)), (scale_y * y, scale_y * (y + h)) + ) + + @skip_stroke_tests + def test_regular_rectangle_with_stroke(self): + + x, y = 10, 20 + w, h = 7, 20 + stroke_half_width = 1 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + rect.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + + self.assert_bounding_box_is_equal( + rect, + (x - stroke_half_width, x + w + stroke_half_width), + (y - stroke_half_width, y + h + stroke_half_width), + ) + + @skip_stroke_tests + def test_regular_rectangle_with_stroke_scaled(self): + + x, y = 10, 20 + w, h = 7, 20 + stroke_half_width = 1 + + scale_x = 2 + scale_y = 3 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + rect.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + rect.transform = Transform(scale=(scale_x, scale_y)) + + self.assert_bounding_box_is_equal( + rect, + (scale_x * (x - stroke_half_width), scale_x * (x + w + stroke_half_width)), + (scale_y * (y - stroke_half_width), scale_y * (y + h + stroke_half_width)), + ) + + def test_empty_path(self): + path = PathElement() + + self.assert_bounding_box_is_equal(path, None, None) + + def test_path_with_move_commands_only(self): + path = PathElement() + + path.set_path("M 0 0 " "m 100 100 " "M 200 200") + self.assert_bounding_box_is_equal(path, (0, 200), (0, 200)) + + def test_path_straight_line(self): + path = PathElement() + + path.set_path("M 0 0 " "L 10 10") + self.assert_bounding_box_is_equal(path, (0, 10), (0, 10)) + + def test_path_two_straight_lines_abosolute(self): + path = PathElement() + + path.set_path("M 0 0 " "L 10 10 " "M -1 1 " "L 10 10") + self.assert_bounding_box_is_equal(path, (-1, 10), (0, 10)) + + def test_path_two_straight_lines_relative(self): + path = PathElement() + + path.set_path("M 0 0 " "l 10 10 " "m -11 -9 " "l 12 12") + self.assert_bounding_box_is_equal(path, (-1, 11), (0, 13)) + + def test_path_straight_line_scaled(self): + path = PathElement() + + scale_x = 2 + scale_y = 3 + + path.set_path("M 10 10 " "L 20 20") + + path.transform = Transform(scale=(scale_x, scale_y)) + self.assert_bounding_box_is_equal( + path, (scale_x * 10, 20 * scale_x), (scale_y * 10, 20 * scale_y) + ) + + @skip_stroke_cap_tests + def test_path_horizontal_line_stroke_butt_cap(self): + path = PathElement() + + path.set_path("M 0 0 " "L 1 0") + + stroke_half_width = 1.0 + path.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + path.set("stroke-linecap", "butt") + + self.assert_bounding_box_is_equal( + path, (0, 1), (-stroke_half_width, stroke_half_width) + ) + + @skip_stroke_cap_tests + def test_path_horizontal_line_stroke_round_cap(self): + path = PathElement() + + path.set_path("M 0 0 " "L 1 0") + + stroke_half_width = 1.0 + path.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + path.set("stroke-linecap", "round") + + self.assert_bounding_box_is_equal( + path, + (-stroke_half_width, 1 + stroke_half_width), + (-stroke_half_width, stroke_half_width), + ) + + @skip_stroke_cap_tests + def test_path_horizontal_line_stroke_square_cap(self): + path = PathElement() + + path.set_path("M 0 0 " "L 1 0") + + stroke_half_width = 1.0 + path.style = Style("stroke-width:{};stroke:red".format(stroke_half_width * 2)) + path.set("stroke-linecap", "square") + + self.assert_bounding_box_is_equal( + path, + (-stroke_half_width, 1 + stroke_half_width), + (-stroke_half_width, stroke_half_width), + ) + + def test_empty_group(self): + group = Group() + self.assert_bounding_box_is_equal(group, None, None) + + def test_empty_group_with_translation(self): + group = Group() + group.transform = Transform(translate=(10, 15)) + self.assert_bounding_box_is_equal(group, None, None) + + def test_group_with_regular_rect(self): + group = Group() + x, y = 10, 20 + w, h = 7, 20 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + group.add(rect) + + self.assert_bounding_box_is_equal(group, (x, x + w), (y, y + h)) + + def test_group_with_number_of_rects(self): + + group = Group() + + xmin, ymin = 1000, 1000 + xmax, ymax = -1000, -1000 + + rects = [] + + for x, y, w, h in [ + (10, 20, 5, 7), + (30, 40, 5, 7), + ]: + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + rects.append(rect) + + xmin = min(xmin, x) + xmax = max(xmax, x + w) + ymin = min(ymin, y) + ymax = max(ymax, y + h) + + group.append(rect) + + self.assert_bounding_box_is_equal(group, (xmin, xmax), (ymin, ymax)) + + def test_group_with_number_of_rects_scaled(self): + + group = Group() + + scale_x, scale_y = 5, 10 + + xmin, ymin = 1000, 1000 + xmax, ymax = -1000, -1000 + rects = [] + + for x, y, w, h in [ + (10, 20, 5, 7), + (30, 40, 5, 7), + ]: + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + rects.append(rect) + + xmin = min(xmin, x) + xmax = max(xmax, x + w) + ymin = min(ymin, y) + ymax = max(ymax, y + h) + + group.add(rect) + + group.transform = Transform(scale=(scale_x, scale_y)) + self.assert_bounding_box_is_equal( + group, (scale_x * xmin, scale_x * xmax), (scale_y * ymin, scale_y * ymax) + ) + + def test_group_with_number_of_rects_translated(self): + + group = Group() + + dx, dy = 5, 10 + + xmin, ymin = 1000, 1000 + xmax, ymax = -1000, -1000 + rects = [] + + for x, y, w, h in [ + (10, 20, 5, 7), + (30, 40, 5, 7), + ]: + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + rects.append(rect) + + xmin = min(xmin, x) + xmax = max(xmax, x + w) + ymin = min(ymin, y) + ymax = max(ymax, y + h) + + group.add(rect) + + group.transform = Transform(translate=(dx, dy)) + + self.assert_bounding_box_is_equal( + group, (dx + xmin, dx + xmax), (dy + ymin, dy + ymax) + ) + + def test_group_nested_transform(self): + group = Group() + + x, y = 10, 20 + w, h = 7, 20 + + scale = 2 + + rect = Rectangle(width=str(w), height=str(h), x=str(x), y=str(y)) + + rect.transform = Transform(rotate=45, scale=scale) + + group.add(rect) + + group.transform = Transform( + rotate=-45 + ) # rotation is compensated, but scale is not + + a = rect.composed_transform() + self.assert_bounding_box_is_equal( + group, (scale * x, scale * (x + w)), (scale * y, scale * (y + h)) + ) + + def test_path_Arc_long_sweep_off(self): + path = Path("M 10 20 A 10 20 0 1 0 20 15") + path_element = PathElement() + path_element.path = path + self.assert_bounding_box_is_equal( + path_element, (7.078, 20 + 7.078), (15.0, 15.0 + 39.127) + ) + + def test_path_Arc_short_sweep_off(self): + path = Path("M 10 20 A 10 20 0 0 0 20 15") + path_element = PathElement() + path_element.path = path + self.assert_bounding_box_is_equal(path_element, (10, 20), (15, 15.0 + 5.873)) + + def test_path_Arc_short_sweep_on(self): + path = Path("M 10 20 A 10 20 0 0 1 20 15") + path_element = PathElement() + path_element.path = path + self.assert_bounding_box_is_equal( + path_element, (10, 20), (14.127, 14.127 + 5.873) + ) + + def test_path_Arc_long_sweep_on(self): + path = Path("M 10 20 A 10 20 0 1 1 20 15") + path_element = PathElement() + path_element.path = path + self.assert_bounding_box_is_equal( + path_element, (2.922, 2.922 + 20), (-19.127, -19.127 + 39.127) + ) + + def test_path_Arc_long_sweep_on_axis_x_25(self): + path = Path("M 10 20 A 10 20 25 1 1 20 15") + path_element = PathElement() + path_element.path = path + self.assert_bounding_box_is_equal( + path_element, (4.723, 4.723 + 24.786), (-17.149, -17.149 + 37.149) + ) + + def test_path_Move(self): + path = Path("M 10 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (10, 10), (20, 20)) + + def test_path_move(self): + path = Path("M 15 30 m 10 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 25), (30, 50)) + + def test_path_Line(self): + path = Path("M 15 30 L 10 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (10, 15), (20, 30)) + + def test_path_line(self): + path = Path("M 15 30 l 10 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 25), (30, 50)) + + def test_path_Zone(self): + path = Path("M 15 30 Z") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 15), (30, 30)) + + def test_path_Horz(self): + path = Path("M 15 30 H 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 20), (30, 30)) + + def test_path_horz(self): + path = Path("M 15 30 h 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 35), (30, 30)) + + def test_path_Vert(self): + path = Path("M 15 30 V 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 15), (20, 30)) + + def test_path_vert(self): + path = Path("M 15 30 v 20") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (15, 15), (30, 50)) + + def test_path_Curve(self): + path = Path("M10 10 C 20 20, 40 20, 50 10") + pe = PathElement() + pe.path = path + self.assert_bounding_box_is_equal(pe, (10, 50), (10, 17.5)) + + @requires_inkscape + def test_path_combined_1(self): + path = Path("M 0 0 C 11 14 33 3 85 98 H 84 V 91 L 13 78 C 26 83 65 24 94 77") + # path = Path("M 0 0 C 11 14 33 3 85 98") + pe = PathElement() + pe.path = path + ibb = self.get_inkscape_bounding_box(pe) + + self.assert_bounding_box_is_equal(pe, *ibb, disable_inkscape_check=True) + + def test_path_TepidQuadratic(self): + path = Path("M 10 5 Q 15 30 25 15 T 50 40") + pe = PathElement() + pe.path = path + ibb = (10, 50), (5, 40) + + self.assert_bounding_box_is_equal(pe, *ibb) + + def test_path_TepidQuadratic_2(self): + path = Path("M 10 5 Q 15 30 25 15 T 50 40 T 15 20") + pe = PathElement() + pe.path = path + ibb = (10, 10 + 43.462), (5, 56) + self.assert_bounding_box_is_equal(pe, *ibb) + + @requires_inkscape + def test_random_path_1(self): + import random + + from inkex.paths import ( + Line, + Vert, + Horz, + Curve, + Move, + Arc, + Quadratic, + TepidQuadratic, + Smooth, + ZoneClose, + ) + + klasses = (Line, Vert, Horz, Curve, Move, Quadratic) # , ZoneClose, Arc + + def random_segment(klass): + args = [random.randint(1, 100) for _ in range(klass.nargs)] + if klass is Arc: + args[2] = 0 # random.randint(0, 1) + args[3] = 0 # random.randint(0, 1) + args[4] = 0 # random.randint(0, 1) + return klass(*args) + + random.seed(2128506) + # random.seed(datetime.now()) + n_trials = 10 + n_elements = 15 + + for i in range(n_trials): + path = Path() + path.append(Move(0, 0)) + + for j in range(n_elements): + k = random.choice(klasses) + path.append(random_segment(k)) + if k is Curve: + while random.randint(0, 1) == 1: + path.append(random_segment(Smooth)) + if k is Quadratic: + while random.randint(0, 1) == 1: + path.append(random_segment(TepidQuadratic)) + + pe = PathElement() + pe.path = path + ibb = self.get_inkscape_bounding_box(pe) + + self.assert_bounding_box_is_equal(pe, *ibb, disable_inkscape_check=True) diff --git a/share/extensions/tests/test_inkex_colors.py b/share/extensions/tests/test_inkex_colors.py new file mode 100644 index 0000000..845b72e --- /dev/null +++ b/share/extensions/tests/test_inkex_colors.py @@ -0,0 +1,187 @@ +# coding=utf-8 + +from inkex.colors import Color, ColorError, ColorIdError, is_color +from inkex.tester import TestCase + + +class ColorTest(TestCase): + """Test for single transformations""" + + def test_empty(self): + """Empty color (black)""" + self.assertEqual(Color(), []) + self.assertEqual(Color().to_rgb(), [0, 0, 0]) + self.assertEqual(Color().to_rgba(), [0, 0, 0, 1.0]) + self.assertEqual(Color().to_hsl(), [0, 0, 0]) + self.assertEqual(str(Color(None)), "none") + self.assertEqual(str(Color("none")), "none") + + def test_errors(self): + """Color parsing errors""" + self.assertRaises(ColorError, Color, {}) + self.assertRaises(ColorError, Color, ["#id"]) + self.assertRaises(ColorError, Color, "#badhex") + self.assertRaises(ColorIdError, Color, "url(#someid)") + self.assertRaises(ColorError, Color, [0, 0, 0, 0]) + self.assertRaises(ColorError, Color(None, space="nop").to_rgb) + self.assertRaises(ColorError, Color(None, space="nop").to_hsl) + self.assertRaises(ColorError, Color([1], space="nop").__str__) + + def test_namedcolor(self): + """Named Color""" + self.assertEqual(Color("red"), [255, 0, 0]) + self.assertEqual(str(Color("red")), "red") + color = Color("red") + color[0] = 41 + self.assertEqual(str(color), "#290000") + color = Color("#ff0000").to_named() + self.assertEqual(str(color), "red") + + def test_rgb_hex(self): + """RGB Hex Color""" + color = Color("#ff0102") + self.assertEqual(color, [255, 1, 2]) + self.assertEqual(str(color), "#ff0102") + self.assertEqual(color.red, 255) + self.assertEqual(color.green, 1) + self.assertEqual(color.blue, 2) + color = Color(" #ff0102") + self.assertEqual(color.to_hsl(), [254, 255, 128]) + self.assertEqual(color.hue, 254) + self.assertEqual(color.saturation, 255) + self.assertEqual(color.lightness, 128) + self.assertEqual(color.alpha, 1.0) + + def test_setter_rgb(self): + """Color RGB units can be set""" + color = Color("red") + color.red = 127 + self.assertEqual(color.red, 127) + color.green = 5 + self.assertEqual(color.green, 5) + color.blue = 15 + self.assertEqual(color.blue, 15) + color.blue = 5.1 + self.assertEqual(color.blue, 5) + self.assertEqual(str(color), "#7f0505") + + def test_setter_hsl(self): + """Color HSL units can be set on RGB color""" + color = Color("#ff0102") + color.hue = 100 + self.assertEqual(color.space, "rgb") + self.assertEqual(color.hue, 100) + color.saturation = 100 + self.assertEqual(color.space, "rgb") + self.assertEqual(color.saturation, 99) + color.lightness = 100 + self.assertEqual(color.space, "rgb") + self.assertEqual(color.lightness, 99) # No sure, bad conversion? + + def test_setter_alpha(self): + """Color conversion from rgb to rgba""" + color = Color("#ff0102") + self.assertEqual(color.space, "rgb") + self.assertEqual(color.alpha, 1.0) + color.alpha = 0.5 + self.assertEqual(color.space, "rgba") + self.assertEqual(color.alpha, 0.5) + + def test_rgb_to_hsl(self): + """RGB to HSL Color""" + self.assertEqual(Color("#ff7c7d").to_hsl(), [254, 255, 189]) + self.assertEqual(Color("#7e7c7d").to_hsl(), [233, 2, 125]) + self.assertEqual(Color("#7e7cff").to_hsl(), [170, 255, 189]) + self.assertEqual(Color("#7eff7d").to_hsl(), [84, 255, 190]) + + def test_rgb_short_hex(self): + """RGB Short Hex Color""" + self.assertEqual(Color("#fff"), [255, 255, 255]) + self.assertEqual(str(Color("#fff")), "#ffffff") + + def test_rgb_int(self): + """RGB Integer Color""" + self.assertEqual(Color("rgb(255,255,255)"), [255, 255, 255]) + + def test_rgb_percent(self): + """RGB Percent Color""" + self.assertEqual(Color("rgb(100%,100%,100%)"), [255, 255, 255]) + self.assertEqual(Color("rgb(50%,0%,1%)"), [127, 0, 2]) + self.assertEqual(Color("rgb(66.667%,0%,6.667%)"), [170, 0, 17]) + + def test_rgba_one(self): + """Test for https://gitlab.com/inkscape/extensions/-/issues/402""" + self.assertEqual(Color("rgb(1, 100%,1.0)"), [1, 255, 255]) + self.assertEqual(Color("rgba(1, 100%,1.0, 100%)"), [1, 255, 255, 1]) + self.assertEqual(Color("rgba(1, 100%, 1.0, 1.0)"), [1, 255, 255, 1]) + self.assertEqual(Color("rgba(1, 100%, 1.0, 1)"), [1, 255, 255, 1]) + self.assertEqual(Color("rgba(1, 0, 0, 1)"), [1, 0, 0, 1]) + self.assertEqual(Color([1, 1.0, 1.0, 1], "rgba"), [1, 255, 255, 1]) + + def test_rgba_color(self): + """Parse RGBA colours""" + self.assertEqual(Color("rgba(45,50,55,1.0)"), [45, 50, 55, 1.0]) + self.assertEqual(Color("rgba(45,50,55,1.5)"), [45, 50, 55, 1.0]) + self.assertEqual(Color("rgba(66.667%,0%,6.667%,0.5)"), [170, 0, 17, 0.5]) + color = Color("rgba(255,127,255,0.5)") + self.assertEqual(str(color), "rgba(255, 127, 255, 0.5)") + self.assertEqual(str(color.to_rgb()), "#ff7fff") + self.assertEqual(color.to_rgb().to_rgba(0.75), [255, 127, 255, 0.75]) + color[3] = 1.0 + self.assertEqual(str(color), "rgb(255, 127, 255)") + + def test_hsl_color(self): + """Parse HSL colors""" + color = Color("hsl(4.0, 128, 99)") + self.assertEqual(color, [4, 128, 99]) + self.assertEqual(str(color), "hsl(4, 128, 99)") + self.assertEqual(color.hue, 4) + self.assertEqual(color.saturation, 128) + self.assertEqual(color.lightness, 99) + + def test_hsl_to_rgb(self): + """Convert HSL to RGB""" + color = Color("hsl(172, 131, 128)") + self.assertEqual(color.to_rgb(), [68, 62, 193]) + self.assertEqual(str(color.to_rgb()), "#443ec1") + self.assertEqual(color.red, 68) + self.assertEqual(color.green, 62) + self.assertEqual(color.blue, 193) + color = Color("hsl(172, 131, 10)") + self.assertEqual(color.to_rgb(), [5, 4, 15]) + color = Color("hsl(0, 131, 10)") + self.assertEqual(color.to_rgb(), [15, 4, 4]) + self.assertEqual(color.to_rgba(), [15, 4, 4, 1.0]) + + def test_hsl_grey(self): + """Parse HSL Grey""" + color = Color("hsl(172, 0, 128)") + self.assertEqual(color.to_rgb(), [128, 128, 128]) + color = Color("rgb(128, 128, 128)") + self.assertEqual(color.to_hsl(), [0, 0, 128]) + + def test_is_color(self): + """Can detect colour format""" + self.assertFalse(is_color("rgb[t, b, s]")) + self.assertTrue(is_color("#fff")) + self.assertTrue(is_color(1364325887)) + + def test_int_color(self): + """Colours from arg parser""" + color = Color(1364325887) + self.assertEqual(str(color), "#5151f5") + color = Color("1364325887") + self.assertEqual(str(color), "#5151f5") + color = Color(0xFFFFFFFF) + self.assertEqual(str(color), "#ffffff") + color = Color(0xFFFFFF00) + self.assertEqual(str(color), "rgba(255, 255, 255, 0)") + self.assertEqual(int(Color("#808080")), 0x808080FF) + self.assertEqual(int(Color("rgba(128, 128, 128, 0.2)")), 2155905075) + + def test_interpolate(self): + black = Color("#000000") + grey50 = Color("#080808") + white = Color("#111111") + val = black.interpolate(white, 0.5) + assert val == grey50 diff --git a/share/extensions/tests/test_inkex_command.py b/share/extensions/tests/test_inkex_command.py new file mode 100644 index 0000000..f6b7b67 --- /dev/null +++ b/share/extensions/tests/test_inkex_command.py @@ -0,0 +1,45 @@ +# coding=utf-8 +""" +Test Inkex command launching functionality. +""" +import pytest +import sys +from inkex.tester import BaseCase +from inkex.command import ( + ProgramRunError, + which, + write_svg, + to_arg, + to_args, + call, + inkscape, + inkscape_command, + take_snapshot, +) + + +class CommandTest(BaseCase): + """Test command API""" + + @pytest.mark.skipif( + sys.platform == "win32", reason="gunzip doesn't exist on windows" + ) + def test_binary_call(self): + """Calls should allow binary stdin""" + # https://gitlab.com/inkscape/extensions/-/commit/2e504f2a3f6bb627f17b267c5623a71005d7234d#note_164780678 + binary = ( + b"\x1f\x8b\x08\x00eh\xc3\\\x02\xffK\xcb\xcf\x07\x00!es\x8c\x03\x00\x00\x00" + ) + stdout = call("gunzip", stdin=binary) + + def test_command_error(self): + """Call to test ProgramRunError""" + + with self.assertRaises(ProgramRunError) as cm: + call("python", "nonexistent_file") + exc = cm.exception + self.assertIsInstance(exc, ProgramRunError) + self.assertEqual(exc.returncode, 2) + self.assertIn("can't open file", exc.stderr.decode("utf8")) + self.assertEqual("", exc.stdout.decode("utf8")) + self.assertIn("can't open file", str(exc)) diff --git a/share/extensions/tests/test_inkex_cubic_paths.py b/share/extensions/tests/test_inkex_cubic_paths.py new file mode 100644 index 0000000..f22ea6c --- /dev/null +++ b/share/extensions/tests/test_inkex_cubic_paths.py @@ -0,0 +1,74 @@ +# coding=utf-8 +""" +Test CubicSuperPath +""" + +from inkex.tester import TestCase +from inkex.paths import CubicSuperPath + + +class CubicPathTest(TestCase): + def test_LHV(self): + p = [ + ["M", [1.2, 2.3]], + ["L", [3.4, 4.5]], + ["H", [5.6]], + ["V", [6.7]], + ] + csp = CubicSuperPath(p) + self.assertDeepAlmostEqual( + csp, + [ + [ + [[1.2, 2.3], [1.2, 2.3], [1.2, 2.3]], + [[3.4, 4.5], [3.4, 4.5], [3.4, 4.5]], + [[5.6, 4.5], [5.6, 4.5], [5.6, 4.5]], + [[5.6, 6.7], [5.6, 6.7], [5.6, 6.7]], + ] + ], + ) + + def test_CS(self): + p = [ + ["M", [1.2, 2.3]], + ["C", [4.5, 3.4, 5.6, 6.7, 8.9, 7.8]], + ["S", [9.1, 1.2, 2.3, 3.4]], + ] + csp = CubicSuperPath(p) + self.assertDeepAlmostEqual( + csp, + [ + [ + [[1.2, 2.3], [1.2, 2.3], [4.5, 3.4]], + [[5.6, 6.7], [8.9, 7.8], [12.2, 8.9]], + [[9.1, 1.2], [2.3, 3.4], [2.3, 3.4]], + ] + ], + ) + + def test_QT(self): + p = [ + ["M", [0.0, 0.0]], + ["Q", [3.0, 0.0, 3.0, 3.0]], + ["T", [0.0, 6.0]], + ] + csp = CubicSuperPath(p) + self.assertDeepAlmostEqual( + csp, + [ + [ + [[0.0, 0.0], [0.0, 0.0], [2.0, 0.0]], + [[3.0, 1.0], [3.0, 3.0], [3.0, 5.0]], + [[2.0, 6.0], [0.0, 6.0], [0.0, 6.0]], + ] + ], + ) + + def test_AZ(self): + p = [ + ["M", [0.0, 4.0]], + ["A", [3.0, 6.0, 0.0, 1, 1, 5.0, 4.0]], + ["Z", []], + ] + csp = CubicSuperPath(p) + self.assertTrue(len(csp[0]) > 3) diff --git a/share/extensions/tests/test_inkex_deprecated.py b/share/extensions/tests/test_inkex_deprecated.py new file mode 100644 index 0000000..3ec1258 --- /dev/null +++ b/share/extensions/tests/test_inkex_deprecated.py @@ -0,0 +1,42 @@ +# coding=utf-8 +"""Test base inkex module functionality""" +from __future__ import absolute_import, print_function, unicode_literals +from pathlib import Path +import warnings + +from inkex.deprecated import _deprecated +from inkex.tester import TestCase + + +class DeprecatedTests(TestCase): + """Test ways in which we deprecate code""" + + maxDiff = 10000 + + def assertDeprecated( + self, call, msg, *args, **kwargs + ): # pylint: disable=invalid-name + """Catch deprecation warnings and test their output""" + with warnings.catch_warnings(record=True) as warns: + warnings.simplefilter("always") + call(*args, **kwargs) + if msg is None: + self.assertFalse(warns, "Expected no warnings, got warnings!") + else: + self.assertTrue(warns, "No warning was returned, expected warning!") + if msg is not False: + self.assertEqual( + str(warns[0].category.__name__), "DeprecationWarning" + ) + return warns[0] + + def test_warning(self): + """What happens when we deprecate things""" + self.assertDeprecated(_deprecated, None, "", stack=0, level=0) + self.assertDeprecated(_deprecated, "FOO", "FOO", stack=0, level=1) + + def test_traceback(self): + """Traceback is possible for deprecation warnings""" + warn = self.assertDeprecated(_deprecated, False, "BAR", stack=0, level=2) + self.assertIn(str(Path("inkex") / "deprecated"), str(warn.message)) + self.assertIn("test_inkex_deprecated.py", str(warn.message)) diff --git a/share/extensions/tests/test_inkex_elements.py b/share/extensions/tests/test_inkex_elements.py new file mode 100644 index 0000000..4844bb4 --- /dev/null +++ b/share/extensions/tests/test_inkex_elements.py @@ -0,0 +1,816 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test specific elements API from svg xml lxml custom classes. +""" + +import pytest +import math +import inkex + +from inkex import ( + Group, + Layer, + Pattern, + Guide, + Page, + Polyline, + Use, + Defs, + TextElement, + TextPath, + Tspan, + FlowPara, + FlowRoot, + FlowRegion, + FlowSpan, + PathElement, + Rectangle, + Circle, + Ellipse, + Anchor, + Line as LineElement, + Transform, + Style, + LinearGradient, + RadialGradient, + Stop, +) +from inkex import paths +from inkex.colors import Color +from inkex.paths import Move, Line +from inkex.utils import FragmentError +from inkex.units import parse_unit + +from .test_inkex_elements_base import SvgTestCase +from inkex.tester.svg import svg + + +class ElementTestCase(SvgTestCase): + """Base element testing""" + + tag = "svg" + + def setUp(self): + super().setUp() + self.elem = self.svg.getElement("//svg:{}".format(self.tag)) + + def test_print(self): + """Print element as string""" + self.assertEqual(str(self.elem), self.tag) + + def assertElement(self, elem, compare): # pylint: disable=invalid-name + """Assert an element""" + self.assertEqual(elem.tostring(), compare) + + +class PathElementTestCase(ElementTestCase): + """Test PathElements""" + + source_file = "with-lpe.svg" + tag = "path" + + def test_new_path(self): + """Test new path element""" + path = PathElement.new(path=[Move(10, 10), Line(20, 20)]) + self.assertEqual(path.get("d"), "M 10 10 L 20 20") + + def test_original_path(self): + """LPE paths can return their original paths""" + lpe = self.svg.getElementById("lpe") + nolpe = self.svg.getElementById("nolpe") + self.assertEqual(str(lpe.path), "M 30 30 L -10 -10 Z") + self.assertEqual(str(lpe.original_path), "M 20 20 L 10 10 Z") + self.assertEqual(str(nolpe.path), "M 30 30 L -10 -10 Z") + self.assertEqual(str(nolpe.original_path), "M 30 30 L -10 -10 Z") + + lpe.original_path = "M 60 60 L 5 5" + self.assertEqual(lpe.get("inkscape:original-d"), "M 60 60 L 5 5") + self.assertEqual(lpe.get("d"), "M 30 30 L -10 -10 Z") + + lpe.path = "M 60 60 L 15 15 Z" + self.assertEqual(lpe.get("d"), "M 60 60 L 15 15 Z") + + nolpe.original_path = "M 60 60 L 5 5" + self.assertEqual(nolpe.get("inkscape:original-d", None), None) + self.assertEqual(nolpe.get("d"), "M 60 60 L 5 5") + + def _compare_paths(self, result, reference, precision=4): + reference = inkex.Path(reference) + result = inkex.Path(result) + self.assertEqual(len(reference), len(result)) + for c1, c2 in zip(reference, result): + self.assertEqual(c1.letter, c2.letter) + self.assertAlmostTuple(c1.args, c2.args, precision=precision, msg=result) + + def test_arc(self): + """Test arc generation""" + + def compare_arc(cx, cy, rx, ry, start, end, reference, type="arc"): + arc = PathElement.arc((cx, cy), rx, ry, start=start, end=end, arctype=type) + self.assertEqual(arc.get("sodipodi:arc-type"), type) + self._compare_paths(arc.get("d"), reference) + + compare_arc( + 10, + 20, + 5, + 5, + math.pi / 4, + math.pi * 6 / 4, + """m 13.535534,23.535534 a 5,5 0 0 1 -6.035534,0.794593 + 5,5 0 0 1 -2.3296291,-5.624222 5,5 0 0 1 4.8296291,-3.705905""", + ) + compare_arc( + 10, + 20, + 5, + 5, + math.pi / 4, + math.pi * 6 / 4, + """m 13.535534,23.535534 a 5,5 0 0 1 -6.035534,0.794593 + 5,5 0 0 1 -2.3296291,-5.624222 5,5 0 0 1 4.8296291,-3.705905 z""", + type="chord", + ) + compare_arc( + 10, + 20, + 5, + 5, + math.pi / 4, + math.pi * 28 / 18, + """m 13.535534,23.535534 a 5,5 0 0 1 -6.2830789,0.641905 5,5 0 0 1 -1.8991927,-6.02347 + 5,5 0 0 1 5.5149786,-3.078008 l -0.868241,4.924039 z""", + type="slice", + ) + + def test_stars(self): + def compare_star( + cx, + cy, + sides, + r1, + r2, + arg1, + arg2, + flatsided, + rounded, + reference, + precision=4, + ): + star = PathElement.star( + (cx, cy), (r1, r2), sides, rounded, (arg1, arg2), flatsided + ) + self.assertEqual(star.get("inkscape:flatsided"), str(flatsided).lower()) + self._compare_paths(star.get("d"), reference, precision=precision) + + # Test a simple polygon + compare_star( + 10, + 5, + 6, + 5.5, + 10, + 7 / 8 * math.pi, + 42, + True, + 0, + """m 4.9186625,7.1047587 0.7178942,-5.4529467 5.0813373,-2.10475872 + 4.363443,3.34818802 -0.717894,5.4529467 -5.0813372,2.104759 z""", + ) + # Test a star + compare_star( + 5, + 10, + 7, + 35, + 17, + 0.95545678, + 1.4790556, + False, + 0, + """m 25.203254,38.580212 -18.6458484,-11.651701 -11.3057927,16.6865 + -2.5158293,-21.842628 -20.0950776,1.564637 15.508661,-15.5856099 + -13.752359,-14.7354284 21.8548124,2.4076898 2.94616632,-19.9394165 + 11.74384528,18.5879506 17.426168,-10.1286176 -7.210477,20.7711057 + 18.783909,7.3092373 -20.735163,7.313194 z""", + ) + # Test a rounded polygon + compare_star( + 10, + 5, + 6, + 5.5, + 10, + 7 / 8 * math.pi, + 42, + True, + 0.1, + """m 4.9186625,7.1047587 c -0.2104759,-0.5081337 0.3830754,-5.0166024 0.7178942,-5.4529467 + 0.3348188,-0.4363443 4.5360433,-2.17654814 5.0813373,-2.10475872 + 0.545295,0.0717894 4.152968,2.84005422 4.363443,3.34818802 + 0.210476,0.5081337 -0.383075,5.0166024 -0.717894,5.4529467 + -0.334819,0.4363443 -4.5360425,2.176548 -5.0813372,2.104759 + -0.5452947,-0.07179 -4.1529674,-2.8400545 -4.3634433,-3.3481883 z""", + ) + compare_star( + 5, + 10, + 7, + 35, + 17, + 0.95545678, + 1.4790556, + False, + 1, + """m 25.203254,38.580212 c -18.8526653,11.31401 3.036933,-15.296807 -18.6458484,-11.651701 + -19.8769816,3.341532 7.5786704,23.731873 -11.3057927,16.6865 + -20.6000929,-7.685438 13.8530224,-7.163034 -2.5158293,-21.842628 + -15.0056106,-13.4570388 -13.8291026,20.721824 -20.0950776,1.564637 + -6.835231,-20.8975929 14.237504,6.364651 15.508661,-15.5856099 + 1.165291,-20.1221851 -24.823279,2.1078182 -13.752359,-14.7354284 + 12.076699,-18.3734357 3.900854,15.0996232 21.8548124,2.4076898 + 16.4587046,-11.6349155 -17.1250194,-18.0934175 2.94616632,-19.9394165 + 21.89462928,-2.013706 -9.37321772,12.464272 11.74384528,18.5879506 + 19.358377,5.61368249 3.468728,-24.6699406 17.426168,-10.1286176 + 15.225456,15.86238583 -15.589066,0.44307 -7.210477,20.7711057 + 7.680797,18.6350633 21.450453,-12.6694955 18.783909,7.3092373 + -2.908795,21.793777 -10.066029,-11.91177319 -20.735163,7.313194 + -9.7805797,17.623861 23.27955,8.871339 5.996985,19.243087 z""", + precision=2, + ) + + +class PolylineElementTestCase(ElementTestCase): + """Test the polyline elements support""" + + tag = "polyline" + + def test_type(self): + """Polyline have their own types""" + self.assertTrue(isinstance(self.elem, inkex.Polyline)) + + def test_polyline_points(self): + """Basic tests for points attribute as a path""" + pol = Polyline(points="10,10 50,50 10,15 15,10") + self.assertEqual(str(pol.path), "M 10 10 L 50 50 L 10 15 L 15 10") + pol.path = "M 10 10 L 30 9 L 1 2 C 10 45 3 4 45 60 M 35 35" + self.assertEqual(pol.get("points"), "10,10 30,9 1,2 45,60 35,35") + + +class PolygonElementTestCase(ElementTestCase): + """Test Polygon Elements""" + + tag = "polygon" + + def test_type(self): + """Polygons have their own types""" + self.assertTrue(isinstance(self.elem, inkex.Polygon)) + + def test_conversion(self): + """Polygones are converted to paths""" + pol = inkex.Polygon(points="10,10 50,50 10,15 15,10") + self.assertEqual(str(pol.path), "M 10 10 L 50 50 L 10 15 L 15 10 Z") + + +class LineElementTestCase(ElementTestCase): + """Test Line Elements""" + + tag = "line" + + def test_new_line(self): + """Line creation""" + line = LineElement.new((10, 10), (20, 20)) + self.assertElement(line, b'') + + def test_type(self): + """Lines have their own types""" + self.assertTrue(isinstance(self.elem, inkex.Line)) + + def test_conversion(self): + """Lines are converted to paths""" + pol = inkex.elements.Line(x1="2", y1="3", x2="4", y2="5") + self.assertEqual(str(pol.path), "M 2 3 L 4 5") + + +class PatternTestCase(ElementTestCase): + """Test Pattern elements""" + + tag = "pattern" + + def test_pattern_transform(self): + """Patterns have a transformation of their own""" + pattern = Pattern() + self.assertEqual(pattern.patternTransform, Transform()) + pattern.patternTransform.add_translate(10, 10) + self.assertEqual(pattern.get("patternTransform"), "translate(10, 10)") + + +class GroupTest(ElementTestCase): + """Test extra functionality on a group element""" + + tag = "g" + + def test_new_group(self): + """Test creating groups""" + svg = Layer.new("layerA", Group.new("groupA", Rectangle())) + self.assertElement( + svg, + b'' + b'', + ) + + def test_transform_property(self): + """Test getting and setting a transform""" + self.assertEqual( + str(self.elem.transform), "matrix(1.44985 0 0 1.36417 -107.03 -167.362)" + ) + self.elem.transform = "translate(12, 14)" + self.assertEqual(self.elem.transform, Transform("translate(12, 14)")) + self.assertEqual(str(self.elem.transform), "translate(12, 14)") + + def test_groupmode(self): + """Get groupmode is layer""" + self.assertEqual(self.svg.getElementById("A").groupmode, "layer") + self.assertEqual(self.svg.getElementById("C").groupmode, "group") + + def test_get_path(self): + """Group path is combined children""" + print(str(self.svg.getElementById("A").get_path())) + self.assertEqual( + str(self.svg.getElementById("A").get_path()), + "M -108.539 517.61 L -87.6093 496.117 L -98.3066 492.768 L -69.9353 492.301 L -55.5172" + " 506.163 L -66.2146 502.814 L -87.1446 524.307 M 60.0914 498.694 L 156.784 439.145 L" + " 240.218 491.183 L 143.526 550.731 z M -176.909 458.816 a 64.2385 38.9175 -7.86457 1" + " 0 88.3701 -19.0784 a 64.2385 38.9175 -7.86457 0 0 -88.3701 19.0784 z M -300.162" + " 513.715 L -282.488 509.9 Z M -214.583 540.504 L -209.001 448.77 M -193.189 547.201 " + "L -238.536 486.266 L -185.049 503.008 L -230.396 442.073 M -193.189 547.201 L -238.536" + " 486.266 L -185.049 503.008 L -230.396 442.073 Z M 15 15 L 15.5 20", + ) + + def test_bounding_box(self): + """A group returns a bounding box""" + empty = self.svg.add(Group(Group())) + self.assertEqual(empty.bounding_box(), None) + self.assertEqual(int(self.svg.getElementById("A").bounding_box().width), 783) + self.assertEqual(int(self.svg.getElementById("B").bounding_box().height), 114) + + +class RectTest(ElementTestCase): + """Test extra functionality on a rectangle element""" + + tag = "rect" + + def test_parse(self): + """Test Rectangle parsed from XML""" + rect = Rectangle( + attrib={ + "x": "10px", + "y": "20px", + "width": "100px", + "height": "200px", + "rx": "15px", + "ry": "30px", + } + ) + self.assertEqual(rect.left, 10) + self.assertEqual(rect.top, 20) + self.assertEqual(rect.right, 10 + 100) + self.assertEqual(rect.bottom, 20 + 200) + self.assertEqual(rect.width, 100) + self.assertEqual(rect.height, 200) + self.assertEqual(rect.rx, 15) + self.assertEqual(rect.ry, 30) + + def test_compose_transform(self): + """Composed transformation""" + self.assertEqual(self.elem.transform, Transform("rotate(16.097889)")) + self.assertEqual( + str(self.elem.composed_transform()), + "matrix(1.4019 -0.812338 1.20967 0.709877 -542.221 533.431)", + ) + + def test_effetive_stylesheet(self): + """Test the non-parent combination of styles""" + self.assertEqual( + str(self.elem.effective_style()), "fill:#0000ff;stroke-width:1px" + ) + self.assertEqual( + str(self.elem.getparent().effective_style()), + "fill:#0000ff;stroke-width:1px;stroke:#f00", + ) + + def test_compose_stylesheet(self): + """Test finding the composed stylesheet for the shape""" + self.assertEqual(str(self.elem.style), "fill:#0000ff;stroke-width:1px") + self.assertEqual( + str(self.elem.specified_style()), + "fill:#0000ff;stroke-width:1px;stroke:#d88", + ) + + def test_path(self): + """Rectangle path""" + self.assertEqual(self.elem.get_path(), "M 200.0,200.0 h100.0v100.0h-100.0 z") + self.assertEqual(str(self.elem.path), "M 200 200 h 100 v 100 h -100 z") + + +class PathTest(ElementTestCase): + """Test path extra functionality""" + + tag = "path" + + def test_apply_transform(self): + """Transformation can be applied to path""" + path = self.svg.getElementById("D") + path.transform = Transform(translate=(10, 10)) + self.assertEqual( + path.get("d"), "M30,130 L60,130 L60,120 L70,140 L60,160 L60,150 L30,150" + ) + path.apply_transform() + self.assertEqual( + path.get("d"), + "M 40 140 L 70 140 L 70 130 L 80 150 " "L 70 170 L 70 160 L 40 160", + ) + self.assertFalse(path.transform) + + +class CircleTest(ElementTestCase): + """Test extra functionality on a circle element""" + + tag = "circle" + + def test_parse(self): + """Test Circle parsed from XML""" + circle = Circle(attrib={"cx": "10px", "cy": "20px", "r": "30px"}) + self.assertEqual(circle.center.x, 10) + self.assertEqual(circle.center.y, 20) + self.assertEqual(circle.radius, 30) + ellipse = Ellipse( + attrib={"cx": "10px", "cy": "20px", "rx": "30px", "ry": "40px"} + ) + self.assertEqual(ellipse.center.x, 10) + self.assertEqual(ellipse.center.y, 20) + self.assertEqual(ellipse.radius.x, 30) + self.assertEqual(ellipse.radius.y, 40) + + def test_new(self): + """Test new circles""" + elem = Circle.new((10, 10), 50) + self.assertElement(elem, b'') + elem = Ellipse.new((10, 10), (15, 10)) + self.assertElement(elem, b'') + + def test_path(self): + """Circle path""" + self.assertEqual( + self.elem.get_path(), + "M 100.0,50.0 a 50.0,50.0 0 1 0 50.0, " + "50.0 a 50.0,50.0 0 0 0 -50.0, -50.0 z", + ) + + +class AnchorTest(ElementTestCase): + """Test anchor tags""" + + def test_new(self): + """Anchor tag creation""" + link = Anchor.new("https://inkscape.org", Rectangle()) + self.assertElement(link, b'') + + +class NamedViewTest(ElementTestCase): + """Test the sodipodi namedview tag""" + + def test_guides(self): + """Create a guide and see a list of them""" + self.svg.namedview.add(Guide().move_to(0, 0, 0)) + self.svg.namedview.add(Guide().move_to(0, 0, "90")) + self.assertEqual(len(self.svg.namedview.get_guides()), 2) + + def test_guides_coincident(self): + """Test the detection of coincident guides""" + + def coincidence_test(data, result): + guide1 = Guide().move_to(*data[0], angle=data[1]) + guide2 = Guide().move_to(*data[2], angle=data[3]) + self.assertEqual(Guide.guides_coincident(guide1, guide2), result) + + # both are good + coincidence_test(((0, 0), (0, 1), (2, 0), (0, 3)), True) + # antiparallel + coincidence_test(((0, 0), (0, 1), (2, 0), (0, -3)), True) + # point not on guide + coincidence_test(((0, 0), (0, 1), (0, 1), (0, 3)), False) + # different orientation + coincidence_test(((0, 0), (0, 1), (2, 0), (1, 0)), False) + # try the same at an angle + coincidence_test(((1, 1), (2, -1), (3, 5), (-2, 1)), True) + coincidence_test(((1, 1), (2, -1), (3, 6), (-2, 1)), False) + # and vertical + coincidence_test(((0, 1), (1, 0), (0, 2), (3, 0)), True) + coincidence_test(((0, 1), (1, 0), (0, 2), (-3, 0)), True) + coincidence_test(((1, 1), (1, 0), (0, 2), (-3, 0)), False) + + def test_pages(self): + """Create some extra pages and see a list of them""" + self.assertEqual(len(self.svg.namedview.get_pages()), 0) + self.svg.namedview.add(Page(width="210", height="297", x="0", y="0")) + self.svg.namedview.new_page( + x="220", y="0", width="147.5", height="210", label="TEST" + ) + self.assertEqual(len(self.svg.namedview.get_pages()), 2) + self.assertEqual(self.svg.namedview.get_pages()[0].attrib["x"], "0") + self.assertEqual( + self.svg.namedview.get_pages()[1].get("inkscape:label"), "TEST" + ) + self.assertEqual(self.svg.namedview.get_pages()[1].attrib["width"], "147.5") + self.assertEqual(self.svg.namedview.get_pages()[0].attrib["height"], "297") + self.assertEqual(self.svg.namedview.get_pages()[1].attrib["x"], "220") + self.assertEqual(self.svg.namedview.get_pages()[1].attrib["y"], "0") + + def test_center(self): + """Test that the center in mm based documents is correctly computed""" + mmbased = svg(f'width="210mm" viewBox="0 0 210 297"') + mmbased.namedview.set( + "inkscape:cx", 396.57881 + ) # Values of a freshly opened mm document + mmbased.namedview.set("inkscape:cy", 561.81998) + + self.assertAlmostTuple( + mmbased.namedview.center, + [mmbased.viewbox_width / 2, mmbased.viewport_height / 2], + precision=0, + ) + + +class TextTest(ElementTestCase): + """Test all text functions""" + + def test_append_superscript(self): + """Test adding superscript""" + tap = TextPath() + tap.append(Tspan.superscript("th")) + self.assertEqual(len(tap), 1) + + def test_path(self): + """Test getting paths""" + self.assertFalse(TextPath().get_path()) + self.assertFalse(TextElement().get_path()) + self.assertFalse(FlowRegion().get_path()) + self.assertFalse(FlowRoot().get_path()) + self.assertFalse(FlowPara().get_path()) + self.assertFalse(FlowSpan().get_path()) + self.assertFalse(Tspan().get_path()) + + +class UseTest(ElementTestCase): + """Test extra functionality on a use element""" + + tag = "use" + + def test_path(self): + """Use path follows ref""" + self.assertEqual(str(self.elem.path), "M 0 0 L 10 10 Z") + + def test_empty_ref(self): + """An empty ref or None ref doesn't cause an error""" + use = Use() + use.set("xlink:href", "something") + self.assertRaises(FragmentError, getattr, use, "href") + elem = self.svg.add(Use()) + self.assertEqual(elem.href, None) + elem.set("xlink:href", "") + self.assertEqual(elem.href, None) + elem.set("xlink:href", "#badref") + self.assertEqual(elem.href, None) + elem.set("xlink:href", self.elem.get("xlink:href")) + self.assertEqual(elem.href.get("id"), "path1") + + def test_unlink(self): + """Test use tag unlinking""" + elem = self.elem.unlink() + self.assertEqual(str(elem.path), "M 0 0 L 10 10 Z") + self.assertEqual(elem.tag_name, "path") + self.assertEqual(elem.getparent().get("id"), "C") + + def test_unlink_xy(self): + """Check that unlink works if both transform and x, y are set on a clone""" + elem = self.svg.add(Use()) + elem.set("xlink:href", "path1") + elem.set("x", "100") + elem.set("y", "20") + elem.set("transform", "rotate(20,-100,100)") + elem2 = elem.unlink() + self.assertEqual(str(elem2.path), "M 0 0 L 10 10 Z") + self.assertEqual(elem2.tag_name, "path") + self.assertAlmostTuple( + tuple(elem2.transform.to_hexad()), + tuple(inkex.Transform("rotate(20,-206.71282,373.56409)").to_hexad()), + 3, + ) + + +class StopTests(ElementTestCase): + """Color stop tests""" + + black = Color("#000000") + grey50 = Color("#080808") + white = Color("#111111") + + def test_interpolate(self): + """Interpolate colours""" + stl1 = Style({"stop-color": self.black, "stop-opacity": 0.0}) + stop1 = Stop(offset="0.0", style=str(stl1)) + stl2 = Style({"stop-color": self.white, "stop-opacity": 1.0}) + stop2 = Stop(offset="1.0", style=str(stl2)) + stop3 = stop1.interpolate(stop2, 0.5) + assert stop3.style["stop-color"] == str(self.grey50) + assert float(stop3.style["stop-opacity"]) == pytest.approx(0.5, 1e-3) + + +class GradientTests(ElementTestCase): + """Gradient testing""" + + black = Color("#000000") + grey50 = Color("#080808") + white = Color("#111111") + + whiteop1 = Style({"stop-color": white, "stop-opacity": 1.0}) + blackop1 = Style({"stop-color": black, "stop-opacity": 1.0}) + whiteop0 = Style({"stop-color": white, "stop-opacity": 0.0}) + blackop0 = Style({"stop-color": black, "stop-opacity": 0.0}) + + translate11 = Transform("translate(1.0, 1.0)") + translate22 = Transform("translate(2.0, 2.0)") + + def test_parse(self): + """Gradients parsed from XML""" + values = [ + ( + LinearGradient, + {"x1": "0px", "y1": "1px", "x2": "2px", "y2": "3px"}, + {"x1": 0.0, "y1": 1.0, "x2": 2.0, "y2": 3.0}, + ), + ( + RadialGradient, + {"cx": "0px", "cy": "1px", "fx": "2px", "fy": "3px", "r": "4px"}, + {"cx": 0.0, "cy": 1.0, "fx": 2.0, "fy": 3.0}, + ), + ] + for classname, attributes, expected in values: + grad = classname(attrib=attributes) + grad.apply_transform() # identity transform + for key, value in expected.items(): + assert float(grad.get(key)) == pytest.approx(value, 1e-3) + grad = classname(attrib=attributes) + + grad = grad.interpolate(grad, 0.0) + for key, value in expected.items(): + assert float(parse_unit(grad.get(key))[0]) == pytest.approx(value, 1e-3) + + def test_apply_transform(self): + """Transform gradients""" + values = [ + ( + LinearGradient, + {"x1": 0.0, "y1": 0.0, "x2": 1.0, "y2": 1.0}, + {"x1": 1.0, "y1": 1.0, "x2": 2.0, "y2": 2.0}, + ), + ( + RadialGradient, + {"cx": 0.0, "cy": 0.0, "fx": 1.0, "fy": 1.0, "r": 1.0}, + {"cx": 1.0, "cy": 1.0, "fx": 2.0, "fy": 2.0, "r": 1.0}, + ), + ] + for classname, orientation, expected in values: + grad = classname().update(**orientation) + grad.gradientTransform = self.translate11 + grad.apply_transform() + val = grad.get("gradientTransform") + assert val is None + for key, value in expected.items(): + assert float(grad.get(key)) == pytest.approx(value, 1e-3) + + def test_stops(self): + """Gradients have stops""" + for classname in [LinearGradient, RadialGradient]: + grad = classname() + stops = [ + Stop().update(offset=0.0, style=self.whiteop0), + Stop().update(offset=1.0, style=self.blackop1), + ] + grad.add(*stops) + assert [s1.tostring() == s2.tostring() for s1, s2 in zip(grad.stops, stops)] + + def test_stop_styles(self): + """Gradients have styles""" + for classname in [LinearGradient, RadialGradient]: + grad = classname() + stops = [ + Stop().update(offset=0.0, style=self.whiteop0), + Stop().update(offset=1.0, style=self.blackop1), + ] + grad.add(*stops) + assert [str(s1) == str(s2.style) for s1, s2 in zip(grad.stop_styles, stops)] + + def test_get_stop_offsets(self): + """Gradients stop offsets""" + for classname in [LinearGradient, RadialGradient]: + grad = classname() + stops = [ + Stop().update(offset=0.0, style=self.whiteop0), + Stop().update(offset=1.0, style=self.blackop1), + ] + grad.add(*stops) + for stop1, stop2 in zip(grad.stop_offsets, stops): + self.assertEqual(float(stop1), pytest.approx(float(stop2.offset), 1e-3)) + + def test_interpolate(self): + """Gradients can be interpolated""" + values = [ + ( + LinearGradient, + {"x1": 0, "y1": 0, "x2": 1, "y2": 1}, + {"x1": 2, "y1": 2, "x2": 1, "y2": 1}, + {"x1": 1.0, "y1": 1.0, "x2": 1.0, "y2": 1.0}, + ), + ( + RadialGradient, + {"cx": 0, "cy": 0, "fx": 1, "fy": 1, "r": 0}, + {"cx": 2, "cy": 2, "fx": 1, "fy": 1, "r": 1}, + {"cx": 1.0, "cy": 1.0, "fx": 1.0, "fy": 1.0, "r": 0.5}, + ), + ] + for classname, orientation1, orientation2, expected in values: + # gradient 1 + grad1 = classname() + stops1 = [ + Stop().update(offset=0.0, style=self.whiteop0), + Stop().update(offset=1.0, style=self.blackop1), + ] + grad1.add(*stops1) + grad1.update(gradientTransform=self.translate11) + grad1.update(**orientation1) + + # gradient 2 + grad2 = classname() + stops2 = [ + Stop().update(offset=0.0, style=self.blackop1), + Stop().update(offset=1.0, style=self.whiteop0), + ] + grad2.add(*stops2) + grad2.update(gradientTransform=self.translate22) + grad2.update(**orientation2) + grad = grad1.interpolate(grad2, 0.5) + comp = Style({"stop-color": self.grey50, "stop-opacity": 0.5}) + self.assertEqual(str(grad.stops[0].style), str(Style(comp))) + self.assertEqual(str(grad.stops[1].style), str(Style(comp))) + self.assertEqual(str(grad.gradientTransform), "translate(1.5, 1.5)") + for key, value in expected.items(): + self.assertEqual( + float(parse_unit(grad.get(key))[0]), pytest.approx(value, 1e-3) + ) + + +class SymbolTest(ElementTestCase): + """Test Symbol elements""" + + source_file = "symbol.svg" + tag = "symbol" + + def test_unlink_symbol(self): + """Test unlink symbols""" + use = self.svg.getElementById("plane01") + self.assertEqual(use.tag_name, "use") + self.assertEqual(use.href.tag_name, "symbol") + # Unlinking should replace symbol with group + elem = use.unlink() + self.assertEqual(elem.tag_name, "g") + self.assertEqual(str(elem.transform), "translate(18, 16)") + self.assertEqual(elem[0].tag_name, "title") + self.assertEqual(elem[1].tag_name, "rect") + + +class DefsTest(ElementTestCase): + """Test the definitions tag""" + + source_file = "shapes.svg" + tag = "defs" + + def test_defs(self): + """Make sure defs can be seen in the nodes of an svg""" + self.assertTrue(isinstance(self.svg.defs, Defs)) + defs = self.svg.getElementById("defs33") + self.assertTrue(isinstance(defs, Defs)) + + +class StyleTest(ElementTestCase): + """Test a style tag""" + + source_file = "css.svg" + tag = "style" + + def test_style(self): + """Make sure style tags can be loaded and saved""" + css = self.svg.stylesheet + self.assertTrue(css) diff --git a/share/extensions/tests/test_inkex_elements_base.py b/share/extensions/tests/test_inkex_elements_base.py new file mode 100644 index 0000000..7ba38fa --- /dev/null +++ b/share/extensions/tests/test_inkex_elements_base.py @@ -0,0 +1,448 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test the element API base classes and basic functionality +""" +import random +from lxml import etree + +from inkex.elements import ( + load_svg, + ShapeElement, + Group, + Rectangle, + Tspan, + TextElement, + Line, +) +from inkex.elements._base import NodeBasedLookup, BaseElement +from inkex.transforms import Transform +from inkex.styles import Style +from inkex.utils import FragmentError +from inkex.tester import TestCase +from inkex.tester.svg import svg_file + + +class FakeShape(ShapeElement): # pylint: disable=abstract-method + """A protend shape""" + + tag_name = "fake" + + +class SvgTestCase(TestCase): + """Test SVG""" + + source_file = "complextransform.test.svg" + + def setUp(self): + super().setUp() + self.svg = svg_file(self.data_file("svg", self.source_file)) + + +class OverridenElementTestCase(SvgTestCase): + """Test element overriding functionality""" + + def test_tag_names(self): + """ + Test tag names for custom and unknown tags + """ + doc = load_svg( + """ + + + Unknown SVG tag + +""" + ) + svg = doc.getroot() + + good = svg.getElementById("good") + self.assertEqual(good.TAG, "g") + bad = svg.getElementById("bad") + self.assertEqual(bad.TAG, "badsvg") + ugly = svg.getElementById("ugly") + self.assertEqual(ugly.TAG, "othertag") + + def test_reference_count(self): + """ + Test inkex.element.BaseElement-derived object type is preserved on adding to group + + See https://gitlab.com/inkscape/extensions/-/issues/81 for details + """ + grp = Group() + for _ in range(10): + rect = Rectangle() + grp.add(rect) + + for elem in grp: + self.assertEqual(type(elem), Rectangle) + + def test_class_lookup(self): + """Can we find element classes with simple xpaths""" + self.assertEqual(NodeBasedLookup.find_class("svg:rect"), Rectangle) + self.assertEqual(NodeBasedLookup.find_class("//svg:svg/svg:g"), Group) + self.assertRaises(KeyError, NodeBasedLookup.find_class, "svg:g[layer]") + + def test_abstract_raises(self): + """Abstract classes cannot be instantiated""" + self.assertRaises(NotImplementedError, FakeShape().get_path) + self.assertRaises(AttributeError, FakeShape().set_path, None) + + def test_add(self): + """Can add single or multiple elements with passthrough""" + elem = self.svg.getElementById("D") + group = elem.add(Group(id="foo")) + self.assertEqual(group.get("id"), "foo") + groups = elem.add(Group(id="f1"), Group(id="f2")) + self.assertEqual(len(groups), 2) + self.assertEqual(groups[0].get("id"), "f1") + self.assertEqual(groups[1].get("id"), "f2") + + def test_creation(self): + """Create elements with attributes""" + group = Group().update(inkscape__label="Foo") + self.assertEqual(group.get("inkscape:label"), "Foo") + group = Group().update(inkscape__label="Bar") + self.assertEqual(group.label, "Bar") + + def test_tostring(self): + """Elements can be printed as strings""" + self.assertEqual(Group().tostring(), b"") + elem = Group(id="bar") + path = elem.add(Tspan(id="foo")) + elem.transform.add_translate(50, 50) + path.style["fill"] = "red" + self.assertEqual( + elem.tostring(), + b'', + ) + + +class AttributeHandelingTestCase(SvgTestCase): + """Test how attributes are handled""" + + def test_chained_multiple_attrs(self): + """Set multiple attributes at a time""" + group = Group().update(attr1="A", attr2="B").update(attr3="C", attr4="D") + self.assertEqual(group.get("attr1"), "A") + self.assertEqual(group.get("attr2"), "B") + self.assertEqual(group.get("attr3"), "C") + self.assertEqual(group.get("attr4"), "D") + + # remove attributes, setting them to None + group.update(attr1=None, attr4=None) + + self.assertEqual(group.get("attr1"), None) + self.assertEqual(group.get("attr2"), "B") + self.assertEqual(group.get("attr3"), "C") + self.assertEqual(group.get("attr4"), None) + + self.assertEqual(group.pop("attr2"), "B") + self.assertEqual(group.pop("attr3"), "C") + + def test_set_wrapped_attribute(self): + """Remove wrapped attribute using .set()""" + group = Group().update(transform=Transform(scale=2)) + self.assertEqual(group.transform.matrix[0][0], 2) + self.assertEqual(group.transform.matrix[1][1], 2) + + group.update(transform=None) + self.assertEqual(group.transform, Transform()) + + def test_pop_wrapped_attribute(self): + """Remove wrapped attribute using .pop()""" + group = Group() + + self.assertEqual(group.pop("transform"), Transform()) + + group.update(transform=Transform(scale=2)) + self.assertEqual(group.pop("transform"), Transform(scale=2)) + self.assertEqual(group.pop("transform"), Transform()) + self.assertRaises(AttributeError, getattr, group, "foo") + + def test_pop_regular_attribute(self): + """Remove wrapped attribute using .pop()""" + group = Group() + + self.assertEqual(group.get("attr1"), None) + + group.update(attr1="42") + self.assertEqual(group.pop("attr1"), "42") + self.assertEqual(group.pop("attr1"), None) + + def test_update_consistant(self): + """Update doesn't keep callbacks around""" + elem = self.svg.getElementById("D") + tr_a = Transform(translate=(10, 10)) + tr_b = Transform(translate=(-20, 15)) + elem.transform = tr_a + elem.transform = tr_b + self.assertEqual(str(elem.transform), "translate(-20, 15)") + tr_a.add_translate(10, 10) + self.assertEqual(str(elem.transform), "translate(-20, 15)") + elem.set("transform", None) + self.assertEqual(elem.get("transform"), None) + + def test_in_place_style(self): + """Do styles update when we set them""" + elem = self.svg.getElementById("D") + elem.style["fill"] = "purple" + self.assertEqual(elem.get("style"), "fill:purple") + elem.style = {"stroke-dashoffset": "1"} + self.assertEqual(elem.get("style"), "stroke-dashoffset:1") + elem.style = Style(stroke="red") + self.assertEqual(elem.get("style"), "stroke:red") + elem.style.update("grape:2;strawberry:nice;") + self.assertEqual(elem.get("style"), "stroke:red;grape:2;strawberry:nice") + + def test_random_id(self): + """Test setting a random id""" + elem = self.svg.getElementById("D") + elem.set_random_id("Thing") + self.assertEqual(elem.get("id"), "Thing5815") + elem.set_random_id("Thing", size=2) + self.assertEqual(elem.get("id"), "Thing85") + elem.set_random_id() + self.assertEqual(elem.get("id"), "path5392") + # No document root, no random id allowed + self.assertRaises(FragmentError, elem.copy().set_random_id) + + def test_random_ids(self): + """Test setting a tree of ids""" + elem = self.svg.getElementById("D") + self.svg.set_random_ids(prefix="TreeItem") + self.assertEqual(self.svg.get("id"), "TreeItem5815") + self.assertEqual(self.svg[0].get("id"), "TreeItem8555") + self.assertEqual(elem.get("id"), "TreeItem2036") + + def test_set_id_backlinks(self): + """Changing an id can update backlinks""" + elem = self.svg.getElementById("path1") + rect1 = Rectangle() + rect1.set("clip-path", "url(#path1)") + rect2 = Rectangle() + rect2.set("mask", "url(#path1)") + elem.addnext(rect1) + self.svg.getElementById("G").add(rect2) + elem.set_id("plant54", True) + self.assertEqual(self.svg.getElementById("G").get("xlink:href"), "#plant54") + self.assertEqual(self.svg.getElementById("G").href, elem) + self.assertEqual( + str(self.svg.getElementById("B").style), "fill:#eee;joker:url(#plant54)" + ) + self.assertEqual(rect1.get("clip-path"), "url(#plant54)") + self.assertEqual(rect2.get("mask"), "url(#plant54)") + + def test_set_id_blacklist(self): + """Test that the set_random_id function respects a blacklist""" + elem: BaseElement = self.svg.getElementById("D") + + state = random.getstate() + elem.set_random_id("Thing") + self.assertEqual(elem.get("id"), "Thing5815") + random.setstate(state) + elem.set_random_id("Other", blacklist=["Other5815"]) + self.assertEqual(elem.get("id"), "Other8555") + + def test_get_element_by_name(self): + """Get elements by name""" + self.assertEqual(self.svg.getElementByName("Key").get("id"), "K") + self.assertEqual(self.svg.getElementByName("Elm", "svg:g").get("id"), "L") + self.assertEqual(self.svg.getElementByName("Mine").get("id"), "M") + self.assertEqual(self.svg.getElementByName("doesntexist"), None) + self.assertEqual(self.svg.getElementByName("Key", "rect"), None) + + def test_insensitive(self): + """Element inkscape sensitivity""" + elem = self.svg.getElementByName("Key") + self.assertTrue(elem.is_sensitive()) + elem.set_sensitive(False) + self.assertFalse(elem.is_sensitive()) + self.assertEqual(elem.get("sodipodi:insensitive"), "true") + elem.set_sensitive(True) + self.assertTrue(elem.is_sensitive()) + self.assertEqual(elem.get("sodipodi:insensitive"), None) + + def test_title_description(self): + """Adding a description to an element""" + + def _content(elem): + return tuple(f"{child.TAG}:{child.text}" for child in elem) + + self.svg.getElementById("K").title = "Before" + elem = self.svg.getElementById("L") + elem.desc = "Dancing" + elem.title = "Start" + self.assertEqual(elem.desc, "Dancing") + self.assertEqual(elem.title, "Start") + self.svg.getElementById("G").title = "After" + # Title and Desc elements have been added + self.assertEqual(_content(elem), ("title:Start", "desc:Dancing", "line:None")) + # No extra elements created, no conflicts. + elem.title = "Stop" + self.assertEqual(_content(elem), ("title:Stop", "desc:Dancing", "line:None")) + # Deletion works too, try twice so we know it doesn't error on not-found + del elem.desc + del elem.desc + self.assertEqual(_content(elem), ("title:Stop", "line:None")) + + +class TransformationTestCase(SvgTestCase): + """Test transformative functions""" + + def test_bounding_box(self): + """Elements can have bounding boxes""" + elem = self.svg.getElementById("D") + self.assertEqual(tuple(elem.bounding_box()), ((60.0, 100.0), (130.0, 170.00))) + self.assertTrue(elem.bounding_box().center.is_close((80.0, 150.0))) + self.assertEqual( + tuple(TextElement(x="10", y="5").bounding_box()), ((10, 10), (5, 5)) + ) + group = Group(elem) + self.assertEqual(elem.bounding_box(), group.bounding_box()) + + def test_transform(self): + """In-place modified transforms are retained""" + elem = self.svg.getElementById("D") + self.assertEqual(str(elem.transform), "translate(30, 10)") + elem.transform.add_translate(-10, 10) + self.assertEqual(str(elem.transform), "translate(20, 20)") + + def test_scale(self): + """In-place scaling from blank transform""" + elem = self.svg.getElementById("F") + self.assertEqual(elem.transform, Transform()) + self.assertEqual(elem.get("transform"), None) + elem.transform.add_scale(1.0666666666666667, 1.0666666666666667) + self.assertEqual(elem.get("transform"), Transform(scale=1.06667)) + self.assertIn(b"transform", etree.tostring(elem)) + + def test_in_place_transforms(self): + """Do style and transforms update correctly""" + elem = self.svg.getElementById("D") + self.assertEqual(type(elem.transform), Transform) + self.assertEqual(type(elem.style), Style) + self.assertTrue(elem.transform) + elem.transform = Transform() + self.assertEqual(elem.transform, Transform()) + self.assertEqual(elem.get("transform"), None) + self.assertNotIn(b"transform", etree.tostring(elem)) + elem.transform.add_translate(10, 10) + self.assertIn(b"transform", etree.tostring(elem)) + elem.transform.add_translate(-10, -10) + self.assertNotIn(b"transform", etree.tostring(elem)) + + +class RelationshipTestCase(SvgTestCase): + """Test relationships between elements""" + + def test_findall(self): + """Findall elements in svg""" + groups = self.svg.findall("svg:g") + self.assertEqual(len(groups), 1) + + def test_copy(self): + """Test copying elements""" + elem = self.svg.getElementById("D") + cpy = elem.copy() + self.assertFalse(cpy.getparent()) + self.assertFalse(cpy.get("id")) + + def test_duplicate(self): + """Test duplicating elements""" + elem = self.svg.getElementById("D") + dup = elem.duplicate() + self.assertTrue(dup.get("id")) + self.assertNotEqual(elem.get("id"), dup.get("id")) + self.assertEqual(elem.getparent(), dup.getparent()) + + def test_duplicate_group(self): + """Check that when duplicating a group, all ids are replaced + (Issue https://gitlab.com/inkscape/extensions/-/issues/379)""" + elem: BaseElement = self.svg.getElementById("A") + dup = elem.duplicate() + elem_ids = [i.get_id() for i in elem.iter() if hasattr(i, "get_id")] + dup_ids = [i.get_id() for i in dup.iter() if hasattr(i, "get_id")] + + in_both = [i for i in elem_ids if i in dup_ids] + + self.assertListEqual(in_both, []) + + def test_replace_with(self): + """Replacing nodes in a tree""" + rect = self.svg.getElementById("E") + path = rect.to_path_element() + rect.replace_with(path) + self.assertEqual(rect.getparent(), None) + self.assertEqual(path.getparent(), self.svg.getElementById("C")) + + def test_descendants(self): + """Elements can walk their descendants""" + self.assertEqual( + tuple(self.svg.descendants().ids), + ( + "mydoc", + "path1", + "base", + "metadata7", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + ), + ) + get = self.svg.getElementById + self.assertEqual(tuple(get("L").descendants().ids), ("L", "M")) + self.assertEqual(tuple(get("M").descendants().ids), ("M",)) + + def test_deep_descendants(self): + """Create a very deep svg and test getting decendants""" + svg = '' + for i in range(1000): + svg += f'' + svg = load_svg(svg + ("" * 1000) + "").getroot() + + self.assertEqual( + tuple(svg.descendants().ids), tuple(str(i) for i in range(1000)) + ) + self.assertEqual( + tuple(svg.getElementById("998").descendants().ids), ("998", "999") + ) + self.assertEqual(tuple(svg.getElementById("999").descendants().ids), ("999",)) + + def test_ancestors(self): + """Element descendants of elements""" + get = self.svg.getElementById + self.assertEqual(tuple(get("M").ancestors().ids), ("L", "K", "A", "mydoc")) + self.assertEqual( + tuple(get("M").ancestors(stop_at=[None]).ids), ("L", "K", "A", "mydoc") + ) + self.assertEqual(tuple(get("M").ancestors(stop_at=[get("K")]).ids), ("L", "K")) + self.assertEqual(tuple(get("M").ancestors(stop_at=[get("L")]).ids), ("L",)) + + def test_deep_ancestors(self): + """Create a very deep svg and test getting ancestors""" + svg = '' + for i in range(1000): + svg += f'' + svg = load_svg(svg + ("" * 1000) + "").getroot() + self.assertEqual( + tuple(svg.getElementById("999").ancestors().ids), + tuple(str(i) for i in range(998, -1, -1)), + ) + + def test_luca(self): + """Test last common ancestor""" + get = self.svg.getElementById + self.assertEqual(tuple(get("M").ancestors(get("M")).ids), ("L",)) + self.assertEqual(tuple(get("G").ancestors(get("H")).ids), ("C",)) + self.assertEqual(tuple(get("M").ancestors(get("H")).ids), ("L", "K", "A")) diff --git a/share/extensions/tests/test_inkex_elements_filters.py b/share/extensions/tests/test_inkex_elements_filters.py new file mode 100644 index 0000000..f034d53 --- /dev/null +++ b/share/extensions/tests/test_inkex_elements_filters.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test the filter elements functionality +""" +from inkex.tester import TestCase +from inkex.tester.svg import svg_file + + +class GradientTestCase(TestCase): + source_file = "gradient_with_mixed_offsets.svg" + + def setUp(self): + super().setUp() + self.svg = svg_file(self.data_file("svg", self.source_file)) + + def test_gradient_offset_order(self): + _gradient = self.svg.getElementById("MyGradient") + offsets = [stop.attrib.get("offset") for stop in _gradient.stops] + assert offsets == ["0%", "100%", "50"] diff --git a/share/extensions/tests/test_inkex_elements_selections.py b/share/extensions/tests/test_inkex_elements_selections.py new file mode 100644 index 0000000..b9d3d2c --- /dev/null +++ b/share/extensions/tests/test_inkex_elements_selections.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test all selection code. +""" + +from inkex.elements import PathElement, Circle, Rectangle +from inkex.elements._selected import ElementList + +from .test_inkex_elements_base import SvgTestCase +from inkex.utils import AbortExtension + + +class ElementListTestCase(SvgTestCase): + """Test Element Selections""" + + def setUp(self): + super().setUp() + self.svg.selection.set("G", "B", "D", "F") + + def test_creation(self): + """Creating an elementList""" + empty = ElementList(self.svg) + self.assertEqual(tuple(empty.ids), ()) + self.assertEqual(empty.first(), None) + lst = ElementList(self.svg, "ABC") + self.assertEqual(tuple(lst.ids), ("A", "B", "C")) + + def test_to_dict(self): + """test dictionary compact""" + self.assertEqual(tuple(self.svg.selection.id_dict()), ("G", "B", "D", "F")) + + def test_getitem(self): + """Can get an item""" + self.assertEqual(self.svg.selection["B"].xml_path, "/*/*[4]/*[1]") + self.assertRaises(KeyError, self.svg.selection.__getitem__, "A") + + def test_svg_selection(self): + """Setting an svg selection""" + self.assertEqual(tuple(self.svg.selection.ids), ("G", "B", "D", "F")) + + def test_rendering_order(self): + """Test paint order""" + items = self.svg.selection.rendering_order() + self.assertTrue(isinstance(items, ElementList)) + self.assertEqual(tuple(items.ids), ("B", "D", "F", "G")) + + def test_set_nothing(self): + """Clear existing selection""" + self.svg.selection.set() + self.assertEqual(tuple(self.svg.selection), ()) + + def test_set_ids(self): + """Set a new selection element ids""" + a_to_g = "ABCDEFG" + self.svg.selection.set(*a_to_g) + self.assertEqual(tuple(self.svg.selection.ids), tuple(a_to_g)) + + def test_set_elements(self): + """Set a new selection from element objects""" + a_to_g = "ABCDEFG" + self.svg.selection.set(*[self.svg.getElementById(eid) for eid in a_to_g]) + self.assertEqual(tuple(self.svg.selection.ids), tuple(a_to_g)) + self.assertRaises(ValueError, self.svg.selection.add, None) + self.assertRaises( + ValueError, + self.svg.selection.__setitem__, + "A", + self.svg.getElementById("B"), + ) + + def test_set_xpath(self): + """Set a new selection from xpath""" + self.svg.selection.set("//svg:g") + self.assertEqual(tuple(self.svg.selection.ids), tuple("ABCKL")) + + def test_set_invalid_ids(self): + """Set invalid ids""" + self.svg.selection.set("X", "Y", "Z", "A") + self.assertEqual(tuple(self.svg.selection.ids), ("A",)) + + def test_pop_items(self): + """Can remove items from the ElementList""" + selection = self.svg.selection + self.assertEqual(tuple(selection.ids), ("G", "B", "D", "F")) + ret = selection.pop() + self.assertEqual(ret.get("id"), "F") + self.assertEqual(tuple(selection.ids), ("G", "B", "D")) + selection.pop(0) + self.assertEqual(tuple(selection.ids), ("B", "D")) + selection.pop("B") + self.assertEqual(tuple(selection.ids), ("D",)) + self.assertRaises(KeyError, selection.pop, "B") + selection.set(*"ABDFH") + self.assertEqual(tuple(selection.ids), ("A", "B", "D", "F", "H")) + selection.pop(selection.first()) + self.assertEqual(tuple(selection.ids), ("B", "D", "F", "H")) + + def test_filtering(self): + """Create a sub-list of selected items""" + selection = self.svg.descendants() + new_list = selection.filter(PathElement) + self.assertEqual(tuple(new_list.ids), ("path1", "D")) + + def test_filternonzero(self): + """Filter and raise an AbortException if the list is empty""" + selection = self.svg.descendants() + new_list = selection.filter(PathElement) + # default error message + with self.assertRaisesRegex(AbortExtension, "Circle.*Rectangle"): + new_list.filter_nonzero(Circle, Rectangle) + # custom error message + with self.assertRaisesRegex(AbortExtension, "test string"): + new_list.filter_nonzero(Circle, error_msg="test string") + self.assertEqual(new_list, selection.filter_nonzero(PathElement)) + + def test_getting_recursively(self): + """Create a list of children of the given type""" + selection = self.svg.selection + selection.set("B") + self.assertEqual(tuple(selection.ids), ("B",)) + self.assertEqual(tuple(selection.get().ids), tuple("BCDEFGHIJ")) + + def test_get_bounding_box(self): + """Selection can get a bounding box""" + self.assertEqual(int(self.svg.selection.bounding_box().width), 540) + self.assertEqual(int(self.svg.selection.bounding_box().height), 550) + + def test_selecting_weird_ids(self): + """Selection can contain some chars""" + selection = self.svg.selection + self.svg.append(PathElement(id="#asdf")) + selection.set("#asdf") + self.assertEqual(tuple(selection.ids), ("#asdf",)) diff --git a/share/extensions/tests/test_inkex_extensions.py b/share/extensions/tests/test_inkex_extensions.py new file mode 100644 index 0000000..56474c9 --- /dev/null +++ b/share/extensions/tests/test_inkex_extensions.py @@ -0,0 +1,69 @@ +# coding=utf-8 +""" +Test each of the extensions base classes (if needed) and sometimes provide +specialised test classes for testers to use. +""" +import inkex +from inkex.tester import ComparisonMixin, TestCase + + +class TurnGreenEffect(inkex.ColorExtension): + """Turn everything the purest green!""" + + def modify_color(self, name, color): + return inkex.Color("green") + + def modify_opacity(self, name, opacity): + if name == "opacity": + return 1.0 + return opacity + + +class ColorEffectTest(ComparisonMixin, TestCase): + """Direct tests for color mechanisms""" + + effect_class = TurnGreenEffect + effect_name = "inkex_extensions_color" + compare_file = "svg/colors.svg" + python3_only = True + + comparisons = [ + ("--id=r1",), # One shape only + ("--id=r2",), # CSS Styles + ("--id=r3",), # Element Attributes + ("--id=r4",), # Gradient stops + ("--id=r1", "--id=r2"), # Two shapes + ("--id=color_svg",), # Recursive group/children + (), # Process all shapes + ] + + +class ColorBaseCase(TestCase): + """Base class for all color effect extensions""" + + color_tests = [] + opacity_tests = [] + + def _test_list(self, tsts): + for tst in tsts: + inp, outp, args = (list(tst) + [[]])[:3] + self.effect.parse_arguments([self.empty_svg] + args) + yield inp, outp + + def test_colors(self): + """Run all color tests""" + for x, (inp, outp) in enumerate(self._test_list(self.color_tests)): + outp = inkex.Color(outp) + got = self.effect._modify_color("fill", inkex.Color(inp)) + self.assertTrue( + isinstance(got, inkex.Color), + "Bad output type: {}".format(type(got).__name__), + ) + outp, got = str(outp), str(got.to(outp.space)) + self.assertEqual( + outp, got, "Color mismatch, test:{} {} != {}".format(x, outp, got) + ) + for x, (inp, outp) in enumerate(self._test_list(self.opacity_tests)): + got = self.effect.modify_opacity("opacity", inp) + self.assertTrue(isinstance(got, float)) + self.assertAlmostEqual(got, outp, delta=0.1) diff --git a/share/extensions/tests/test_inkex_extensions_GenerateExtension.py b/share/extensions/tests/test_inkex_extensions_GenerateExtension.py new file mode 100644 index 0000000..9c125dd --- /dev/null +++ b/share/extensions/tests/test_inkex_extensions_GenerateExtension.py @@ -0,0 +1,41 @@ +# coding=utf-8 +""" +Test the inkex.GenerateExtension class. +""" +import inkex +from inkex.tester import TestCase + + +class MyGenerateExtension(inkex.GenerateExtension): + TEST_ITEM_ATTRIBS = { + "transform": "rotate(123)", + "d": "M3,4L5,6", + "id": "yielded_test_item", + } + + def generate(self): + yield inkex.PathElement(**self.TEST_ITEM_ATTRIBS) + + +class TestExtensionGenerate(TestCase): + effect_class = MyGenerateExtension + + def test_layer_transform(self): + effect = self.assertEffect("svg", "transformed-layer.svg") + item = effect.svg.getElementById(MyGenerateExtension.TEST_ITEM_ATTRIBS["id"]) + parent = item.getparent() + + # expect that generated items have not been modified + for key, value in MyGenerateExtension.TEST_ITEM_ATTRIBS.items(): + self.assertEqual(item.get(key), value) + + # expect a new parent group which is a child of the current layer + self.assertEqual(parent.getparent().get("id"), "inner_layer") + + # expect that the parent group compensates the transform of the current + # layer and is positioned at the current view center + self.assertTransformEqual( + parent.get("transform"), + "scale(0.5) translate(-20,-30) rotate(-30) translate(100,300)", + 3, + ) diff --git a/share/extensions/tests/test_inkex_gui.py b/share/extensions/tests/test_inkex_gui.py new file mode 100644 index 0000000..cd4093c --- /dev/null +++ b/share/extensions/tests/test_inkex_gui.py @@ -0,0 +1,174 @@ +# coding=utf-8 +# +# Copyright 2022 Martin Owens +# +# 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 3 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, see +# +""" +Test GUI App, running main loops and threading from and to them. + +Do NOT copy this test if you are looking for examples of how to write +unit tests for your GUI enabled inkscape extensions. This code contains +a lot of weird and confusing checking of loops and process running. +""" + +import os +import sys +import time +import pytest + +from inkex.tester import TestCase +from inkex.utils import DependencyError + +try: + from inkex.gui.tester import MainLoopProtection + from inkex.gui.listview import label + from inkex.gui import GtkApp, Window, asyncme + from gi.repository import Gtk, GLib + +except DependencyError: + Window = object + GtkApp = None + + class asyncme: + run_or_none = classmethod(lambda a, f: f) + run_or_wait = classmethod(lambda a, f: f) + mainloop_only = classmethod(lambda a, f: f) + + +class LoopyWindow(Window): + """A testing window with various loops""" + + def realized(self, widget=None): + """Called by the window's realise signal, see glade ui xml""" + # Spawn a thread to do something without locking up the UI + self.thread_action() + # Add a function to the GLib main loop manually + GLib.idle_add(self.loop_action) + + def loop_action(self): + """Called while we are in the idle loop""" + # Test Mainloop to mainloop doesn't lock up. + assert "pancakes" == self.get_pancakes() + time.sleep(0.2) + # Run some useful action we might want to test + self.in_loop_action() + # We actually want to quit to make the test faster + if self.gapp.exit() is None: + return True # Run again + return False + + def in_loop_action(self): + """Defined by the test loader if needed""" + pass + + @asyncme.run_or_none + def thread_action(self): + """Run in a different thread from Gtk""" + self.in_thread_action() + + @asyncme.run_or_wait + def in_thread_action(self): + """Defined by the test loader if needed""" + pass + + @asyncme.mainloop_only + def get_pancakes(self): + """ + A call which always runs in the mainloop, + even if not called from one. + """ + return "pancakes" + + def test_signal(self, widget=None): + """A signal from Gtk widgets defined in the glade xml""" + if widget: + pass + + +@pytest.mark.skipif(GtkApp is None, reason="PyGObject is required") +class GtkAppTest(TestCase): + """Tests for GUI App""" + + def construct_app(self, windows=(), ui_file="app-test"): + """Create a gtk app based on some inputs""" + return type( + "_GtkApp", + (GtkApp,), + { + "app_name": "application-test", + "windows": list(windows), + "ui_dir": self.datadir(), + "prefix": "ui", + "ui_file": ui_file, + }, + ) + + def construct_window(self, name, **kwargs): + return type("_GtkWindow", (LoopyWindow,), {"name": name, **kwargs}) + + def test_app_errors(self): + """Various consruction errors""" + self.assertRaises(NotImplementedError, GtkApp) + bad_win = self.construct_window("bad-window") + bad_app = self.construct_app([bad_win], ui_file="bad-file") + self.assertRaises(FileNotFoundError, bad_app) + self.assertRaises(KeyError, self.construct_app()) + good_win = self.construct_window("basic_app") + good_app = self.construct_app([good_win])() + self.assertRaises(KeyError, good_app.load_window, "no-window") + + def test_args(self): + """Test app arguments""" + self.assertEqual(label(4), "int") + self.assertEqual(label((4, 5)), "int or int") + GtkApp( + app_name="inline-app", + ui_dir=self.datadir(), + prefix="ui", + ui_file="app-test", + windows=[self.construct_window("basic_app")], + ) + + def test_app_inline_run(self): + """Test a basic gui loop""" + cls = self.construct_app([self.construct_window("basic_app")]) + with MainLoopProtection(): + cls(start_loop=True) + + def test_app_outside_run(self): + """Test various threading in and out of Gtk""" + other_win = self.construct_window("basic_app") + + def _thread(self): + self.looped = self.widget("button1").get_label() + + def _loop(self, widget=None): + self.gapp.remove_window(other_win(self.gapp)) + self.gapp.remove_window(self) + + app = self.construct_app( + [ + self.construct_window( + "basic_app", + in_loop_action=_loop, + in_thread_action=asyncme.mainloop_only(_thread), + ) + ] + )() + with MainLoopProtection(): + app.run() + + # Threading doesn't work in the CI builder, disabled for now. + # self.assertEqual(app._primary.looped, 'gtk-apply') diff --git a/share/extensions/tests/test_inkex_gui_asyncme.py b/share/extensions/tests/test_inkex_gui_asyncme.py new file mode 100644 index 0000000..45e317c --- /dev/null +++ b/share/extensions/tests/test_inkex_gui_asyncme.py @@ -0,0 +1,124 @@ +# +# Copyright 2015 Ian Denhardt +# 2022 Martin Owens +# +# 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 3 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, see +# +""" +Test async threading code +""" + +import sys +import time +import pytest +import threading + +from inkex.tester import TestCase +from inkex.utils import DependencyError + +try: + from inkex.gui import asyncme +except DependencyError: + asyncme = None + + +@pytest.mark.skipif(asyncme is None, reason="PyGObject is required") +class AsyncTest(TestCase): + """Test the gui async code""" + + def test_basic(self): + """Basic waiting""" + future = asyncme.Future() + self.assertFalse(future.is_ready()) + + def do_result(): + future.result("ok") + + thread = asyncme.spawn_thread(do_result) + self.assertEqual(future.wait(), "ok") + self.assertTrue(future.is_ready()) + thread.join() + + def test_exception(self): + """Exception handling""" + + def do_exception(): + raise IOError("It broke!") + + future = asyncme.Future() + future.run(do_exception) + self.assertRaises(IOError, future.wait) + + def test_holding(self): + self._test_holding(True, 0.5, 4) + self._test_holding(False, 2, 1000) + + def _test_holding(self, blocking, delay, count): + """Test holding for a delay""" + lock = threading.Lock() + shared_var = [0] + + def do_thread(): + self.assertEqual(shared_var[0], 0) + shared_var[0] += 1 + time.sleep(delay) + self.assertEqual(shared_var[0], 1) + shared_var[0] -= 1 + + results = [] + for i in range(count): + results.append(asyncme.holding(lock, do_thread, blocking)) + + for r in results: + if r is not None: + r.wait() + + def test_debounce(self): + """Put DebounceSyncVar through its paces + + We create a dsv and with a delay of 1 second and launch two threads + in parallel. One thread collects values from the dsv repeatedly. + The other submits ten values, the first five with replace(), the rest + with put(). + + Unless the machine this is running on is very slow, the final result + should be the last value that was inserted via replace(), followed by + all of the values inserted with put(); The one-second delay guarantees + that the first four values will be overwritten. + + This should take about 6 seconds to run. + """ + dsv = asyncme.DebouncedSyncVar(2) + dsv.set_delay(1) + + def do_replace_put(): + for i in range(0, 5): + dsv.replace(i) + for i in range(5, 10): + dsv.put(i) + + future = asyncme.Future() + + def do_get(): + result = [] + i = 0 + while i < 9: + i, _ok = dsv.get() + result.append(i) + future.result(result) + + asyncme.spawn_thread(do_replace_put) + asyncme.spawn_thread(do_get) + result = future.wait() + self.assertEqual(result, list(range(4, 10))) diff --git a/share/extensions/tests/test_inkex_gui_listview.py b/share/extensions/tests/test_inkex_gui_listview.py new file mode 100644 index 0000000..67837a8 --- /dev/null +++ b/share/extensions/tests/test_inkex_gui_listview.py @@ -0,0 +1,253 @@ +# coding=utf-8 +# +# Copyright 2022 Martin Owens +# +# 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 3 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, see +# +""" +Test the ListView and TreeView features. +""" + +import os +import sys +import time +import pytest + +from inkex.tester import TestCase +from inkex.utils import DependencyError + +try: + from inkex.gui import GtkApp, Window + from inkex.gui.pixmap import PixmapManager + from inkex.gui.listview import ( + TreeView, + IconView, + ComboBox, + ViewSort, + ViewColumn, + Separator, + ) + from gi.repository import Gtk, Gdk, GLib +except DependencyError: + Window = object + GtkApp = None + + +class DataItem: + def __init__(self, name): + self.name = name + self.icon = "edit-find" + + def get_id(self): + return str(self.name).lower() + + def __repr__(self): + return f"" + + def get_name(self): + return self.name + + +class ListWindow(Window): + name = "listing_app" + + def realized(self, widget=None): + """Called by the window's realise signal, see glade ui xml""" + # Add a function to the GLib main loop manually + GLib.idle_add(self.loop_action) + + def loop_action(self): + """Called while we are in the idle loop""" + time.sleep(0.2) + if self.gapp.exit() is None: + return True # Run again + return False + + def select_tree(self, tree): + """Select some items""" + items = [a for a, b, c in tree] + tree.set_selected_items(*items[:2]) + + +@pytest.mark.skipif(GtkApp is None, reason="PyGObject is required") +class GtkListTest(TestCase): + """Tests all treeview types""" + + def setUp(self): + self.app = GtkApp( + app_name="listapp", + windows=(ListWindow,), + ui_dir=self.datadir(), + prefix="ui", + ui_file="listing-app", + ) + self.window = self.app.window + self.tree = self.window.widget("tree1") + self.icon = self.window.widget("icon1") + self.combo = self.window.widget("combo1") + self.pixmaps = PixmapManager(self.datadir()) + + def test_errors(self): + self.assertRaises(TypeError, TreeView, self.icon) + self.assertRaises(TypeError, TreeView, self.tree, liststore="pig") + self.assertRaises(TypeError, IconView, self.tree) + + def test_treeview(self): + """Test TreeView Controls""" + + def sel(item): + pass + + def unsel(item): + pass + + tv1 = TreeView(self.tree, selected=sel, unselected=unsel) + parent = tv1.add_item(DataItem("green")) + item1 = DataItem("blue") + item2 = DataItem("vase") + tv1.add([item1, item2], parent) + self.assertTrue(tv1.get_iter(item1)) + self.assertTrue(tv1.get_iter(item2)) + self.assertRaises(ValueError, tv1.add_item, item1) + self.assertEqual(len(list(tv1)), 3) + + tv1.set_selected_items(parent) + self.assertTrue(tv1.is_selected(parent)) + self.assertFalse(tv1.is_selected(item1)) + self.assertTrue(tv1.get_selected_items()) + + item3 = DataItem("red") + tv1.replace(item3, tv1.get_iter(item2)) + self.assertTrue(tv1.get_model()) + + tv1.expand_item(item1) + + self.assertRaises(ValueError, tv1.add_item, None) + + tv1.refresh() + tv1.item_selected_signal() + tv1.item_button_clicked(None, None) + Gtk.main_iteration() + + def test_iconview(self): + """Test special icon view""" + iv1 = IconView(self.icon, self.pixmaps) + item1 = DataItem("red") + iv1.add_item(item1) + iv1.add_item(DataItem("yellow")) + iv1.add([DataItem("policebox"), DataItem("scarf")]) + iv1.set_selected_item(item1) + + iv1.replace(DataItem("purse")) + self.assertEqual(len(list(iv1)), 1) + self.assertTrue(iv1.get_model()) + iv1.item_selected_signal() + + self.assertRaises(ValueError, iv1.add_item, None) + + def test_combobox(self): + """Tst special combo box""" + item = DataItem("pea") + combo = ComboBox(self.combo) + combo.add_item(item) + combo.set_selected_item(item) + self.assertTrue(combo.is_selected(item)) + self.assertTrue(combo.get_selected_item()) + + col = combo.create_column("Bold", expand=True) + col.add_text_renderer("name", wrap=True) + + def test_sort(self): + """Test list sorting""" + tv2 = TreeView(self.tree) + tv2.add_item(DataItem("Bat")) + tv2.add_item(DataItem("Ant")) + tv2.add_item(DataItem("Cat")) + tv2.add_item(DataItem("Dog")) + tv2.add_item(DataItem("0")) + tv2.add_item(DataItem(None)) + + def ids(): + return [item.get_id()[0] for item, *_ in tv2] + + sorter = tv2.create_sort(data="name", ascending=False) + self.assertEqual(ids(), ["0", "a", "b", "c", "d", "n"]) + + sorter = tv2.create_sort(data="name", ascending=True) + self.assertEqual(ids(), ["d", "c", "b", "a", "0", "n"]) + + sorter = tv2.create_sort(data="name", exact="bat") + self.assertEqual(ids(), ["b", "d", "c", "a", "0", "n"]) + + sorter = tv2.create_sort(data="name", contains="at") + self.assertEqual(ids(), ["b", "c", "d", "a", "0", "n"]) + + def test_sort_func(self): + tv3 = TreeView(self.tree) + + def ids(): + return [item.get_id()[0] for item, *_ in tv3] + + def get_data(item): + return len(item.name) + + tv3.add_item(DataItem("A")) + tv3.add_item(DataItem("Be")) + tv3.add_item(DataItem("Cat")) + tv3.add_item(DataItem("Dog")) + + sorter = tv3.create_sort(data=get_data) + self.assertEqual(ids(), ["a", "b", "c", "d"]) + + def test_columns(self): + tv4 = TreeView(self.tree) + + col = tv4.create_column("Bold", expand=True) + col.add_image_renderer("icon", pixmaps=self.pixmaps) + col.add_text_renderer("name", wrap=True) + + self.assertEqual(col.clean(None), "") + self.assertEqual(col.clean("", markup=True), "&lt;A&B&gt;") + self.assertEqual(col.clean(["A", "B"]), ("A", "B")) + self.assertEqual(col.clean({"A": "B"}), {"A": "B"}) + self.assertRaises(TypeError, col.clean, col) + + def test_in_runnning_app(self): + tree = TreeView(self.tree) + tree.set_sensitive(True) + + col = tree.create_column("Bold", expand=True) + col.add_image_renderer(None, pixmaps=self.pixmaps, size=32) + col.add_text_renderer(None, wrap=True) + col2 = tree.create_column("Italic", expand=False) + col2.add_image_renderer("icon", pixmaps=None, size=32) + col2.add_text_renderer("get_name", template="{}") + col.add_text_renderer("get_nom", wrap=True) + + def set_bg(self, item): + super().set_background(item) + return "#ff0000" + + col.set_background = set_bg + + item_b = DataItem("B") + item_b.icon = self.pixmaps.get(item_b.icon) + + tree.add_item(DataItem("A")) + tree.add_item(item_b) + tree.add_item(Separator()) + tree.add_item(DataItem("C")) + + GLib.idle_add(self.window.select_tree, tree) + self.app.run() diff --git a/share/extensions/tests/test_inkex_gui_pixmaps.py b/share/extensions/tests/test_inkex_gui_pixmaps.py new file mode 100644 index 0000000..6e9c9ec --- /dev/null +++ b/share/extensions/tests/test_inkex_gui_pixmaps.py @@ -0,0 +1,232 @@ +# coding=utf-8 +# +# Copyright 2022 Martin Owens +# +# 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 3 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, see +# +""" +Test pixmap and image handling from various sources. +""" + +import os +import sys +import time +import pytest + +from inkex.tester import TestCase +from inkex.utils import DependencyError + +try: + from inkex.gui.tester import MainLoopProtection + from inkex.gui.pixmap import ( + PixmapLoadError, + PixmapFilter, + OverlayFilter, + PadFilter, + SizeFilter, + SIZE_ASPECT, + SIZE_ASPECT_GROW, + SIZE_ASPECT_CROP, + SIZE_STRETCH, + ) + from inkex.gui import PixmapManager +except DependencyError: + PixmapFilter = object + PixmapManager = None + + +class NullFilter(PixmapFilter): + required = ["underpants"] + + +@pytest.mark.skipif(PixmapManager is None, reason="PyGObject is required") +class GtkPixmapsTest(TestCase): + """Tests all the pixmaps functionality""" + + def construct_manager(self, **kwargs): + """Create a gtk app based on some inputs""" + return type( + "_PixMan", + (PixmapManager,), + { + "pixmap_dir": self.datadir(), + "missing_image": kwargs.pop("missing_image", None), + "default_image": kwargs.pop("default_image", None), + **kwargs, + }, + ) + + def test_filter(self): + """Test building filters and errors""" + null_filter = NullFilter(underpants=True) + self.assertRaises(NotImplementedError, null_filter.filter, "not") + self.assertRaises(ValueError, OverlayFilter().filter, None) + + def test_manager_filter_overlay(self): + """Test overlay filter in use""" + pixmaps = self.construct_manager(filters=[OverlayFilter])("svg") + self.assertTrue(pixmaps.get("colors.svg", overlay="application-default-icon")) + + def test_manger_filter_size(self): + """Test resizing a file pixmap""" + pixmaps = self.construct_manager(filters=[SizeFilter])("svg", size=150) + ret = pixmaps.get("colors.svg") + self.assertEqual(ret.get_width(), 150) + self.assertEqual(ret.get_height(), 50) + self.assertRaises(PixmapLoadError, pixmaps.load_from_name, "no-file.svg") + self.assertRaises( + PixmapLoadError, + pixmaps.load_from_name, + os.path.join(self.datadir(), "ui", "window-test.ui"), + ) + + def test_missing_image(self): + pixmaps = PixmapManager("svg", filters=[SizeFilter(size=25)]) + img_a = pixmaps.get("NeverExisted.svg") + img_b = pixmaps.get(PixmapManager.missing_image) + self.assertEqual(img_a.get_width(), 25) + self.assertPixbuf(img_a, img_b) + + def test_overlay_filter(self): + """Test overlay filter""" + pixmaps = self.construct_manager()("svg") + start = pixmaps.get("gradient_with_mixed_offsets.svg") + + # 1. Simple overlay + ret = OverlayFilter().filter(start, manager=pixmaps, overlay="colors.svg") + comp = pixmaps.get("img/color_overlay_a.png") + self.assertPixbuf(ret, comp) + + # 2. Overlay at bottom + ret = OverlayFilter(position=1).filter( + start, manager=pixmaps, overlay="colors.svg" + ) + comp = pixmaps.get("img/color_overlay_b.png") + self.assertPixbuf(ret, comp) + + def test_pad_filter(self): + """Test padding filter""" + pixmaps = self.construct_manager()("svg") + start = pixmaps.get("colors.svg") + + # 1. Add no padding + ret = PadFilter(size=(300, 100)).filter(start) + self.assertPixbuf(ret, start) + + # 2a. Add padding at top-left + ret = PadFilter(size=300, padding=0.0).filter(start) + comp = pixmaps.get("img/color_pad_a.png") + self.assertPixbuf(ret, comp) + + # 12b. Add padding at top-left + ret = PadFilter(size=300, padding=1.0).filter(start) + comp = pixmaps.get("img/color_pad_b.png") + self.assertPixbuf(ret, comp) + + # 12c. Add padding at top-left + ret = PadFilter(size=300, padding=0.5).filter(start) + comp = pixmaps.get("img/color_pad_c.png") + self.assertPixbuf(ret, comp) + + # 3. Take image and pad to 1px x 150px + ret = PadFilter(size=(1, 150)).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (300, 150)) + + def test_size_filter(self): + """Test the size pixbuf filter""" + pixmaps = self.construct_manager()("svg") + start = pixmaps.get("colors.svg") + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + ret = SizeFilter().filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (300, 100)) + + ret = SizeFilter(size=600, resize_mode=SIZE_ASPECT).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (300, 100)) + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + ret = SizeFilter(size=60, resize_mode=SIZE_ASPECT).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (60, 20)) + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + ret = SizeFilter(size=600, resize_mode=SIZE_ASPECT_GROW).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (600, 200)) + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + ret = SizeFilter(size=60, resize_mode=SIZE_ASPECT_CROP).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (180, 60)) + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + ret = SizeFilter(size=600, resize_mode=SIZE_STRETCH).filter(start) + self.assertEqual((ret.get_width(), ret.get_height()), (600, 600)) + self.assertEqual((start.get_width(), start.get_height()), (300, 100)) + + def test_load_file(self): + """Test loading a filename""" + pixmaps = self.construct_manager()("svg") + self.assertTrue(pixmaps.get("colors.svg")) + self.assertFalse(pixmaps.get("colors-no-file.svg")) + + def test_load_name(self): + """Test loading from a Gtk named theme icon""" + pixmaps = self.construct_manager()() + self.assertTrue(pixmaps.get("image-missing")) + + def test_load_data_svg(self): + """Test loading a data svg""" + pixmaps = self.construct_manager()(size=None, load_size=(128, 128)) + with open(os.path.join(self.datadir(), "svg", "colors.svg"), "r") as fhl: + self.assertTrue(pixmaps.get(fhl.read())) + self.assertRaises(PixmapLoadError, pixmaps.load_from_data, " {pcent}%" + ) diff --git a/share/extensions/tests/test_inkex_gui_window.py b/share/extensions/tests/test_inkex_gui_window.py new file mode 100644 index 0000000..81da56f --- /dev/null +++ b/share/extensions/tests/test_inkex_gui_window.py @@ -0,0 +1,102 @@ +# coding=utf-8 +# +# Copyright 2022 Martin Owens +# +# 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 3 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, see +# +""" +Test the various features of a Gtk/Inkex Window. +""" + +import os +import sys +import time +import pytest + +from inkex.tester import TestCase +from inkex.utils import DependencyError + +try: + from inkex.gui.tester import MainLoopProtection + from inkex.gui import GtkApp, Window, ChildWindow, asyncme +except DependencyError: + Window = object + ChildWindow = object + GtkApp = None + + +class BadNamedWindow(Window): + name = "bad-name" + + +class BasicWindow(Window): + name = "basic-window" + + +class ChildWindow(ChildWindow): + name = "child-window" + + +@pytest.mark.skipif(GtkApp is None, reason="PyGObject is required") +class GtkWindowTest(TestCase): + """Tests for GUI Window""" + + def construct_app(self, windows=()): + """Create a gtk app based on some inputs""" + return type( + "_GtkApp", + (GtkApp,), + { + "app_name": "window-test", + "windows": list(windows), + "ui_dir": self.datadir(), + "prefix": "ui", + "ui_file": "window-test", + }, + ) + + def test_window(self): + """Various consruction errors""" + app = self.construct_app([BadNamedWindow]) + + def test_load_window_extract(self): + """Test extracting widgets""" + app = self.construct_app([BasicWindow])() + widget = app.load_window_extract("basic-window") + self.assertEqual(Window.get_widget_name(widget), "box1") + # original window widget is untouched + self.assertTrue(list(app.window.window.get_children())) + # Destroy origial widgets + app.window.exit(widget) + + def test_child_window(self): + """Test the loading of child windows""" + app = self.construct_app([BasicWindow, ChildWindow])() + window = app.window + child = window.load_window("child-window") + self.assertEqual(Window.get_widget_name(child.widget("box2")), "box2") + self.assertEqual(child.name, "child-window") + child.exit(child) + + def test_if_widget(self): + """Test getting a widget with a fake fallback""" + app = self.construct_app([BasicWindow])() + faker = app.window.if_widget("fake") + self.assertFalse(faker) + self.assertFalse(faker.get_name()) + + def test_replace_widget(self): + """Replace a widget in a window""" + app = self.construct_app([BasicWindow])() + app.window.replace("button1", "button2") diff --git a/share/extensions/tests/test_inkex_inx.py b/share/extensions/tests/test_inkex_inx.py new file mode 100644 index 0000000..5a55efa --- /dev/null +++ b/share/extensions/tests/test_inkex_inx.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +Test elements extra logic from svg xml lxml custom classes. +""" + +import os +from glob import glob + +from inkex.utils import PY3 +from inkex.tester import TestCase +from inkex.tester.inx import InxMixin +from inkex.inx import InxFile + + +class InxTestCase(InxMixin, TestCase): + """Test INX files""" + + def test_inx_effect(self): + inx = InxFile( + """ + + TestOne + org.inkscape.test.inx_one + + all + + + + + + + +""" + ) + self.assertEqual(inx.name, "TestOne") + self.assertEqual(inx.ident, "org.inkscape.test.inx_one") + self.assertEqual(inx.slug, "InxOne") + self.assertEqual( + inx.metadata, {"type": "effect", "preview": False, "objects": "all"} + ) + self.assertEqual(inx.menu, ["Banana", "Ice Cream", "TestOne"]) + self.assertEqual(inx.warnings, []) + + def test_inx_output(self): + inx = InxFile( + """ + + <_name>TestTwo + org.inkscape.test.inx_two + + .inx + text/xml+inx + Extension (*.inx) + <_filetypetooltip>The extension extension repention suspension. + true + +""" + ) + self.assertEqual(inx.name, "TestTwo") + self.assertEqual(inx.ident, "org.inkscape.test.inx_two") + self.assertEqual( + inx.metadata, + { + "dataloss": True, + "extension": ".inx", + "mimetype": "text/xml+inx", + "name": "Extension (*.inx)", + "tooltip": "The extension extension repention suspension.", + "type": "output", + }, + ) + self.assertEqual( + inx.warnings, + [ + "Use of old translation scheme: <_filetypetooltip...>", + "Use of old translation scheme: <_name...>", + ], + ) + + def test_inx_input(self): + inx = InxFile( + """ + TestThree + org.inkscape.test.inx_three + +""" + ) + self.assertEqual(inx.name, "TestThree") + self.assertEqual( + inx.metadata, + { + "extension": ".inx", + "mimetype": "text/xml+inx", + "name": "Extension (*.inx)", + "tooltip": "The extension extension repention suspension.", + "type": "input", + }, + ) + self.assertEqual(inx.warnings, ["No inx xml prefix."]) + + def test_inx_template(self): + inx = InxFile( + """ + TestFour + org.inkscape.test.inx_four + + all + + + + Magic Number + Donky Oaty + Something might happen. + 2070-01-01 + word food strawberry + +""" + ) + self.assertEqual(inx.name, "TestFour") + self.assertEqual( + inx.metadata, + { + "author": "Donky Oaty", + "desc": "Something might happen.", + "type": "template", + }, + ) + self.assertEqual(inx.warnings, ["No inx xml prefix."]) + + def test_inx_files(self): + """Get all inx files and test each of them""" + if not PY3: + self.skipTest("No INX testing in python2") + return + for inx_file in glob(os.path.join(self._testdir(), "..", "*.inx")): + self.assertInxIsGood(inx_file) diff --git a/share/extensions/tests/test_inkex_paths.py b/share/extensions/tests/test_inkex_paths.py new file mode 100644 index 0000000..e8f147b --- /dev/null +++ b/share/extensions/tests/test_inkex_paths.py @@ -0,0 +1,950 @@ +# coding=utf-8 +""" +Test Inkex path parsing functionality. +""" + +import re + +from inkex.paths import ( + InvalidPath, + Path, + PathCommand, + CubicSuperPath, + line, + move, + curve, + smooth, + quadratic, + tepidQuadratic, + arc, + vert, + horz, + zoneClose, + Line, + Move, + Horz, + Vert, + Curve, + Smooth, + Quadratic, + TepidQuadratic, + Arc, + ZoneClose, +) +from inkex.transforms import Transform, Vector2d +from inkex.tester import TestCase + +# pylint: disable=too-many-public-methods + + +class SegmentTest(TestCase): + """ + Test specific segment functionality. + """ + + def get_random_cmd(self, Cmd): + import random + + return Cmd(*[random.randint(0, 10) for i in range(Cmd.nargs)]) + + def test_equals(self): + """Segments should be equalitive""" + self.assertEqual(Move(10, 10), Move(10, 10)) + self.assertEqual(Line(10, 10), Line(10, 10)) + self.assertEqual(line(10, 10), line(10, 10)) + self.assertNotEqual(line(10, 10), Line(10, 10)) + self.assertEqual(Horz(10), Line(10, 0)) + self.assertEqual(Vert(10), Line(0, 10)) + self.assertNotEqual(Vert(10), Horz(10)) + + def test_to_curves(self): + """Segments can become curves""" + self.assertRaises(ValueError, Move(0, 0).to_curve, None) + self.assertEqual( + Line(10, 10).to_curve(Vector2d(10, 5)), (10, 5, 10, 10, 10, 10) + ) + self.assertEqual(Horz(10).to_curve(Vector2d(10, 5)), (10, 5, 10, 5, 10, 5)) + self.assertEqual(Vert(10).to_curve(Vector2d(5, 10)), (5, 10, 5, 10, 5, 10)) + self.assertEqual( + Curve(5, 5, 10, 10, 4, 4).to_curve(Vector2d(0, 0)), (5, 5, 10, 10, 4, 4) + ) + + self.assertEqual( + Smooth(10, 10, 4, 4).to_curve(Vector2d(4, 4), Vector2d(10, 10)), + (-2, -2, 10, 10, 4, 4), + ) + + self.assertAlmostTuple( + Quadratic(10, 10, 4, 4).to_curve(Vector2d(0, 0)).args, + (6.666666666666666, 6.666666666666666, 8, 8, 4, 4), + ) + + self.assertAlmostTuple( + TepidQuadratic(4, 4).to_curve(Vector2d(14, 19), Vector2d(11, 12)).args, + # (20.666666666666664, 30, 17.333333333333332, 25, 4, 4), + ( + 15.999999999999998, + 23.666666666666664, + 12.666666666666666, + 18.666666666666664, + 4, + 4, + ), + ) + + curves = list(Arc(50, 50, 0, 0, 1, 85, 85).to_curves(Vector2d(0, 0))) + self.assertEqual(len(curves), 3) + self.assertAlmostTuple( + curves[0].args, + ( + 19.77590700610636, + -5.4865851247611115, + 38.18634924829132, + -10.4196482558544, + 55.44095225512604, + -5.796291314453416, + ), + ) + self.assertAlmostTuple( + curves[1].args, + ( + 72.69555526196076, + -1.172934373052433, + 86.17293437305243, + 12.30444473803924, + 90.79629131445341, + 29.559047744873958, + ), + ) + self.assertAlmostTuple( + curves[2].args, + ( + 95.41964825585441, + 46.81365075170867, + 90.4865851247611, + 65.22409299389365, + 77.85533905932738, + 77.85533905932738, + ), + ) + + def apply_to_curve(obj): + obj.to_curve(Vector2d()) + + def apply_to_curves(obj): + obj.to_curve(Vector2d()) + + self.assertRaises(ValueError, apply_to_curve, ZoneClose()) + self.assertRaises(ValueError, apply_to_curves, zoneClose()) + + self.assertRaises(ValueError, apply_to_curve, Move(0, 0)) + self.assertRaises(ValueError, apply_to_curves, move(0, 0)) + + def test_transformation(self): + t = Transform(matrix=((1, 2, 3), (4, 5, 6))) + + first = Vector2d() + prev = Vector2d(31, 97) + prev_prev = Vector2d(5, 7) + + for Cmd in (Line, Move, Curve, Smooth, Quadratic, TepidQuadratic, Arc): + random_seg = self.get_random_cmd(Cmd) + self.assertTrue( + random_seg.transform(t) is not random_seg + ) # transform returns copy + self.assertEqual( + random_seg.transform(t).name, Cmd.name + ) # transform does not change Command type + + T = Transform() + T.add_translate(10, 20) + A = [ + T.apply_to_point(p) + for p in random_seg.control_points(first, prev, prev_prev) + ] + first2, prev2, prev_prev2 = ( + T.apply_to_point(p) for p in (first, prev, prev_prev) + ) + B = list( + random_seg.translate(Vector2d(10, 20)).control_points( + first2, prev2, prev_prev2 + ) + ) + self.assertAlmostTuple(A, B) + + T = Transform() + T.add_scale(10, 20) + A = [ + T.apply_to_point(p) + for p in random_seg.control_points(first, prev, prev_prev) + ] + first2, prev2, prev_prev2 = ( + T.apply_to_point(p) for p in (first, prev, prev_prev) + ) + B = list( + random_seg.scale((10, 20)).control_points(first2, prev2, prev_prev2) + ) + self.assertAlmostTuple(A, B) + + T = Transform() + T.add_rotate(35, 15, 28) + A = [ + T.apply_to_point(p) + for p in random_seg.control_points(first, prev, prev_prev) + ] + first2, prev2, prev_prev2 = ( + T.apply_to_point(p) for p in (first, prev, prev_prev) + ) + B = list( + random_seg.rotate(35, Vector2d(15, 28)).control_points( + first2, prev2, prev_prev2 + ) + ) + self.assertAlmostTuple(A, B) + + def test_absolute_relative(self): + absolutes = ( + Line, + Move, + Curve, + Smooth, + Quadratic, + TepidQuadratic, + Arc, + Vert, + Horz, + ZoneClose, + ) + relatives = ( + line, + move, + curve, + smooth, + quadratic, + tepidQuadratic, + arc, + vert, + horz, + zoneClose, + ) + + zero = Vector2d() + for R, A in zip(relatives, absolutes): + rel = self.get_random_cmd(R) + ab = self.get_random_cmd(A) + + self.assertTrue(rel.is_relative) + self.assertTrue(ab.is_absolute) + + self.assertFalse(rel.is_absolute) + self.assertFalse(ab.is_relative) + + self.assertEqual(type(rel.to_absolute(zero)), A) + self.assertEqual(type(ab.to_relative(zero)), R) + self.assertTrue(rel.to_relative(zero) is not rel) + self.assertTrue(ab.to_absolute(zero) is not ab) + + def test_to_line(self): + self.assertEqual(Vert(3).to_line(Vector2d(5, 11)), Line(5, 3)) + self.assertEqual(Horz(3).to_line(Vector2d(5, 11)), Line(3, 11)) + + self.assertEqual(vert(3).to_line(Vector2d(5, 11)), Line(5, 14)) + self.assertEqual(horz(3).to_line(Vector2d(5, 11)), Line(8, 11)) + + def test_args(self): + + commands = ( + Line, + Move, + Curve, + Smooth, + Quadratic, + TepidQuadratic, + Arc, + Vert, + Horz, + ZoneClose, + line, + move, + curve, + smooth, + quadratic, + tepidQuadratic, + arc, + vert, + horz, + zoneClose, + ) + + for Cmd in commands: + cmd = self.get_random_cmd(Cmd) + self.assertEqual(len(cmd.args), cmd.nargs) + self.assertEqual(Cmd(*cmd.args), cmd) + + +class PathTest(TestCase): + """Test path API and calculations""" + + def _assertPath(self, path, want_string): + """Test a normalized path string against a good value""" + return self.assertEqual(re.sub("\\s+", " ", str(path)), want_string) + + def test_new_empty(self): + """Create a path from a path string""" + self.assertEqual(str(Path()), "") + + def test_invalid(self): + """Load an invalid path""" + self._assertPath(Path("& 10 10 M 20 20"), "M 20 20") + self.assertRaises( + TypeError, + Line, + [ + 40, + ], + ) + + def test_copy(self): + """Make a copy of a path""" + self.assertEqual(str(Path("M 10 10").copy()), "M 10 10") + + def test_repr(self): + """Path representation""" + self._assertPath(repr(Path("M 10 10 10 10")), "[Move(10, 10), Line(10, 10)]") + + def test_list(self): + """Path of previous commands""" + path = Path(Path("M 10 10 20 20 30 30 Z")[1:-1]) + self._assertPath(path, "L 20 20 L 30 30") + + def test_passthrough(self): + """Create a path and test the re-rendering of the commands""" + for path in ( + "M 50,50 L 10,10 m 10 10 l 2.1,2", + "m 150 150 c 10 10 6 6 20 10 L 10 10", + ): + self._assertPath(Path(path), path.replace(",", " ")) + + def test_chained_conversion(self): + """Paths always extrapolate chained commands""" + for path, ret in ( + ("M 100 100 20 20", "M 100 100 L 20 20"), + ("M 100 100 Z 20 20", "M 100 100 Z M 20 20"), + ("M 100 100 L 20 20 40 40 30 10 Z", "M 100 100 L 20 20 L 40 40 L 30 10 Z"), + ("m 50 50 l 20 20 40 40", "m 50 50 l 20 20 l 40 40"), + ("m 50 50 20 20", "m 50 50 l 20 20"), + ((("m", (50, 50)), ("l", (20, 20))), "m 50 50 l 20 20"), + ): + self._assertPath(Path(path), ret) + + def test_create_from_points(self): + """Paths can be made of simple list of tuples""" + arg = ((10, 10), (4, 5), (16, -9), (20, 20)) + self.assertEqual(str(Path(arg)), "L 10 10 L 4 5 L 16 -9 L 20 20") + + def test_control_points(self): + """Test how x,y points are extracted""" + for path, ret in ( + ("M 100 100", ((100, 100),)), + ("L 100 100", ((100, 100),)), + ("H 133", ((133, 0),)), + ("V 144", ((0, 144),)), + ( + "Q 40 20 12 99 T 100 100", + ( + (40, 20), + (12, 99), + (-16, 178), + (100, 100), + ), + ), + ("C 12 12 15 15 20 20", ((12, 12), (15, 15), (20, 20))), + ( + "S 50 90 30 10", + ( + (0, 0), + (50, 90), + (30, 10), + ), + ), + ( + "Q 40 20 12 99", + ( + (40, 20), + (12, 99), + ), + ), + ("A 1,2,3,0,0,10,20", ((10, 20),)), + ("Z", ((0, 0),)), + ): + points = list(Path(path).control_points) + self.assertEqual(len(points), len(ret), msg=path) + self.assertTrue(all(p.is_close(r) for p, r in zip(points, ret)), msg=path) + + def test_bounding_box_lines(self): + """ + Test the bounding box calculations + + A diagonal line from 20,20 to 90,90 then to +10,+10 "\" + + """ + self.assertEqual( + (20, 100), (20, 100), Path("M 20,20 L 90,90 l 10,10 Z").bounding_box() + ) + self.assertEqual( + (10, 90), (10, 90), Path("M 20,20 L 90,90 L 10,10 Z").bounding_box() + ) + + def test_bounding_box_curves(self): + """ + Test the bounding box calculations of a curve + """ + + path = Path( + "M 85,14 C 104.63953,33.639531 104.71989,65.441157" + " 85,85 65.441157,104.71989 33.558843,104.71989 14,85" + " -5.7198883,65.441157 -5.6395306,33.639531 14,14" + " 33.639531,-5.6395306 65.360469,-5.6395306 85,14 Z" + ) + bb_tuple = path.bounding_box() + expected = (-0.760, -0.760 + 100.520), (-0.730, -0.730 + 100.520) + precision = 3 + + self.assertDeepAlmostEqual(tuple(bb_tuple.x), expected[0], places=precision) + self.assertDeepAlmostEqual(tuple(bb_tuple.y), expected[1], places=precision) + + def test_bounding_box_arcs(self): + """ + Test the bounding box calculations with arcs (currently is rough only) + + Bounding box around a circle with a radius of 50 + it should be from 0,0 -> 100, 100 + """ + path = Path( + "M 85.355333,14.644651 " + "A 50,50 0 0 1 85.355333,85.355341" + " 50,50 0 0 1 14.644657,85.355341" + " 50,50 0 0 1 14.644676,14.644651" + " 50,50 0 0 1 85.355333,14.644651 Z" + ) + + bb_tuple = path.bounding_box() + expected = (0, 100), (0, 100) + precision = 4 + + self.assertDeepAlmostEqual(tuple(bb_tuple.x), expected[0], places=precision) + self.assertDeepAlmostEqual(tuple(bb_tuple.y), expected[1], places=precision) + + # self.assertEqual(('ERROR'), Path('M 10 10 S 100 100 300 0').bounding_box()) + # self.assertEqual(('ERRPR'), Path('M 10 10 Q 100 100 300 0').bounding_box()) + + def test_adding_to_path(self): + """Paths can be translated using addition""" + ret = Path("M 20,20 L 90,90 l 10,10 Z").translate(50, 50) + self._assertPath(ret, "M 70 70 L 140 140 l 10 10 Z") + + def test_extending(self): + """Paths can be extended using addition""" + ret = Path("M 20 20") + Path("L 40 40 9 10") + self.assertEqual(type(ret), Path) + self._assertPath(ret, "M 20 20 L 40 40 L 9 10") + + ret = Path("M 20 20") + "C 40 40 9 10 10 10" + self.assertEqual(type(ret), Path) + self._assertPath(ret, "M 20 20 C 40 40 9 10 10 10") + + def test_subtracting_from_path(self): + """Paths can be translated using addition""" + ret = Path("M 20,20 L 90,90 l 10,10 Z").translate(-10, -10) + self._assertPath(ret, "M 10 10 L 80 80 l 10 10 Z") + + def test_scale(self): + """Paths can be scaled using the times operator""" + ret = Path("M 10,10 L 30,30 C 20 20 10 10 10 10 l 10 10").scale(2.5, 3) + self._assertPath(ret, "M 25 30 L 75 90 C 50 60 25 30 25 30 l 25 30") + + ret = Path( + "M 29.867708,101.68274 A 14.867708,14.867708 0 0 1 15,116.55045 14.867708," + "14.867708 0 0 1 0.13229179,101.68274 14.867708,14.867708 0 0 1 15,86.815031 " + "14.867708,14.867708 0 0 1 29.867708,101.68274 Z" + ) + ret = ret.scale(1.2, 0.8) + self._assertPath( + ret, + "M 35.8412 81.3462 " + "A 17.8412 11.8942 0 0 1 18 93.2404 " + "A 17.8412 11.8942 0 0 1 0.15875 81.3462 " + "A 17.8412 11.8942 0 0 1 18 69.452 " + "A 17.8412 11.8942 0 0 1 35.8412 81.3462 Z", + ) + + def test_scale_relative_after_close(self): + """Zone close moves current position correctly after transform""" + # expected positions: + # - before scale: + # M to (10,10), l by (+10,+10), Z back to (10,10), l by (+10,+10) + # <=> M to (10,10), L to (20,20), Z back to (10,10), L to (20,20) + # - after scale: + # M to (20,20), L to (40,40), Z back to (20,20), L to (40,40) + # <=> M to (20,20), l by (+20,+20), Z back to (20,20), l by (+20,+20) + ret = Path("M 10,10 l 10,10 Z l 10,10").scale(2, 2) + self._assertPath(ret, "M 20 20 l 20 20 Z l 20 20") + + def test_scale_multiple_zones(self): + """Zone close returns current position to start of zone (not start of path)""" + ret = Path("M 100 100 Z M 200 200 Z h 0").scale(1, 1) + self._assertPath(ret.to_absolute(), "M 100 100 Z M 200 200 Z L 200 200") + + def test_absolute(self): + """Paths can be converted to absolute""" + ret = Path("M 100 100 l 10 10 10 10 10 10") + self._assertPath(ret.to_absolute(), "M 100 100 L 110 110 L 120 120 L 130 130") + + ret = Path("M 100 100 h 10 10 10 v 10 10 10") + self._assertPath( + ret.to_absolute(), "M 100 100 H 110 H 120 H 130 V 110 V 120 V 130" + ) + + ret = Path("M 150,150 a 76,55 0 1 1 283,128") + self._assertPath(ret.to_absolute(), "M 150 150 A 76 55 0 1 1 433 278") + + ret = Path("m 5 5 h 5 v 5 h -5 z M 15 15 l 5 5 z m 10 10 h 5 v 5 h -5 z") + self._assertPath( + ret.to_absolute(), + "M 5 5 H 10 V 10 H 5 Z M 15 15 L 20 20 Z M 25 25 H 30 V 30 H 25 Z", + ) + + ret = Path("m 1 2 h 2 v 1 z m 4 0 h 2 v 1 z m 0 2 h 2 v 1 z") + self._assertPath( + ret.to_absolute(), "M 1 2 H 3 V 3 Z M 5 2 H 7 V 3 Z M 5 4 H 7 V 5 Z" + ) + + def test_relative(self): + """Paths can be converted to relative""" + ret = Path("M 100 100 L 110 120 140 140 300 300") + self._assertPath(ret.to_relative(), "m 100 100 l 10 20 l 30 20 l 160 160") + + ret = Path("M 150,150 A 76,55 0 1 1 433,278") + self._assertPath(ret.to_relative(), "m 150 150 a 76 55 0 1 1 283 128") + + ret = Path("M 1 2 H 3 V 3 Z M 5 2 H 7 V 3 Z M 5 4 H 7 V 5 Z") + self._assertPath( + ret.to_relative(), "m 1 2 h 2 v 1 z m 4 0 h 2 v 1 z m 0 2 h 2 v 1 z" + ) + + def test_rotate(self): + """Paths can be rotated""" + ret = Path("M 0.24999949,0.24999949 H 12.979167 V 12.979167 H 0.24999949 Z") + ret = ret.rotate(35, (0, 0)) + self._assertPath( + ret, + "M 0.0613938 0.348181 L 10.4885 7.64933 L 3.18737 18.0765 L -7.23976 10.7753 Z", + ) + + ret = Path("M 0.24999949,0.24999949 H 12.979167 V 12.979167 H 0.24999949 Z") + ret = ret.rotate(-35, (0, 0)) + self._assertPath( + ret, + "M 0.348181 0.0613938 L 10.7753 -7.23976 L 18.0765 3.18737 L 7.64933 10.4885 Z", + ) + + ret = Path("M 0.24999949,0.24999949 H 12.979167 V 12.979167 H 0.24999949 Z") + ret = ret.rotate(90, (10, -10)) + self._assertPath( + ret, + "M -0.249999 -19.75 L -0.249999 -7.02083 L -12.9792 -7.02083 L -12.9792 -19.75 Z", + ) + + ret = Path("M 0.24999949,0.24999949 H 12.979167 V 12.979167 H 0.24999949 Z") + ret = ret.rotate(90) + self._assertPath( + ret, + "M 12.9792 0.249999 L 12.9792 12.9792 L 0.249999 12.9792 L 0.249999 0.249999 Z", + ) + + def test_to_arrays(self): + """Return the full path as a bunch of arrays""" + ret = Path("M 100 100 L 110 120 H 20 C 120 0 6 10 10 2 Z").to_arrays() + self.assertEqual(len(ret), 5) + self.assertEqual(ret[0][0], "M") + self.assertEqual(ret[1][0], "L") + self.assertEqual(ret[2][0], "L") + self.assertEqual(ret[3][0], "C") + + def test_transform(self): + """Transform by a whole matrix""" + ret = Path("M 100 100 L 110 120 L 140 140 L 300 300") + ret = ret.transform(Transform(translate=(10, 10))) + self.assertEqual(str(ret), "M 110 110 L 120 130 L 150 150 L 310 310") + ret = ret.transform(Transform(translate=(-10, -10))) + self.assertEqual(str(ret), "M 100 100 L 110 120 L 140 140 L 300 300") + ret = Path("M 5 5 H 10 V 15") + ret = ret.transform(Transform(rotate=-10)) + self.assertEqual( + "M 5.79228 4.0558 " "L 10.7163 3.18756 " "L 12.4528 13.0356", str(ret) + ) + ret = Path("M 10 10 A 50,50 0 0 1 85.355333,85.355341 L 100 0") + ret = ret.transform(Transform(scale=10)) + self.assertEqual(str(ret), "M 100 100 A 500 500 0 0 1 853.553 853.553 L 1000 0") + self.assertRaises(ValueError, Horz([10]).transform, Transform()) + + def test_inline_transformations(self): + path = Path() + self.assertTrue(path is not path.translate(10, 20)) + self.assertTrue(path is not path.transform(Transform(scale=10))) + self.assertTrue(path is not path.rotate(10)) + self.assertTrue(path is not path.scale(10, 20)) + + self.assertTrue(path is path.translate(10, 20, inplace=True)) + self.assertTrue(path is path.transform(Transform(scale=10), inplace=True)) + self.assertTrue(path is path.rotate(10, inplace=True)) + self.assertTrue(path is path.scale(10, 20, inplace=True)) + + def test_transformation_preserve_type(self): + import re + + paths = [ + "M 10 10 A 100 100 0 1 0 100 100 C 10 15 20 20 5 5 Z", + "m 10 10 a 100 100 0 1 0 100 100 c 10 15 20 20 5 5 z", + "m 10 10 l 100 200 L 20 30 C 10 20 30 40 11 12", + "M 10 10 Q 12 13 14 15 T 11 32 T 32 11", + "m 10 10 q 12 13 14 15 t 11 32 t 32 11", + ] + t = Transform(matrix=((1, 2, 3), (4, 5, 6))) + for path_str in paths: + path = Path(path_str) + new_path = path.transform(t) + cmds = "".join([cmd.letter for cmd in new_path]) + expected = re.sub(r"\d|\s|,", "", path_str) + + self.assertEqual(expected, cmds) + self.assertAlmostTuple( + [t.apply_to_point(p) for p in path.control_points], + list(new_path.control_points), + ) + + def test_arc_transformation(self): + cases = [ + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 0, 1), (0, 1, 0)), + "M 11 10 A 100 100 0 1 0 101 100 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 0, 0), (0, 1, 1)), + "M 10 11 A 100 100 0 1 0 100 101 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 0, 1), (0, 1, 1)), + "M 11 11 A 100 100 0 1 0 101 101 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((2, 0, 0), (0, 1, 0)), + "M 20 10 A 200 100 0 1 0 200 100 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 0, 0), (0, 2, 0)), + "M 10 20 A 200 100 90 1 0 100 200 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 0, 0), (0, -1, 0)), + "M 10 -10 A 100 100 0 1 1 100 -100 Z", + ), + ( + "M 10 10 A 100 100 0 1 0 100 100 Z", + ((1, 2, 0), (0, 2, 0)), + "M 30 20 " "A 292.081 68.4742 41.4375 1 0 300 200 Z", + ), + ( + "M 10 10 " "A 100 100 0 1 0 100 100 " "A 300 200 0 1 0 50 20 Z", + ((1, 2, 0), (5, 6, 0)), + "M 30,110 " + "A 810.90492,49.327608 74.368134 1 1 " + "300,1100 1981.2436,121.13604 75.800007 1 1 90,370 Z", + ), + ] + for path, transform, expected in cases: + expected = Path(expected) + result = Path(path).transform(Transform(matrix=transform)) + self.assertDeepAlmostEqual( + expected.to_arrays(), result.to_arrays(), places=4 + ) + + def test_single_point_transform(self): + from math import sqrt, sin, cos + + self.assertAlmostTuple( + list(Path("M 10 10 30 20").control_points), ((10, 10), (30, 20)) + ) + self.assertAlmostTuple( + list( + Path("M 10 10 30 20") + .transform(Transform(translate=(10, 7))) + .control_points + ), + ((20, 17), (40, 27)), + ) + self.assertAlmostTuple( + list( + Path("M 20 20 5 0 0 7 ").transform(Transform(scale=10)).control_points + ), + ((200, 200), (50, 0), (0, 70)), + ) + + self.assertAlmostTuple( + list(Path("M 20 20 1 0").transform(Transform(rotate=90)).control_points), + ((-20, 20), (0, 1)), + ) + + self.assertAlmostTuple( + list(Path("M 20 20 1 0").transform(Transform(rotate=45)).control_points), + ((0, sqrt(20**2 + 20**2)), (sqrt(2) / 2, sqrt(2) / 2)), + ) + + self.assertAlmostTuple( + list(Path("M 1 0 0 1").transform(Transform(rotate=30)).control_points), + ((sqrt(3) / 2, 0.5), (-0.5, sqrt(3) / 2)), + ) + + def test_reverse(self): + """Paths can be reversed""" + # Testing reverse() with relative coordinates, closed path + ret = Path( + "m 10 50 h 40 v -40 l 50 39.9998 c -22 2 -35 12 -50 25 l -40 -15 l 0 -10 z" + ) + ret = ret.reverse() + self._assertPath( + ret, + "m 10 50 l 0 -0.0002 l -0 10 l 40 15 c 15 -13 28 -23 50 -25 l -50 -39.9998 v 40 z", + ) + # Testing reverse() with relative coordinates, open path + ret = Path( + "m 10 50 h 40 v -40 l 50 39.9998 c -22 2 -35 12 -50 25 l -40 -15 l 0 -10" + ) + ret = ret.reverse() + self._assertPath( + ret, + "m 10 49.9998 l -0 10 l 40 15 c 15 -13 28 -23 50 -25 l -50 -39.9998 v 40 h -40", + ) + # Testing reverse() with absolute coordinates, closed path + ret = Path("M 100 35 L 100 25 L 60 10 C 45 23 32 33 10 35 L 60 75 L 60 35 Z") + ret = ret.reverse() + self._assertPath( + ret, + "M 100 35 L 60 35 L 60 75 L 10 35 C 32 33 45 23 60 10 L 100 25 Z", + ) + # Testing reverse() with absolute coordinates, open path + ret = Path( + "M 100 35 L 100 25 L 60 10 C 45 23 32 33 10 35 L 60 75 L 60 35 L 100 35" + ) + ret = ret.reverse() + self._assertPath( + ret, + "M 100 35 L 60 35 L 60 75 L 10 35 C 32 33 45 23 60 10 L 100 25 L 100 35", + ) + ret = Path("M 100,250 q 250,100 400,250") + ret = ret.reverse() + self._assertPath(ret, "M 500 500 q -150 -150 -400 -250") + + def test_reverse_multiple_subpaths(self): + """Test for https://gitlab.com/inkscape/extensions/-/issues/445. First two + examples are from the issue""" + ret = Path("M 128,64 L 128,128 M 128,196 L 128,256").reverse() + self._assertPath(ret, "M 128 256 L 128 196 M 128 128 L 128 64") + + ret = Path("M 128,64 L 128,128 m 128,196 L 128,256").reverse() + self._assertPath(ret, "M 128 256 L 256 324 m -128 -196 L 128 64") + + # More complex example with absolute and relative move commands + ret = Path( + "m 58,88 c -10,2 3,13 10,4 z M 32,67 c 14,-5 23,-3 35,7 m 2,-21 c" + "10,11 20,19 34,11 M 24,43 c 23,-14 18,-5 39,4" + ).reverse() + self._assertPath( + ret, + "m 63 47 c -21 -9 -16 -18 -39 -4 M 103 64 c -14 8 -24 0 -34 -11 " + "m -2 21 c -12 -10 -21 -12 -35 -7 M 58 88 l 10 4 c -7 9 -20 -2 -10 -4 z", + ) + + +class SuperPathTest(TestCase): + """Super path tests for testing the super path class""" + + def test_closing(self): + """Closing paths create two arrays""" + path = Path( + "M 0,0 C 1.505,0 2.727,-0.823 2.727,-1.841 V -4.348 C 2.727,-5.363" + " 1.505,-6.189 0,-6.189 H -8.3 V 0 Z m -10.713,1.991 h -0.211 V -8.178" + " H 0 c 2.954,0 5.345,1.716 5.345,3.83 v 2.507 C 5.345,0.271 2.954,1.991" + " 0,1.991 Z" + ) + csp = path.to_superpath() + self.assertEqual(len(csp), 2) + + def test_closing_without_z(self): + """Closing paths without z create two arrays""" + path = Path( + "m 51.553104,253.58572 c -11.644086,-0.14509 -4.683516,-19.48876" + " 2.096523,-8.48973 1.722993,2.92995 0.781608,6.73867 -2.096523,8.48973" + " m -3.100522,-13.02176 c -18.971587,17.33811 15.454875,20.05577" + " 6.51412,3.75474 -1.362416,-2.30812 -3.856221,-3.74395 -6.51412,-3.75474" + ) + csp = path.to_superpath() + self.assertEqual(len(csp), 2) + + def test_from_arrays(self): + """SuperPath from arrays""" + csp = CubicSuperPath( + [ + [ + [[14, 173], [14, 173], (14, 173)], + [(15, 171), (17, 168), (18, 168)], + ], + [ + [(18, 167), (18, 167), [20, 165]], + ((21, 164), [22, 162], (23, 162)), + ], + ] + ) + self.assertEqual( + str(csp.to_path()), + "M 14 173 C 14 173 15 171 17 168 M 18 167 C 20 165 21 164 22 162", + ) + + def test_is_line(self): + """Test is super path segments can detect lines""" + path = Path( + "m 49,88 70,-1 c 18,17 1,59 1.7,59 " + "0,0 -48.7,18 -70.5,-1 18,-15 25,-32.4 -1.5,-57.2 z" + ) + csp = path.to_superpath() + self.assertTrue(csp.is_line(csp[0][0], csp[0][1]), "Should be a line") + self.assertFalse( + csp.is_line(csp[0][3], csp[0][4]), "Both controls not detected" + ) + self.assertFalse( + csp.is_line(csp[0][1], csp[0][2]), "Start control not detected" + ) + self.assertFalse(csp.is_line(csp[0][2], csp[0][3]), "End control not detected") + # Also tests if zone close is applied correctly. + self.assertEqual( + str(csp.to_path()), + "M 49 88 L 119 87 C 137 104 120 146 120.7 146 " + "C 120.7 146 72 164 50.2 145 C 68.2 130 75.2 112.6 48.7 87.8 Z", + ) + + def test_is_line_simplify(self): + """Test if super path segments can detect if a segment can be simplified to a line""" + path = Path("M 10 10 C 20,20 30,30 40,40 C 100, 100 50, 50 60, 60") + csp = path.to_superpath() + + self.assertTrue(csp.is_line(csp[0][0], csp[0][1])) # line can be retracted + self.assertFalse( + csp.is_line(csp[0][1], csp[0][2]) + ) # is line, but shoots over endpoint + + self.assertEqual(str(csp.to_path()), "M 10 10 L 40 40 C 100 100 50 50 60 60") + + def test_is_line_collinear(self): + self.assertFalse(CubicSuperPath.collinear([1, 2], [2, 2.00001], [3, 2])) + self.assertTrue(CubicSuperPath.collinear([1, 2], [2, 2], [3, 2])) + self.assertTrue(CubicSuperPath.collinear([3, 2], [2, 2], [1, 2])) + + def test_is_within(self): + self.assertTrue(CubicSuperPath.within(2, 1, 3)) + self.assertTrue(CubicSuperPath.within(2, 3, 1)) + self.assertTrue(CubicSuperPath.within(2, 2, 2)) + self.assertTrue(CubicSuperPath.within(2, 3, 2)) + self.assertFalse(CubicSuperPath.within(3, 2.9999, 2)) + + def test_is_stable(self): + """Test for https://gitlab.com/inkscape/extensions/-/issues/374""" + path = Path("M 10 10 h 10 v 10 h -10 Z") + + tempsub = path.to_superpath() + comparison = str(tempsub) + for _ in range(15): + tempsub = CubicSuperPath(tempsub[0]) + self.assertEqual(comparison, str(tempsub)) + + def test_multiple_relative(self): + """Test for https://gitlab.com/inkscape/extensions/-/issues/450""" + + def compare_complex(current, epts): + for point, comp in zip(current.end_points, epts): + self.assertAlmostTuple(point, comp, msg=f"got {point}, expected {comp}") + for point, comp in zip(current.control_points, epts): + self.assertAlmostTuple(point, comp, msg=f"got {point}, expected {comp}") + # now reverse the path + p_rev = current.reverse() + for point, comp in zip(p_rev.end_points, epts[::-1]): + self.assertAlmostTuple(point, comp, msg=f"got {point}, expected {comp}") + # We expect to have the same amount of closed subpaths after the operation + self.assertEqual( + len(re.findall(r"[Zz]", str(p_rev))), + len(re.findall(r"[Zz]", str(current))), + ) + # now check that transform works correctly + p_trans = current.transform(Transform("translate(10, 20)")) + for point, comp in zip(p_trans.end_points, epts): + comp = comp + Vector2d(10, 20) + self.assertAlmostTuple(point, comp, msg=f"got {point}, expected {comp}") + + path = Path("m 50,20 v -10 h -10 z m 30,-20 v 20 h 20 z m -50,20 v -15 h -15 z") + path2 = Path( + "m 50,20 v -10 h -10 l 10, 10 m 30,-20 v 20 h 20 l -20,-20 m -50,20 v -15 h -15 z" + ) + path3 = Path( + "m 50,20 v -10 h -10 z m 30,-20 v 20 h 20 l -20,-20 m -50,20 v -15 h -15 l 15 15" + ) + pts = [ + (50, 20), + (50, 10), + (40, 10), + (50, 20), + (80, 0), + (80, 20), + (100, 20), + (80, 0), + (30, 20), + (30, 5), + (15, 5), + (30, 20), + ] + compare_complex(path, pts) + compare_complex(path2, pts) + compare_complex(path3, pts) + path4 = Path("m 50,20 v -10 h -10 z z z") + pts4 = [(50, 20), (50, 10), (40, 10), (50, 20), (50, 20), (50, 20)] + compare_complex(path4, pts4) + path5 = Path("m 50,20 z m 10, 10 m 20, 20 v -10 h -10 z") + pts5 = [(50, 20), (50, 20), (60, 30), (80, 50), (80, 40), (70, 40), (80, 50)] + compare_complex(path5, pts5) + + +class ProxyTest(TestCase): + def test_simple_path(self): + """Check coordinate computation""" + path = Path("M 10 10 h 10 v 10 h -10 Z") + + proxycommands = list(path.proxy_iterator()) + + self.assertAlmostTuple(list(proxycommands[1].previous_end_point), (10, 10)) + self.assertAlmostTuple(list(proxycommands[1].end_point), (20, 10)) + self.assertAlmostTuple(list(proxycommands[2].previous_end_point), (20, 10)) + + +class TestPathErrorHandling(TestCase): + """Path data error handling""" + + def test_incorrect_parameter_amount(self): + """Check that extra args (or rather, missing args of the next path) is + handled correctly, i.e. according to + https://www.w3.org/TR/SVG/paths.html#PathDataErrorHandling""" + path = Path("M 10,10 L 20,20,30") + self.assertEqual(str(path), "M 10 10 L 20 20") diff --git a/share/extensions/tests/test_inkex_styles.py b/share/extensions/tests/test_inkex_styles.py new file mode 100644 index 0000000..68fdd87 --- /dev/null +++ b/share/extensions/tests/test_inkex_styles.py @@ -0,0 +1,235 @@ +# coding=utf-8 +""" +Test Inkex style parsing functionality. +""" + +import pytest +import warnings + +from inkex.styles import Style +from inkex.colors import Color +from inkex.tester import TestCase +from inkex.tester.svg import svg_file + + +class StyleTest(TestCase): + """Test path API and calculations""" + + def test_new_style(self): + """Create a style from a path string""" + stl = Style("border-color: blue; border-width: 4px;") + self.assertEqual(str(stl), "border-color:blue;border-width:4px") + + def test_composite(self): + """Test chaining styles together""" + stl = Style("border-color: blue;") + stl += "border-color: red; border-issues: true;" + self.assertEqual(str(stl), "border-color:red;border-issues:true") + st2 = stl + "border-issues: false;" + self.assertEqual(str(st2), "border-color:red;border-issues:false") + + def test_inbuilts(self): + """Test inbuild style functions""" + stadd = Style("a: 1") + Style("b: 2") + self.assertTrue(stadd == Style("b: 2; a: 1")) + self.assertFalse(stadd == Style("b: 2")) + self.assertFalse(stadd != Style("b: 2; a: 1")) + self.assertEqual(stadd - "a: 4", "b: 2") + stadd -= "b: 3; c: 4" + self.assertEqual(stadd, Style("a: 1")) + + def test_set_property(self): + """Set the style attribute directly""" + stl = Style() + stl["border-pain"] = "green" + self.assertEqual(str(stl), "border-pain:green") + + def test_color_property(self): + """Color special handling""" + stl = Style("fill-opacity:0.7;fill:red;") + self.assertEqual(stl.get_color("fill").alpha, 0.7) + self.assertEqual(str(stl.get_color("fill")), "rgba(255, 0, 0, 0.7)") + stl.set_color("rgba(0, 127, 0, 0.5)", "stroke") + self.assertEqual( + str(stl), "fill-opacity:0.7;fill:red;stroke-opacity:0.5;stroke:#007f00" + ) + + def test_interpolate(self): + """Test interpolation method.""" + stl1 = Style( + {"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))} + ) + stl2 = Style( + {"stroke-width": "1pc", "fill-opacity": 0.0, "fill": Color((100, 0, 100))} + ) + stl3 = stl1.interpolate(stl2, 0.5) + print(stl3) + self.assertAlmostEqual(stl3("fill-opacity"), 0.5, 1e-3) + assert stl3("fill") == [150, 0, 50] + assert stl3["stroke-width"] == "8px" + + def test_callback(self): + """Test callback.""" + calls = 0 + + def cb(style): + nonlocal calls + self.assertNotIn("fill-opacity", style) + calls += 1 + + st = Style( + {"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))}, + callback=cb, + ) + self.assertEqual(calls, 0) + st.pop("fill-opacity") + self.assertEqual(calls, 1) + + def cb(style): + nonlocal calls + self.assertEqual(style["fill-opacity"], ".75") + calls += 1 + + st.callback = cb + st["fill-opacity"] = ".75" + self.assertEqual(calls, 2) + + +class StyleSheetTest(TestCase): + """Test parsing style sheets""" + + def setUp(self): + super(StyleSheetTest, self).setUp() + self.svg = svg_file(self.data_file("svg", "css.svg")) + self.css = self.svg.stylesheet + + def test_classes(self): + """Test element class manipulation""" + rect = self.svg.getElementById("rect2") + self.assertEqual(rect.get("class"), "two") + self.assertEqual(rect.classes, ["two"]) + rect.classes[0] = "twa" + self.assertEqual(rect.get("class"), "twa") + rect.classes.append("tri") + rect.classes.append("four") + self.assertEqual(rect.get("class"), "twa tri four") + rect.classes.remove("twa") + self.assertEqual(rect.get("class"), "tri four") + rect.classes.toggle("toggle") + self.assertEqual(rect.get("class"), "tri four toggle") + rect.classes.toggle("toggle") + self.assertEqual(rect.get("class"), "tri four") + + def test_creation(self): + """Stylesheet is created when needed""" + self.svg = svg_file(self.data_file("svg", "empty.svg")) + self.assertEqual(len(self.svg.stylesheets), 0) + self.assertEqual(len(self.svg.stylesheet), 0) + self.assertEqual(len(self.svg.stylesheets), 1) + self.svg.stylesheet.append(".cls1 { fill: blue; }") + self.assertIn( + b"style>\n.cls1 {\n fill:blue;\n}\n<", self.svg.tostring() + ) + + def test_parsing(self): + """SVG parsing provides access to stylesheets""" + sheets = self.svg.stylesheets + self.assertEqual(len(sheets), 3) + self.assertEqual(len(sheets[0]), 7) + self.assertEqual(len(sheets[1]), 0) + self.assertEqual(len(sheets[2]), 2) + + def test_string(self): + """Rendered to a string""" + sheets = self.svg.stylesheets + self.assertEqual(str(sheets[0][0]), "#layer1 {\n stroke:yellow;\n}") + self.assertEqual(str(sheets[2][1]), ".rule {}") + + def test_lookup_by_id(self): + """ID CSS lookup""" + self.assertTrue( + self.css[0].to_xpath() + in ["//*[@id='layer1']", "descendant-or-self::*[@id = 'layer1']"] + ) + elem = self.svg.getElement(self.css[0].to_xpath()) + self.assertEqual(elem.get("id"), "layer1") + + def test_lookup_by_element(self): + """Element name CSS lookup""" + self.assertTrue( + self.css[1].to_xpath() in ["//svg:circle", "descendant-or-self::svg:circle"] + ) + elems = list(self.svg.xpath(self.css[1].to_xpath())) + self.assertEqual(len(elems), 2) + self.assertEqual(elems[0].get("id"), "circle1") + self.assertEqual(elems[1].get("id"), "circle2") + + def test_lookup_by_class(self): + """Class name CSS lookup""" + self.assertTrue( + self.css[2].to_xpath() + in [ + "//*[contains(concat(' ', normalize-space(@class), ' '), ' two ')]", + "descendant-or-self::*[@class and contains" + "(concat(' ', normalize-space(@class), ' '), ' two ')]", + ] + ) + elem = self.svg.getElement(self.css[2].to_xpath()) + self.assertEqual(elem.get("id"), "rect2") + + def test_lookup_and(self): + """Multiple CSS lookups""" + self.assertTrue( + self.css[3].to_xpath() + in [ + "//*[@id='rect3']" + "[contains(concat(' ', normalize-space(@class), ' '), ' three ')]", + "descendant-or-self::*[@id = 'rect3' and " + "(@class and contains(concat(' ', normalize-space(@class), ' '), ' three '))]", + ] + ) + elem = self.svg.getElement(self.css[3].to_xpath()) + self.assertEqual(elem.get("id"), "rect3") + + def test_lookup_or(self): + """SVG rules can look up the right elements""" + self.assertTrue( + self.css[6].to_xpath() + in [ + "//*[@id='circle1']|//*[@id='circle2']|" + "//*[contains(concat(' ', normalize-space(@class), ' '), ' two ')]", + "descendant-or-self::*[@id = 'circle1']|descendant-or-self::*[@id = 'circle2']" + "|descendant-or-self::*[@class and contains(concat(' ', " + "normalize-space(@class), ' '), ' two ')]", + ] + ) + elems = self.svg.xpath(self.css[6].to_xpath()) + self.assertEqual(len(elems), 3) + self.assertEqual(elems[0].get("id"), "rect2") + self.assertEqual(elems[1].get("id"), "circle1") + self.assertEqual(elems[2].get("id"), "circle2") + + def test_applied_styles(self): + """Are styles applied to the svg elements correctly""" + self.assertEqual( + str(self.svg.getElementById("rect1").cascaded_style()), "fill:blue" + ) + self.assertEqual( + str(self.svg.getElementById("rect2").cascaded_style()), + "fill:green;font:Homie", + ) + self.assertEqual( + str(self.svg.getElementById("rect3").cascaded_style()), "fill:cyan" + ) + self.assertEqual( + str(self.svg.getElementById("rect4").cascaded_style()), + "fill:grey;stroke:red", + ) + self.assertEqual( + str(self.svg.getElementById("circle1").cascaded_style()), + "fill:red;font:Homie", + ) + self.assertEqual( + str(self.svg.getElementById("circle2").cascaded_style()), + "fill:red;font:Homie", + ) diff --git a/share/extensions/tests/test_inkex_styles_complex.py b/share/extensions/tests/test_inkex_styles_complex.py new file mode 100644 index 0000000..6355228 --- /dev/null +++ b/share/extensions/tests/test_inkex_styles_complex.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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, USA. +# +""" +Some more complicated styling tests, including inheritance and shorthand attributes +""" +from lxml import etree +from typing import List, Tuple +from inkex.styles import Style +from inkex.colors import Color +from inkex.tester import TestCase +from inkex.tester.svg import svg_file +from inkex import ( + SvgDocumentElement, + BaseElement, + ColorError, + BaseStyleValue, + RadialGradient, + Stop, + PathElement, +) +from inkex import SVG_PARSER + + +class StyleInheritanceTests(TestCase): + """Some test cases for css attribute handling""" + + def test_style_sheet_1(self): + """File from https://commons.wikimedia.org/wiki/File:Test_only.svg, public domain + note that Inkscape fails the same test: https://gitlab.com/inkscape/inbox/-/issues/1929""" + doc: SvgDocumentElement = svg_file( + self.data_file("svg", "style_inheritance.svg") + ) + + circles: List[BaseElement] = doc.xpath("//svg:circle") + for circle in circles: + style = circle.specified_style() + self.assertEqual(style("fill"), Color("red"), circle.getparent().get_id()) + + rects: List[BaseElement] = doc.xpath("//svg:rect") + for rect in rects: + style = rect.specified_style() + self.assertEqual(style("fill"), Color("blue")) + + def test_style_sheet_2(self): + """This is the unit test styling-css-04-f.svg from + https://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-styling-css-04-f.html + Note that the "good" preview image attached on the site is wrong per the explanation""" + doc: SvgDocumentElement = svg_file( + self.data_file("svg", "styling-css-04-f.svg") + ) + + rects: List[BaseElement] = doc.xpath("//svg:rect") + + results = { + "A": "blue", + "B": "green", + "C": "orange", + "D": "gold", + "E": "purple", + "F": "red", + } + for rect in rects: + ident = rect.get_id() + if len(ident) != 2: + continue + result = results[ident[0]] + + style = rect.specified_style() + self.assertEqual(style("fill"), Color(result)) + self.assertEqual(style["stroke-dasharray"], "none") + + def test_current_color(self): + """This is the unit test styling-inherit-01-b.svg from + https://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-styling-inherit-01-b.html + """ + + doc: SvgDocumentElement = svg_file( + self.data_file("svg", "styling-inherit-01-b.svg") + ) + + objects: List[BaseElement] = doc.xpath("//svg:rect|//svg:ellipse") + + for counter, obj in zip(range(3), objects[:3]): + fill = obj.specified_style()("fill") + if counter == 0: + self.assertEqual(fill, Color("yellow")) + else: + if counter == 1: + result = "green" + else: + result = "#700" + self.assertIsInstance(fill, RadialGradient) + stops = [child for child in fill if isinstance(child, Stop)] + stop = stops[1] + self.assertEqual(stop.specified_style()("stop-color"), Color(result)) + + stroke = objects[3].specified_style()("stroke") + self.assertEqual(stroke, Color("red")) + + def test_marker_style(self): + """Check if markers are read and written correctly""" + + doc: SvgDocumentElement = svg_file(self.data_file("svg", "markers.svg")) + elem = doc.getElementById("dimension") + style = elem.specified_style() + marker = style("marker-start") + self.assertEqual(marker, doc.getElementById("Arrow1Lstart")) + + # replace marker + elem.style["marker-start"] = doc.getElementById("Arrow1Lend") + marker = elem.specified_style()("marker-start") + self.assertEqual(marker, doc.getElementById("Arrow1Lend")) + + # write invalid attribute + with self.assertRaisesRegex(ValueError, "Invalid property value"): + elem.style["marker-start"] = "#url(test)" + + # write invalid attribute, second attempt + with self.assertRaisesRegex(ValueError, "invalid URL format"): + elem.style["marker-start"] = "url('test)" + + # write shorthand + elem.style["marker"] = doc.getElementById("Arrow1Lstart") + self.assertEqual(elem.style("marker-start"), doc.getElementById("Arrow1Lstart")) + self.assertEqual(elem.style("marker-mid"), doc.getElementById("Arrow1Lstart")) + self.assertEqual(elem.style("marker-end"), doc.getElementById("Arrow1Lstart")) + + # write shorthand to empty + elem.style["marker"] = "" + self.assertEqual(elem.style("marker-start"), doc.getElementById("Arrow1Lend")) + + def test_get_default(self): + """Test if the default values are returned for missing attributes""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + elem = doc.getElementById("path6") + + assert elem.style("stroke-dashoffset") == "0" + assert elem.style("font") == "" + + def parse_style_and_compare(self, tests: List[Tuple[str, dict]]): + """Parses a style and compares the output to a dictionary of attributes""" + for shorthand, result in tests: + style = Style(shorthand) + for key, value in result.items(): + self.assertEqual(str(style(key)), value) + + def test_font_shorthand(self): + """Test whether shorthand properties are applied correctly""" + tests: List[Tuple[str, dict]] = [ + ("font: ", {"font-size": "medium"}), + ( + r"font: 12px/14px sans-serif", + { + "font-size": "12px", + "line-height": "14px", + "font-family": "sans-serif", + }, + ), + ( + r"font: 80% sans-serif", + {"font-size": "80%", "font-family": "sans-serif"}, + ), + ( + r'font: x-large/110% "New Century Schoolbook", serif', + { + "font-size": "x-large", + "line-height": "110%", + "font-family": '"New Century Schoolbook", serif', + }, + ), + ( + r"font: semi-condensed bold italic large Palatino, serif", + { + "font-weight": "bold", + "font-style": "italic", + "font-size": "large", + "font-family": "Palatino, serif", + "font-stretch": "semi-condensed", + }, + ), + ( + r"font: normal small-caps 120%/120% fantasy", + { + "font-weight": "normal", + "font-style": "normal", + "font-variant": "small-caps", + "font-size": "120%", + "line-height": "120%", + "font-family": "fantasy", + }, + ), + ] + self.parse_style_and_compare(tests) + + def test_shorthand_overwrites(self): + """Test whether shorthands correctly follow precedence: only overwrite rules which are + defined before and not important""" + tests: List[Tuple[str, dict]] = [ + ( + """font-size: large; + font-family: Verdana !important; + font: bold 12px/14px sans-serif; + font-weight: normal;""", + { + "font-size": "12px", + "font-family": "Verdana", + "line-height": "14px", + "font-weight": "normal", + }, + ) + ] + self.parse_style_and_compare(tests) + + def test_gradient_parsing(self): + """Test if the style correctly outputs Gradient objects""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + elem = doc.getElementById("path6") + style = elem.style + grad = style("stroke") + self.assertEqual(grad, doc.getElementById("linearGradient855")) + + def test_attribute_set(self): + """Tests if we can set attributes with parsed values""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + + elem = doc.getElementById("path6") + style = elem.style + + tests = [ + ( + "stroke", + doc.getElementById("linearGradient847"), + "url(#linearGradient847)", + ), + ("fill", Color("red"), "red"), + ("stroke", None, "none"), + ("opacity", 0.5, "0.5"), + ("opacity", 1.2, "1"), + ("opacity", -2, "0"), + ("font-variant", "small-caps", "small-caps"), + ] + for attr, value, result in tests: + style[attr] = value + self.assertEqual(style[attr], result) + self.assertEqual(elem.specified_style()[attr], result) + + def test_opacity_clip(self): + """Test if opacity clipping works""" + style = Style() + tests = [ + ("opacity", "0.5", 0.5), + ("opacity", "1.2", 1), + ("opacity", "-2", 0), + ("opacity", "50%", 0.5), + ] + for attr, value, result in tests: + style[attr] = value + self.assertEqual(style(attr), result) + + def test_style_parsing_error(self): + """Test if bad attribute data raises an exception during parsing""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + tests: List[Tuple[str, Exception]] = [ + (r"opacity: abc", ValueError), + (r"fill: #GHI", ColorError), + (r"stroke: url(#missing)", ValueError), + (r"fill: ", ColorError), + (r"font-variant: blue", ValueError), + ] + for decl, exceptiontype in tests: + with self.assertRaises(exceptiontype): + value = BaseStyleValue.factory(declaration=decl) + _ = value.parse_value(doc) + self.assertEqual( + BaseStyleValue.factory_errorhandled(element=doc, declaration=decl), None + ) + + def test_attribute_set_invalid(self): + """Test if bad attribute data raises an exception when setting it on a style""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + + elem = doc.getElementById("path6") + tests = [ + ("fill", "nocolor", "Unknown color format"), + ("opacity", Style(), "Value must be number"), + ( + "font-variant", + "red", + "Value 'red' is invalid for the property font-variant", + ), + ("stroke", "url(#missing)", "Paint server not found"), + ] + style = elem.style + for attr, value, errormsg in tests: + with self.assertRaisesRegex(Exception, errormsg): + style[attr] = value + + def test_gradient_id_fallback(self): + """Test if the gradient fallback (color after nonexistent url) works""" + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + sty = Style(element=doc) + sty["stroke"] = "url(#nonexistent) red" + self.assertEqual(sty("stroke"), Color("red")) + + def test_compare_styles(self): + """Check style comparison""" + st1 = Style("fill: blue; stroke: red") + st2 = Style("fill: orange; stroke: red") + self.assertNotEqual(st1, st2) + st2["fill"] = "blue" + self.assertEqual(st1, st2) + st1["font-size"] = 1 + self.assertNotEqual(st1, st2) + + def test_basestylevalue(self): + """Create BaseStyleValue's directly and work on them""" + + val1 = BaseStyleValue.factory("fill: red;") + self.assertEqual(val1.parse_value(), Color("red")) + + # Compare the style + self.assertNotEqual(val1, "fill: red;") + + # Create a rule with an invalid declaration + with self.assertRaises(ValueError): + _ = BaseStyleValue.parse_declaration("fill=red;") + + # Try to apply a shorthand to the wrong style + val2 = BaseStyleValue.factory("font: 12pt Verdana") + style = Style("fill: context-fill;") + copy = style.copy() + + val2.apply_shorthand(style) + + self.assertEqual(style, copy) + + # Set a value to the wrong key + with self.assertRaises(ValueError): + style["stroke"] = BaseStyleValue.factory("font: 12pt Verdana") + + def test_style_bad_interfacing(self): + """Check a few ways to wrongly interface the Style class""" + style = Style("fill: red;") + + # call a missing key that is unknown and therefore has no default + with self.assertRaises(KeyError): + _ = style("favourite-test") + + # call the add_inherited method with a non-style argument + style2 = style.add_inherited("fill: blue") + self.assertEqual(style, style2) + + # set the importance on a value that doesn't exist + with self.assertRaises(KeyError): + style.set_importance("stroke", True) + + def test_style_exchange(self): + doc: SvgDocumentElement = svg_file(self.data_file("svg", "interp_shapes.svg")) + + elem = doc.getElementById("path6") + style = elem.style + + copystyle = style.copy() + self.assertIsNone(copystyle.callback) + copystyle["new-attribute"] = "test" + self.assertNotIn("new-attribute", elem.style) + + elem.style = copystyle + + copystyle["new-attribute"] = "test" + self.assertEqual(elem.style("new-attribute"), "test") + # callback is set after accessing the element + self.assertIsNotNone(elem.style.callback) + # copystyle["new-attribute2"] = "test" + # self.assertEqual(elem.style("new-attribute2"), "test") + + def test_stop_opacity_inheritance(self): + # subtest of pservers-grad-18b SVG1.1 unit test + content = """ + + + + + + + """ + doc = etree.fromstring(content, parser=SVG_PARSER) + grad = doc.getElementById("MyGradient1") + self.assertEqual( + grad[0].specified_style()("stop-opacity"), 1 + ) # assert that stop opacity is overwritten + self.assertEqual( + grad[1].specified_style()("stop-opacity"), 1 + ) # assert that stop opacity is not inherited by default + + def test_inheritance_second_attribute(self): + """Check that the second attribute is also correctly inherited""" + content = """""" + doc = etree.fromstring(content, parser=SVG_PARSER) + group = doc.getElementById("test") + self.assertEqual(group.specified_style()("font-size"), 20) + + def test_inherit_fallback(self): + content = """""" + doc = etree.fromstring(content, parser=SVG_PARSER) + group = doc.getElementById("test") + self.assertEqual(group.specified_style()("fill"), Color("black")) + self.assertEqual(group.specified_style()("bla"), None) + + def test_direct_child_and_import(self): + content = """ + + """ + doc = etree.fromstring(content, parser=SVG_PARSER) + ellipse = doc.getElementById("test") + self.assertEqual(ellipse.specified_style()("fill"), Color("red")) + + def test_dasharray(self): + """test parsing of dasharray""" + elem = PathElement() + style = elem.style + tests = [ + ("1 2 3 4", [1, 2, 3, 4]), + ("1 2,3 4.5", [1, 2, 3, 4.5]), + ("1;2", None), + ("1.111", [1.111, 1.111]), + ("1px, 2px, 3px", [1, 2, 3, 1, 2, 3]), + ("", None), + ("1 -2", None), + (None, None), + ([1, 2, 3], [1, 2, 3, 1, 2, 3]), + ] + for value, result in tests: + style["stroke-dasharray"] = value + setvalue = style("stroke-dasharray") + if result is None: + self.assertEqual(result, setvalue, f"got {setvalue}, original: {value}") + else: + self.assertAlmostTuple( + result, setvalue, msg=f"Expected {result}, got {setvalue}" + ) diff --git a/share/extensions/tests/test_inkex_svg.py b/share/extensions/tests/test_inkex_svg.py new file mode 100644 index 0000000..09a9228 --- /dev/null +++ b/share/extensions/tests/test_inkex_svg.py @@ -0,0 +1,610 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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, USA. +# +""" +Test the svg interface for inkscape extensions. +""" +from inkex.transforms import Vector2d +from inkex import Guide +from inkex.tester import TestCase +from inkex.tester.svg import svg, svg_file, svg_unit_scaled +from inkex import addNS + + +class BasicSvgTest(TestCase): + """Basic svg tests""" + + def test_svg_load(self): + """Test loading an svg with the right parser""" + self.assertEqual(type(svg()).__name__, "SvgDocumentElement") + + def test_add_ns(self): + """Test adding a namespace to a tag""" + self.assertEqual(addNS("g", "svg"), "{http://www.w3.org/2000/svg}g") + self.assertEqual( + addNS("h", "inkscape"), "{http://www.inkscape.org/namespaces/inkscape}h" + ) + self.assertEqual( + addNS("i", "sodipodi"), + "{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}i", + ) + self.assertEqual(addNS("{p}j"), "{p}j") + + def test_svg_ids(self): + """Test a list of ids from an svg document""" + self.assertEqual(svg('id="apples"').get_ids(), {"apples"}) + + def test_svg_new_id(self): + """Test generatign a new id for a given tag""" + doc = svg('id="apples"') + usedids = set(["apples"]) + for prefix in ["apples"] * 3: + newid = doc.get_unique_id(prefix) + self.assertTrue(newid.startswith(prefix)) + self.assertTrue(newid not in usedids) + usedids.add(newid) + + def test_svg_select_id(self): + """Select an id from the document""" + doc = svg('id="bananas"') + doc.selection.set("bananas") + self.assertEqual(doc.selection["bananas"], doc) + self.assertEqual(doc.selection.first(), doc) + doc = svg('id="apples"') + doc.selection.set(doc.getElementById("apples")) + self.assertEqual(doc.selection["apples"], doc) + self.assertEqual(doc.selection.first(), doc) + + def test_svg_by_class(self): + """Select elements by class""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + elems = doc.getElementsByClass("frog") + self.assertEqual( + [elem.get_id() for elem in elems], + ["path3902", "text3926", "path3900", "rect3898"], + ) + elems = doc.getElementsByClass("apple") + self.assertEqual([elem.get_id() for elem in elems], ["text3926", "rect3898"]) + + def test_svg_by_href(self): + """Select element by xlink href""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + elem = doc.getElementsByHref("path3900")[0] + self.assertEqual(elem.TAG, "textPath") + self.assertEqual(elem.get_id(), "textPath3923") + elem = doc.getElementsByHref("path3904")[0] + self.assertEqual(elem.TAG, "textPath") + self.assertEqual(elem.get_id(), "textPath3906") + self.assertEqual(doc.getElementsByHref("not-an-id"), []) + + def test_svg_by_url_link(self): + """Select element by urls in styles""" + doc = svg_file(self.data_file("svg", "markers.svg")) + elem = doc.getElementsByStyleUrl("Arrow1Lend")[0] + self.assertEqual(elem.get_id(), "dimension") + elem = doc.getElementsByStyleUrl("Arrow1Lstart")[0] + self.assertEqual(elem.get_id(), "dimension") + self.assertEqual(doc.getElementsByStyleUrl("not-an-id"), []) + + def test_selected_bbox(self): + """Can we get a bounding box from the selected items""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + doc.selection.set("path3904", "path3902") + from inkex.transforms import BoundingBox + + x, y, w, h = 199.544, 156.412, 377.489, 199.972 # from inkscape --query-all + expected_3904 = BoundingBox((x, x + w), (y, y + h)) + x, y, w, h = 145.358, 478.373, 439.135, 419.142 # from inkscape --query-all + expected_3902 = BoundingBox((x, x + w), (y, y + h)) + expected = list(expected_3902 + expected_3904) + + for x, y in zip(expected, doc.selection.bounding_box()): + self.assertDeepAlmostEqual(tuple(x), tuple(y), delta=1e-3) + + def test_svg_name(self): + """Can get the sodipodi name attribute""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + self.assertEqual(doc.name, "Nouveau document 1") + + def test_svg_nameview(self): + """Can get the sodipodi nameview element""" + doc = svg() + self.assertEqual(doc.namedview.center.x, 0) + self.assertEqual(type(doc.namedview).__name__, "NamedView") + + def test_svg_layers(self): + """Selected layer is selected""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + self.assertEqual(doc.get_current_layer().get("id"), "layer3") + doc = svg('id="empty"') + self.assertEqual(doc.get_current_layer(), doc) + + def test_svg_center_position(self): + """SVG with namedview has a center position""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + self.assertTrue(doc.namedview.center.is_close((30.714286, 520.0))) + self.assertTrue(svg().namedview.center.is_close(Vector2d())) + + def test_defs(self): + """Can get the defs from an svg file""" + doc = svg_file(self.data_file("svg", "markers.svg")) + self.assertEqual(len(doc.defs), 2) + doc = svg('id="empty"') + self.assertEqual(len(doc.defs), 0) + + def test_scale(self): + """Scale of a document""" + doc = svg('id="empty" viewBox="0 0 100 100" width="200" height="200"') + self.assertEqual(doc.viewport_width, 200.0) + self.assertEqual(doc.get_viewbox()[2], 100.0) + self.assertEqual(doc.scale, 2.0) + doc = svg('id="empty" viewBox="0 0 0 0" width="200" height="200"') + self.assertEqual(doc.scale, 1.0) + + +class NamedViewTest(TestCase): + """Tests for the named view functionality""" + + def test_create_guide(self): + """Test creating guides""" + doc = svg_file(self.data_file("svg", "multilayered-test.svg")) + namedview = doc.namedview + self.assertEqual(len(namedview.get_guides()), 0) + + namedview.add(Guide().move_to(50, 50, 45)) + self.assertEqual(len(namedview.get_guides()), 1) + (guide,) = namedview.get_guides() + self.assertEqual(guide.get("position"), "50,50") + self.assertEqual(guide.get("orientation"), "0.707107,-0.707107") + + +class GetDocumentWidthTest(TestCase): + """Tests for SvgDocumentElement.viewport_width and viewbox_width.""" + + def assert_svg_sizes(self, creation_string, viewport_width, viewbox_width): + """Check viewport and viewbox width""" + doc = svg(creation_string) + self.assertAlmostEqual(doc.viewbox_width, viewbox_width) + self.assertAlmostEqual(doc.viewport_width, viewport_width) + + def test_no_dimensions(self): + """An empty width value should be default zero width""" + self.assert_svg_sizes("", 0, 0) + + def test_empty_width(self): + """An empty width value should be the same as a missing width.""" + self.assert_svg_sizes('width=""', 0, 0) + + def test_empty_viewbox(self): + """An empty viewBox value should be the same as a missing viewBox.""" + self.assert_svg_sizes('viewBox=""', 0, 0) + + def test_empty_width_and_viewbox(self): + """Empty values for both should be the same as both missing.""" + self.assert_svg_sizes('width="" viewBox=""', 0, 0) + + def test_width_only(self): + """Test a fixed width""" + self.assert_svg_sizes('width="120mm"', 453.5433071, 453.5433071) + + def test_width_and_viewbox(self): + """If both are present, width overrides viewBox.""" + self.assert_svg_sizes('width="120mm" viewBox="0 0 22 99"', 453.5433071, 22) + + def test_viewbox_only(self): + """IF only the viewBox is present""" + self.assert_svg_sizes('viewBox="0 0 22 99"', 22, 22) + + def test_only_valid_viewbox(self): + """An empty width value should be the same as a missing width.""" + self.assert_svg_sizes('width="" viewBox="0 0 22 99"', 22, 22) + + def test_non_zero_viewbox_x(self): + """Demonstrate that a non-zero x value (viewbox[0]) does not affect the width value.""" + self.assert_svg_sizes('width="" viewBox="5 7 22 99"', 22, 22) + + def test_comma_separated_viewbox(self): + """Viewbox values can be separated by comma""" + self.assert_svg_sizes('width="" viewBox="5,7,22,99"', 22, 22) + + +class GetDocumentHeightTest(TestCase): + """Tests for Effect.height.""" + + def assert_svg_sizes(self, creation_string, viewport_height, viewbox_height): + """Check viewport and viewbox height""" + doc = svg(creation_string) + self.assertAlmostEqual(doc.viewbox_height, viewbox_height) + self.assertAlmostEqual(doc.viewport_height, viewport_height) + + def test_no_dimensions(self): + """Test height from blank svg""" + self.assert_svg_sizes("", 0, 0) + + def test_empty_height(self): + """An empty height value should be the same as a missing height.""" + self.assert_svg_sizes('height=""', 0, 0) + + def test_empty_viewbox(self): + """An empty viewBox value should be the same as a missing viewBox.""" + self.assert_svg_sizes('viewBox=""', 0, 0) + + def test_empty_height_viewbox(self): + """Empty values for both should be the same as both missing.""" + self.assert_svg_sizes('height="" viewBox=""', 0, 0) + + def test_height_only(self): + """A simple height only in px""" + self.assert_svg_sizes('height="330px"', 330, 330) + + def test_height_and_viewbox(self): + """If both are present, height overrides viewBox.""" + self.assert_svg_sizes('height="330px" viewBox="0 0 22 99"', 330, 99) + + def test_viewbox_only(self): + """Height from viewBox only""" + self.assert_svg_sizes('viewBox="0 0 22 99"', 99, 99) + + def test_no_height_valid_viewbox(self): + """An empty height value should be the same as a missing height.""" + self.assert_svg_sizes('height="" viewBox="0 0 22 99"', 99, 99) + + def test_non_zero_viewbox_y(self): + """Demonstrate that a non-zero y value (viewbox[1]) does not affect the height value.""" + self.assert_svg_sizes('height="" viewBox="5 7 22 99"', 99, 99) + + +class GetDocumentUnitTest(TestCase): + """Tests for Effect.unit.""" + + def test_no_dimensions(self): + """Default units with no arguments""" + self.assertEqual(svg().unit, "px") + + def test_width_only(self): + """ "Units from document width only""" + # TODO: Determine whether returning 'px' in this case is the + # intended behavior. + self.assertEqual(svg('width="100m"').unit, "px") + + def test_height_only(self): + """Units from document height only""" + # TODO: Determine whether returning 'px' in this case is the + # intended behavior. + self.assertEqual(svg('height="100m"').unit, "px") + + def test_viewbox_only(self): + """Test viewbox only document units""" + self.assertEqual(svg('viewBox="0 0 377 565"').unit, "px") + + # Unit-ratio tests. Don't exhaustively test every unit conversion, just + # demonstrate that the logic works. + + def test_width_and_viewbox_px(self): + """100mm is ~377px, so unit should be 'px'.""" + self.assertEqual(svg('width="100mm" viewBox="0 0 377 565"').unit, "px") + + def test_width_and_viewbox_in(self): + """100mm is ~3.94in, so unit should be 'in'.""" + self.assertEqual(svg('width="100mm" viewBox="0 0 3.94 5.90"').unit, "in") + + def test_unitless_width_and_viewbox(self): + """Unitless width should be treated as 'px'.""" + # 3779px is ~1m, so unit should be 'm'. + self.assertEqual(svg('width="3779" viewBox="0 0 1 1.5"').unit, "m") + + def test_height_with_viewbox(self): + """150mm is ~5.90in, so unit should be 'in', but height is ignored""" + # TODO: Determine whether returning 'px' in this case is the intended + # behavior. + self.assertEqual(svg('height="150mm" viewBox="0 0 3.94 5.90"').unit, "px") + + def test_height_width_and_viewbox(self): + """100mm is ~23.6pc, so unit should be 'pc'.""" + doc = svg('width="100mm" height="150mm" viewBox="0 0 23.6 35.4"') + self.assertEqual(doc.unit, "pc") + + def test_large_error_reverts_to_px(self): + """'px' instead of using the closest match 'pc'.""" + # 100mm is ~23.6pc; 24.1 is ~2% off from that, so unit should fall back + self.assertEqual(svg('width="100mm" viewBox="0 0 24.1 35.4"').unit, "px") + + # TODO: Demonstrate that unknown width units are treated as px while + # determining the ratio. + + # 100px fallback tests. Although that value is an arbitrary default, it's + # possible for users of inkex.Effect to depend on this behavior. + # NOTE: Do not treat the existence of these tests as a reason to preserve + # the 100px fallback logic. + + def test_bad_width_number(self): + """Fallback test: Bad numbers default to 100""" + # First, demonstrate that 1in is 2.54cm, so unit should be 'cm'. + self.assertEqual(svg('width="1in" viewBox="0 0 2.54 1"').unit, "cm") + + # Corrupt the width to contain an invalid number component; note that + # the units change to 'px'. This is because the corrupt number part is + # replaced with 100px, producing a width of "100px"; + self.assertEqual(svg('width="ABCDin" viewBox="0 0 2.54 1"').unit, "px") + + def test_bad_viewbox_entry(self): + """Fallback test: Bad viewBox default to 100""" + # First, demonstrate that 3779px is 1m, so unit should be 'm'. + self.assertEqual(svg('width="3779px" viewBox="0 0 1 1"').unit, "m") + + # Corrupt the viewBox to include a non-float value; will default to 'px' + self.assertEqual(svg('width="3779px" viewBox="x 0 1 1"').unit, "px") + + +class UserUnitTest(TestCase): + """Tests for methods that are based on the value of unit.""" + + def assertToUserUnit( + self, user_unit, test_value, expected + ): # pylint: disable=invalid-name + """Checks a user unit and a test_value against the expected result""" + doc = svg_unit_scaled(user_unit) + self.assertEqual(doc.unit, user_unit, msg=svg) + self.assertAlmostEqual(doc.to_dimensionless(test_value), expected) + + def assertToDocumentUnit( + self, user_unit, test_value, expected + ): # pylint: disable=invalid-name + """Checks a user unit and a test_value against the expected result""" + doc = svg_unit_scaled(user_unit) + self.assertEqual(doc.unit, user_unit, msg=svg) + self.assertAlmostEqual(doc.unittouu(test_value), expected) + + def assertFromUserUnit( + self, user_unit, value, unit, expected + ): # pylint: disable=invalid-name + """Check converting from a user unity for the test_value""" + self.assertAlmostEqual( + svg_unit_scaled(user_unit).to_dimensional(value, unit), expected + ) + + def assertFromDocumentUnit( + self, user_unit, value, unit, expected + ): # pylint: disable=invalid-name + """Check converting from a user unity for the test_value""" + self.assertAlmostEqual( + svg_unit_scaled(user_unit).uutounit(value, unit), expected + ) + + # Unit-ratio tests. Don't exhaustively test every unit conversion, just + # demonstrate that the logic works. + + def test_unittouu_in_to_cm(self): + """1in is ~2.54cm""" + self.assertToDocumentUnit("cm", "1in", 2.54) + + def test_unittouu_yd_to_m(self): + """1yd is ~0.9144m""" + self.assertToDocumentUnit("m", "1yd", 0.9144) + + def test_unittouu_identity(self): + """If the input and output units are the same, the input and output + values should exactly be the same, too.""" + self.assertToDocumentUnit("pc", "9.87654321pc", 9.87654321) + + def test_unittouu_bad_input_number(self): + """Bad input number""" + self.assertToDocumentUnit("cm", "1in", 2.54) + + # Corrupt the input to contain an invalid number component; note that + # the result changes to zero. + self.assertToDocumentUnit("cm", "ABCDin", 0) + + def test_unittouu_bad_input_unit(self): + """Bad input unit""" + # Demonstrate that 1.0in passes through without change. + self.assertToDocumentUnit("in", "1.0in", 1.0) + + # Corrupt the input to contain an invalid unit component; note that the + # result changes to 0.0, because corrupt parsing is zero px. + # it used to be the ratio between inches and pixels. This was + # because unittouu() treats unknown units as 'px'. + self.assertToDocumentUnit("in", "1.0ABCD", 0) + + def test_to_dimensionless_in_to_cm(self): + """1in is 96px in a cm based document""" + self.assertToUserUnit("cm", "1in", 96.0) + + def test_to_dimensionless_yd_to_m(self): + """1yd is 3456px""" + self.assertToUserUnit("m", "1yd", 3456.0) + + def test_to_dimensionless_no_unit(self): + """If no unit is given, the value must not be changed in mm based documents.""" + self.assertToUserUnit("mm", "9.87654321", 9.87654321) + + def test_to_dimensionless_identity(self): + """User units are px. If a value is given in px, the value must not change""" + self.assertToUserUnit("px", "9.87654321px", 9.87654321) + + def test_to_dimensionless_unitless_input(self): + """Passing a unitless value to unittouu() should treat the units as 'px'.""" + self.assertToUserUnit("in", "96", 96) # user unit = px + + def test_to_dimensionless_empty_input(self): + """Passing an empty string to unittouu() should treat the value as zero.""" + self.assertToUserUnit("in", "", 0) + + def test_to_dimensionless_parsing(self): + """Test user unit parsing forms""" + for value in ( + "100pc", + "100 pc", + " 100pc", + "100pc ", + "+100pc", + "100.0pc", + "100.0e0pc", + "10.0e1pc", + "10.0e+1pc", + "1000.0e-1pc", + ".1e+3pc", + "+.1e+3pc", + ): + # 100pc is ~3.937in + self.assertToUserUnit("px", value, 1600) + + def test_to_dimensionless_bad_input_number(self): + """Bad input number""" + self.assertToUserUnit("cm", "1in", 96.0) + # Demonstrate that 1in is ~96px, also in a "cm based" document. + + # Corrupt the input to contain an invalid number component; note that + # the result changes to zero. + self.assertToUserUnit("cm", "ABCDin", 0) + + def test_to_dimensionless_bad_input_unit(self): + """Bad input unit""" + # Demonstrate that 1.0px passes through without change. + self.assertToUserUnit("mm", "1.0px", 1.0) + + # Corrupt the input to contain an invalid unit component; note that the + # result changes to 0.0, because corrupt parsing is zero px. + # it used to be the ratio between inches and pixels. This was + # because to_dimensionless() treats unknown units as 'px'. + self.assertToUserUnit("mm", "1.0ABCD", 0) + + # Unit-ratio tests. Don't exhaustively test every unit conversion, just + # demonstrate that the logic works. + + def test_to_dimensional_cm_to_in(self): + """Convert 1 user unit (px) to 'cm' in a in-based document""" + self.assertFromUserUnit("in", 1, "cm", 2.54 / 96) # 1in is ~2.54cm + + def test_to_dimensional_m_to_yd(self): + """Convert 1 user unit (px) to 'm' in a yd-based document""" + self.assertFromUserUnit("yd", 1, "m", 1 / 100 * 2.54 / 96) + + def test_to_dimensional_identity(self): + """If the input unit is px, output value should be identical""" + self.assertFromUserUnit("pc", 9.87654321, "px", 9.87654321) + + def test_to_dimensional_unknown_unit(self): + """Demonstrate that passing an unknown unit string to uutounit()""" + self.assertEqual(svg_unit_scaled("in").to_dimensional(1, "px"), 1) + + def test_uutounit_cm_to_in(self): + """Convert 1 user unit ('in') to 'cm'.""" + self.assertFromDocumentUnit("in", 1, "cm", 2.54) # 1in is ~2.54cm + + def test_uutounit_m_to_yd(self): + """Convert 1 user unit ('yd') to 'm'.""" + self.assertFromDocumentUnit("yd", 1, "m", 0.9144) # 1yd is ~0.9144m + + def test_uutounit_unknown_unit(self): + """Demonstrate that passing an unknown unit string to uutounit()""" + self.assertEqual(svg_unit_scaled("in").uutounit(1, "px"), 96.0) + + def test_adddocumentunit_common(self): + """Test common add_unit results""" + # For valid float inputs, the output should be the input with the user unit appended. + doc = svg_unit_scaled("pt") + cases = ( + # Input, expected output + (100, "100pt"), + ("100", "100pt"), + ("+100", "100pt"), + ("-100", "-100pt"), + ("100.0", "100pt"), + ("100.0e0", "100pt"), + ("10.0e1", "100pt"), + ("10.0e+1", "100pt"), + ("1000.0e-1", "100pt"), + (".1e+3", "100pt"), + ("+.1e+3", "100pt"), + (" 100", "100pt"), + ("100 ", "100pt"), + (" 100 ", "100pt"), + ) + for input_value, expected in cases: + self.assertEqual(doc.add_unit(input_value), expected) + + def test_adddocumentunit_non_float(self): + """Strings that are invalid floats should pass through unchanged.""" + doc = svg_unit_scaled("pt") + inputs = ( + "", + "ABCD", + ".", + " ", + ) + for value in inputs: + self.assertEqual(doc.add_unit(value), "") + + def test_scales(self): + svg1 = svg('width="793.70081" height="1122.5197" viewBox="0 0 105 148.5"') + self.assertAlmostEqual(svg1.scale, 7.559055, places=5) + self.assertAlmostEqual(svg1.inkscape_scale, 7.559055, places=5) + + svg1 = svg('width="210mm" height="297mm" viewBox="0 0 105 148.5"') + self.assertAlmostEqual(svg1.scale, 7.559055, places=5) + self.assertEqual(svg1.inkscape_scale, 2) + + svg1 = svg('viewBox="0 0 105 148.5"') + self.assertEqual(svg1.scale, 1) + self.assertEqual(svg1.inkscape_scale, 1) + + +class ViewportUnitTestCase(TestCase): + def assertFromVPUnit( + self, width_unit, test_value, unit, expected + ): # pylint: disable=invalid-name + """Checks a viewport unit and a test_value against the expected result""" + doc = svg_unit_scaled(width_unit) + self.assertEqual(doc.unit, width_unit, msg=svg) + self.assertAlmostEqual(doc.viewport_to_unit(test_value, unit), expected) + + def assertToVPUnit( + self, user_unit, value, unit, expected + ): # pylint: disable=invalid-name + """Check converting from a user unity for the test_value""" + self.assertAlmostEqual( + svg_unit_scaled(user_unit).unit_to_viewport(value, unit), expected + ) + + def test_unittovp(self): + """1in is ~2.54cm""" + self.assertToVPUnit("px", "1in", "px", 96) + self.assertToVPUnit("px", "1", "px", 1) + + # 1 in = 96 px = 96 * 96 px/in / 2.54 cm/in on the viewport + self.assertToVPUnit( + "cm", + "1in", + "px", + 96 * 96 / 2.54, + ) + self.assertToVPUnit( + "cm", + "1in", + "in", + 96 / 2.54, + ) + self.assertToVPUnit("mm", "4", "mm", 4) + self.assertToVPUnit("mm", "4", "px", 4 * 96 / 25.4) + + def test_vptounit(self): + self.assertFromVPUnit("mm", "1m", "px", 1000) + self.assertFromVPUnit("mm", "4mm", "px", 4) + self.assertFromVPUnit("mm", "4mm", "mm", 4 * 25.4 / 96) diff --git a/share/extensions/tests/test_inkex_tester.py b/share/extensions/tests/test_inkex_tester.py new file mode 100644 index 0000000..911d68d --- /dev/null +++ b/share/extensions/tests/test_inkex_tester.py @@ -0,0 +1,30 @@ +# coding=utf-8 +""" +Test Inkex tester functionality +""" +from inkex.tester import TestCase +from inkex.tester.xmldiff import xmldiff + + +class TesterTest(TestCase): + """Ironic""" + + maxDiff = 20000 + + def get_file(self, filename): + """Get the contents of a file""" + with open(self.data_file("svg", filename), "rb") as fhl: + return fhl.read() + + def test_xmldiff(self): + """XML Diff""" + xml_a = self.get_file("shapes.svg") + xml_b = self.get_file("diff.svg") + + xml, delta = xmldiff(xml_a, xml_b) + self.assertFalse(delta) + self.assertEqual(str(delta), "9 xml differences") + # self.assertEqual(str(xml), '') + xml, delta = xmldiff(xml_a, xml_a) + self.assertTrue(delta) + self.assertEqual(str(delta), "No differences detected") diff --git a/share/extensions/tests/test_inkex_transforms.py b/share/extensions/tests/test_inkex_transforms.py new file mode 100644 index 0000000..6068631 --- /dev/null +++ b/share/extensions/tests/test_inkex_transforms.py @@ -0,0 +1,801 @@ +# coding=utf-8 +""" +Test Inkex transformational logic. +""" +from math import sqrt, pi +from inkex.transforms import ( + Vector2d, + ImmutableVector2d, + BoundingBox, + BoundingInterval, + Transform, + DirectedLineSegment, +) +from inkex.utils import PY3 +from inkex.tester import TestCase +import pytest + + +class ImmutableVector2dTest(TestCase): + """Test the ImmutableVector2d object""" + + def test_vector_creation(self): + """Test ImmutableVector2d creation""" + vec0 = ImmutableVector2d(15, 22) + self.assertEqual(vec0.x, 15) + self.assertEqual(vec0.y, 22) + + vec1 = ImmutableVector2d() + self.assertEqual(vec1.x, 0) + self.assertEqual(vec1.y, 0) + + vec2 = ImmutableVector2d((17, 32)) + self.assertEqual(vec2.x, 17) + self.assertEqual(vec2.y, 32) + + vec3 = ImmutableVector2d(vec0) + self.assertEqual(vec3.x, 15) + self.assertEqual(vec3.y, 22) + + vec4 = ImmutableVector2d("-5,8") + self.assertEqual(vec4.x, -5) + self.assertEqual(vec4.y, 8) + + self.assertRaises(ValueError, ImmutableVector2d, (1)) + self.assertRaises(ValueError, ImmutableVector2d, (1, 2, 3)) + + def test_binary_operators(self): + """Test binary operators for vector2d""" + vec1 = ImmutableVector2d(15, 22) + vec2 = ImmutableVector2d(5, 3) + + self.assertTrue((vec1 - vec2).is_close((10, 19))) + self.assertTrue((vec1 - (5, 3)).is_close((10, 19))) + self.assertTrue(((15, 22) - vec2).is_close((10, 19))) + self.assertTrue((vec1 + vec2).is_close((20, 25))) + self.assertTrue((vec1 + (5, 3)).is_close((20, 25))) + self.assertTrue(((15, 22) + vec2).is_close((20, 25))) + self.assertTrue((vec1 * 2).is_close((30, 44))) + self.assertTrue((2 * vec1).is_close((30, 44))) + self.assertTrue((vec1 / 2).is_close((7.5, 11))) + self.assertTrue((vec1.__div__(2)).is_close((7.5, 11))) + self.assertTrue((vec1 // 2).is_close((7.5, 11))) + + def test_ioperators(self): + """Test operators for vector2d""" + vec0 = vec = ImmutableVector2d(15, 22) + vec += (1, 1) + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((16, 23))) + vec -= (10, 20) + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((6, 3))) + vec *= 5 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((30, 15))) + vec /= 90 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((1.0 / 3, 1.0 / 6))) + vec //= 1.0 / 3 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((1, 0.5))) + self.assertTrue(vec0.is_close((15, 22))) + self.assertFalse(vec0.is_close(vec)) + + def test_unary_operators(self): + """Test unary operators""" + vec = ImmutableVector2d(1, 2) + self.assertTrue((-vec).is_close((-1, -2))) + self.assertTrue((+vec).is_close(vec)) + self.assertAlmostEqual(abs(vec), sqrt(5)) + self.assertTrue(+vec is not vec) # returned value is a copy + + def test_representations(self): + """Test ImmutableVector2d Repr""" + self.assertEqual(str(ImmutableVector2d(1, 2)), "1, 2") + self.assertEqual(repr(ImmutableVector2d(1, 2)), "Vector2d(1, 2)") + self.assertEqual(ImmutableVector2d(1, 2).to_tuple(), (1, 2)) + + def test_assign(self): + """Test ImmutableVector2d assignement""" + vec = ImmutableVector2d(10, 20) + with pytest.raises(AttributeError): + vec.assign(5, 10) + + def test_getitem(self): + """Test getitem for ImmutableVector2d""" + vec = ImmutableVector2d(10, 20) + self.assertEqual(len(vec), 2) + self.assertEqual(vec[0], 10) + self.assertEqual(vec[1], 20) + + def test_cross(self): + """Test cross product for ImmutableVector2d""" + vec1 = ImmutableVector2d(0, 2) + vec2 = ImmutableVector2d(0, 3) + vec3 = ImmutableVector2d(0, -3) + vec4 = ImmutableVector2d(3, 0) + vec5 = ImmutableVector2d(-3, 0) + vec6 = ImmutableVector2d(1, 1) + self.assertAlmostEqual(vec1.cross(vec2), 0) + self.assertAlmostEqual(vec2.cross(vec3), 0) + self.assertAlmostEqual(vec1.cross(vec4), -6) + self.assertAlmostEqual(vec1.cross(vec5), 6) + self.assertAlmostEqual(vec1.cross(vec6), -2.0) + self.assertAlmostEqual(vec6.cross(vec1), 2.0) + + +class Vector2dTest(TestCase): + """Test the Vector2d object""" + + def test_vector_creation(self): + """Test Vector2D creation""" + vec0 = Vector2d(15, 22) + self.assertEqual(vec0.x, 15) + self.assertEqual(vec0.y, 22) + + vec1 = Vector2d() + self.assertEqual(vec1.x, 0) + self.assertEqual(vec1.y, 0) + + vec2 = Vector2d((17, 32)) + self.assertEqual(vec2.x, 17) + self.assertEqual(vec2.y, 32) + + vec3 = Vector2d(vec0) + self.assertEqual(vec3.x, 15) + self.assertEqual(vec3.y, 22) + + self.assertRaises(ValueError, Vector2d, (1)) + self.assertRaises(ValueError, Vector2d, (1, 2, 3)) + self.assertRaises(ValueError, Vector2d, 1, 2, 3) + + def test_vector_default_creation(self): + """Test fallback for vectors""" + + # no fallback + vec0 = Vector2d("1,2", fallback=None) + self.assertEqual(vec0.x, 1) + self.assertEqual(vec0.y, 2) + + self.assertRaises(ValueError, Vector2d, "a,2") + self.assertRaises(ValueError, Vector2d, 1) + # invalid fallback + self.assertRaises(ValueError, Vector2d, 1, fallback="a") + + # fallback + vec0 = Vector2d("a,3", fallback=(1, 2)) + self.assertEqual(vec0.x, 1) + self.assertEqual(vec0.y, 2) + + vec0 = Vector2d(("a", "b"), fallback=(1, 2)) + self.assertEqual(vec0.x, 1) + self.assertEqual(vec0.y, 2) + + vec0 = Vector2d((3, 4, 5), fallback=(1, 2)) + self.assertEqual(vec0.x, 1) + self.assertEqual(vec0.y, 2) + + def test_binary_operators(self): + """Test binary operators for vector2d""" + vec1 = Vector2d(15, 22) + vec2 = Vector2d(5, 3) + + self.assertTrue((vec1 - vec2).is_close((10, 19))) + self.assertTrue((vec1 - (5, 3)).is_close((10, 19))) + self.assertTrue(((15, 22) - vec2).is_close((10, 19))) + self.assertTrue((vec1 + vec2).is_close((20, 25))) + self.assertTrue((vec1 + (5, 3)).is_close((20, 25))) + self.assertTrue(((15, 22) + vec2).is_close((20, 25))) + self.assertTrue((vec1 * 2).is_close((30, 44))) + self.assertTrue((2 * vec1).is_close((30, 44))) + self.assertTrue((vec1 / 2).is_close((7.5, 11))) + self.assertTrue((vec1.__div__(2)).is_close((7.5, 11))) + self.assertTrue((vec1 // 2).is_close((7.5, 11))) + + def test_ioperators(self): + """Test operators for vector2d""" + vec0 = vec = Vector2d(15, 22) + vec += (1, 1) + self.assertTrue(vec.is_close((16, 23))) + vec -= (10, 20) + self.assertTrue(vec.is_close((6, 3))) + vec *= 5 + self.assertTrue(vec.is_close((30, 15))) + vec /= 90 + self.assertTrue(vec.is_close((1.0 / 3, 1.0 / 6))) + vec //= 1.0 / 3 + self.assertTrue(vec.is_close((1, 0.5))) + self.assertFalse(vec0.is_close((15, 22))) + self.assertTrue(vec0.is_close(vec)) + + def test_unary_operators(self): + """Test unary operators""" + vec = Vector2d(1, 2) + self.assertTrue((-vec).is_close((-1, -2))) + self.assertTrue((+vec).is_close(vec)) + self.assertTrue(+vec is not vec) # returned value is a copy + + def test_representations(self): + """Test Vector2D Repr""" + self.assertEqual(str(Vector2d(1, 2)), "1, 2") + self.assertEqual(repr(Vector2d(1, 2)), "Vector2d(1, 2)") + self.assertEqual(Vector2d(1, 2).to_tuple(), (1, 2)) + + def test_assign(self): + """Test vector2d assignement""" + vec = Vector2d(10, 20) + vec.assign(5, 10) + self.assertAlmostTuple(vec, (5, 10)) + vec.assign((7, 11)) + self.assertAlmostTuple(vec, (7, 11)) + self.assertAlmostTuple(vec.assign(10, 20).assign(96, 11), (96, 11)) + self.assertAlmostTuple(vec.assign(10, 20).assign(45, 22), (45, 22)) + self.assertTrue(vec.assign(0, 0) is vec) + + def test_getitem(self): + """Test getitem for Vector2D""" + vec = Vector2d(10, 20) + self.assertEqual(len(vec), 2) + self.assertEqual(vec[0], 10) + self.assertEqual(vec[1], 20) + + def test_polar_operations(self): + """Test polar coordinates operations""" + # x y r pi + equivilents = [ + (0, 0, 0, 0), + (0, 0, 0, 1), + (0, 0, 0, -1), + (0, 0, 0, 0.5), + (1, 0, 1, 0), + (0, 1, 1, 0.5), + (0, -1, 1, -0.5), + (3, 0, 3, 0), + (0, 3, 3, 0.5), + (0, -3, 3, -0.5), + (sqrt(2), sqrt(2), 2, 0.25), + (-sqrt(2), sqrt(2), 2, 0.75), + (sqrt(2), -sqrt(2), 2, -0.25), + (-sqrt(2), -sqrt(2), 2, -0.75), + ] + for x, y, r, t in equivilents: + theta = t * pi if r != 0 else None + for ts in [0, 2, -2]: + ctx_msg = "Test values are x: {} y: {} r: {} θ: {} * pi".format( + x, y, r, t + ts + ) + polar = Vector2d.from_polar(r, (t + ts) * pi) + cart = Vector2d(x, y) + self.assertEqual(cart.length, r, msg=ctx_msg) + self.assertEqual(polar.length, r, msg=ctx_msg) + self.assertAlmostEqual(cart.angle, theta, msg=ctx_msg, delta=1e-12) + self.assertAlmostEqual(polar.angle, theta, msg=ctx_msg, delta=1e-12) + self.assertEqual(cart.to_polar_tuple(), (r, cart.angle), msg=ctx_msg) + self.assertEqual(polar.to_polar_tuple(), (r, polar.angle), msg=ctx_msg) + self.assertEqual(cart.to_tuple(), (x, y), msg=ctx_msg) + self.assertAlmostEqual(polar.to_tuple()[0], x, msg=ctx_msg, delta=1e-12) + self.assertAlmostEqual(polar.to_tuple()[1], y, msg=ctx_msg, delta=1e-12) + # Test special handling of from_polar with None theta + self.assertEqual(Vector2d.from_polar(0, None).to_tuple(), (0.0, 0.0)) + self.assertIsNone(Vector2d.from_polar(4, None)) + + +class TransformTest(TestCase): + """Test transformation API and calculations""" + + def test_new_empty(self): + """Create a transformation from two triplets matrix""" + self.assertEqual(Transform(), ((1, 0, 0), (0, 1, 0))) + + def test_new_from_triples(self): + """Create a transformation from two triplets matrix""" + self.assertEqual(Transform(((1, 2, 3), (4, 5, 6))), ((1, 2, 3), (4, 5, 6))) + + def test_new_from_sextlet(self): + """Create a transformation from a list of six numbers""" + self.assertEqual(Transform((1, 2, 3, 4, 5, 6)), ((1, 3, 5), (2, 4, 6))) + + def test_new_from_matrix_str(self): + """Create a transformation from a list of six numbers""" + self.assertEqual(Transform("matrix(1, 2, 3, 4, 5, 6)"), ((1, 3, 5), (2, 4, 6))) + + def test_new_from_scale(self): + """Create a scale based transformation""" + self.assertEqual(Transform("scale(10)"), ((10, 0, 0), (0, 10, 0))) + self.assertEqual(Transform("scale(10, 3.3)"), ((10, 0, 0), (0, 3.3, 0))) + + def test_new_from_translate(self): + """Create a translate transformation""" + self.assertEqual(Transform("translate(12)"), ((1, 0, 12), (0, 1, 0))) + self.assertEqual(Transform("translate(12, 14)"), ((1, 0, 12), (0, 1, 14))) + + def test_new_from_rotate(self): + """Create a rotational transformation""" + self.assertEqual(str(Transform("rotate(90)")), "rotate(90)") + self.assertEqual( + str(Transform("rotate(90 10 12)")), + "matrix(6.12323e-17 1 -1 6.12323e-17 22 2)", + ) + + def test_new_from_skew(self): + """Create skew x/y transformations""" + self.assertEqual(str(Transform("skewX(10)")), "matrix(1 0 0.176327 1 0 0)") + self.assertEqual(str(Transform("skewY(10)")), "matrix(1 0.176327 0 1 0 0)") + + def test_invalid_creation_string(self): + """Test creating invalid transforms""" + self.assertEqual(Transform("boo(4)"), ((1, 0, 0), (0, 1, 0))) + + def test_invalid_creation_matrix(self): + """Test creating invalid transforms""" + self.assertRaises(ValueError, Transform, 0.0) + self.assertRaises(ValueError, Transform, (0.0,)) + self.assertRaises(ValueError, Transform, (0.0, 0.0, 0.0)) + + def test_repr(self): + """Test repr string""" + self.assertEqual(repr(Transform()), "Transform(((1, 0, 0), (0, 1, 0)))") + + def test_matrix_inversion(self): + """Test the negative of a transformation""" + self.assertEqual(-Transform("rotate(45)"), Transform("rotate(-45)")) + self.assertEqual( + -Transform("translate(12, 10)"), Transform("translate(-12, -10)") + ) + self.assertEqual(-Transform("scale(4)"), Transform("scale(0.25)")) + + def test_apply_to_point(self): + """Test applying the transformation to a point""" + trans = Transform("translate(10, 10)") + self.assertEqual(trans.apply_to_point((10, 10)).to_tuple(), (20, 20)) + self.assertRaises(ValueError, trans.apply_to_point, "") + + def test_translate(self): + """Test making translate specific items""" + self.assertEqual( + str(Transform(translate=(10.6, 99.9))), "translate(10.6, 99.9)" + ) + + def test_scale(self): + """Test making scale specific items""" + self.assertEqual(str(Transform(scale=(1.0, 2.2))), "scale(1, 2.2)") + + def test_rotate(self): + """Test making rotate specific items""" + self.assertEqual(str(Transform(rotate=45)), "rotate(45)") + self.assertEqual( + str(Transform(rotate=(45, 10, 10))), + "matrix(0.707107 0.707107 -0.707107 0.707107 10 -4.14214)", + ) + + def test_add_transform(self): + """Test add_TRANSFORM syntax for quickly composing known transforms""" + tr1 = Transform() + tr1.add_scale(5.0, 1.0) + self.assertEqual(str(tr1), "scale(5, 1)") + tr1.add_translate(10, 10) + self.assertEqual(str(tr1), "matrix(5 0 0 1 50 10)") + self.assertEqual(str(Transform().add_scale(5.0, 1.0)), "scale(5, 1)") + self.assertEqual( + str(Transform().add_scale(5.0, 1.0).add_translate(10, 10)), + "matrix(5 0 0 1 50 10)", + ) + tr2 = Transform() + self.assertTrue( + tr2.add_scale(1, 1) + .add_translate(0, 0) + .add_skewy(0) + .add_skewx(0) + .add_rotate(0) + is tr2 + ) + self.assertEqual( + str(tr2.add_kwargs(translate=(10, 10), scale=(5.0, 1.0))), + "matrix(5 0 0 1 50 10)", + ) + + def test_is_unity(self): + """Test that unix matrix looks like rotate, scale, and translate""" + unity = Transform() + self.assertTrue(unity.is_rotate()) + self.assertTrue(unity.is_scale()) + self.assertTrue(unity.is_translate()) + + def test_is_rotation(self): + """Test that rotations about origin are correctly identified""" + rot1 = Transform(rotate=21) + rot2 = Transform(rotate=35) + rot3 = Transform(rotate=53) + + self.assertFalse(Transform(translate=1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(scale=1 + 1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_rotate(exactly=True)) + + self.assertTrue(Transform(translate=1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(scale=1 + 1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_rotate(exactly=False)) + + self.assertTrue(rot1.is_rotate()) + self.assertTrue(rot2.is_rotate()) + self.assertTrue(rot3.is_rotate()) + + self.assertFalse(rot1.is_translate()) + self.assertFalse(rot2.is_translate()) + self.assertFalse(rot3.is_translate()) + + self.assertFalse(rot1.is_scale()) + self.assertFalse(rot2.is_scale()) + self.assertFalse(rot3.is_scale()) + + self.assertTrue((rot1 @ rot1).is_rotate()) + self.assertTrue((rot1 @ rot2).is_rotate()) + self.assertTrue((rot1 @ rot2 @ rot3 @ rot2 @ rot1).is_rotate()) + + def test_is_translate(self): + """Test that translations are correctly identified""" + tr1 = Transform(translate=(1.1,)) + tr2 = Transform(translate=(1.3, 2.7)) + tr3 = Transform(translate=(sqrt(2) / 2, pi)) + + self.assertFalse(Transform(rotate=1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(scale=1 + 1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_translate(exactly=True)) + + self.assertTrue(Transform(rotate=1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(scale=1 + 1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_translate(exactly=False)) + + self.assertTrue(tr1.is_translate()) + self.assertTrue(tr2.is_translate()) + self.assertTrue(tr3.is_translate()) + self.assertFalse(tr1.is_rotate()) + self.assertFalse(tr2.is_rotate()) + self.assertFalse(tr3.is_rotate()) + self.assertFalse(tr1.is_scale()) + self.assertFalse(tr2.is_scale()) + self.assertFalse(tr3.is_scale()) + + self.assertTrue((tr1 @ tr1).is_translate()) + self.assertTrue((tr1 @ tr2).is_translate()) + self.assertTrue((tr1 @ tr2 @ tr3 @ tr2 @ tr1).is_translate()) + self.assertFalse(tr1 @ tr2 @ tr3 @ -tr1 @ -tr2 @ -tr3) # is almost unity + + def test_is_scale(self): + """Test that scale transformations are correctly identified""" + s1 = Transform(scale=(1.1,)) + s2 = Transform(scale=(1.3, 2.7)) + s3 = Transform(scale=(sqrt(2) / 2, pi)) + + self.assertFalse(Transform(translate=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(rotate=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_scale(exactly=True)) + + self.assertTrue(Transform(translate=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(rotate=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_scale(exactly=False)) + + self.assertFalse(s1.is_translate()) + self.assertFalse(s2.is_translate()) + self.assertFalse(s3.is_translate()) + self.assertFalse(s1.is_rotate()) + self.assertFalse(s2.is_rotate()) + self.assertFalse(s3.is_rotate()) + self.assertTrue(s1.is_scale()) + self.assertTrue(s2.is_scale()) + self.assertTrue(s3.is_scale()) + + def test_rotation_degrees(self): + """Test parsing and composition of different rotations""" + self.assertAlmostEqual(Transform(rotate=30).rotation_degrees(), 30) + self.assertAlmostEqual(Transform(translate=(10, 20)).rotation_degrees(), 0) + self.assertAlmostEqual(Transform(scale=(1, 1)).rotation_degrees(), 0) + + self.assertAlmostEqual( + Transform(rotate=35, translate=(10, 20)).rotation_degrees(), 35 + ) + self.assertAlmostEqual( + Transform(rotate=35, translate=(10, 20), scale=5).rotation_degrees(), 35 + ) + self.assertAlmostEqual( + Transform(rotate=35, translate=(10, 20), scale=(5, 5)).rotation_degrees(), + 35, + ) + + def rotation_degrees(**kwargs): + return Transform(**kwargs).rotation_degrees() + + self.assertRaises(ValueError, rotation_degrees, rotate=35, skewx=1) + self.assertRaises(ValueError, rotation_degrees, rotate=35, skewy=1) + self.assertRaises(ValueError, rotation_degrees, rotate=35, scale=(10, 11)) + self.assertRaises(ValueError, rotation_degrees, rotate=35, scale=(10, 11)) + + def test_construction_order(self): + """Test transform kwargs construction order""" + if not PY3: + self.skipTest("Construction order is known to fail on python2 (by design).") + return + + self.assertEqual( + str(Transform(scale=2.0, translate=(5, 6))), "matrix(2 0 0 2 5 6)" + ) + self.assertEqual( + str(Transform(scale=2.0, rotate=45)), + "matrix(1.41421 1.41421 -1.41421 1.41421 0 0)", + ) + + x, y, angle = 5, 7, 31 + rotation = Transform(rotate=angle) + translation = Transform(translate=(x, y)) + + rotation_then_translation = translation @ rotation + translation_then_rotation = rotation @ translation + + tr1 = Transform(rotate=angle, translate=(x, y)) + tr2 = Transform(translate=(x, y), rotate=angle) + + self.assertNotEqual(tr1, tr2) + self.assertDeepAlmostEqual(tr1.matrix, rotation_then_translation.matrix) + self.assertDeepAlmostEqual(tr2.matrix, translation_then_rotation.matrix) + + def test_interpolate(self): + """Test interpolate with other transform""" + t1 = Transform((0, 0, 0, 0, 0, 0)) + t2 = Transform((1, 1, 1, 1, 1, 1)) + val = t1.interpolate(t2, 0.5) + assert all(getattr(val, a) == pytest.approx(0.5, 1e-3) for a in "abcdef") + + +class ScaleTest(TestCase): + """Test scale class""" + + def test_creation(self): + """Creating scales""" + self.assertEqual(BoundingInterval(0, 0), (0, 0)) + self.assertEqual(BoundingInterval(1), (1, 1)) + self.assertEqual(BoundingInterval(10), (10, 10)) + self.assertEqual(BoundingInterval(10, 20), (10, 20)) + self.assertEqual(BoundingInterval((2, 50)), (2, 50)) + self.assertEqual(repr(BoundingInterval((5, 10))), "BoundingInterval(5, 10)") + + def test_center(self): + """Center of a scale""" + self.assertEqual(BoundingInterval(0, 0).center, 0) + self.assertEqual(BoundingInterval(0, 10).center, 5) + self.assertEqual(BoundingInterval(-10, 10).center, 0) + + def test_neg(self): + """-Span(...)""" + self.assertEqual(tuple(-BoundingInterval(-10, 10)), (-10, 10)) + self.assertEqual(tuple(-BoundingInterval(-15, 2)), (-2, 15)) + self.assertEqual(tuple(-BoundingInterval(100, 110)), (-110, -100)) + self.assertEqual(tuple(-BoundingInterval(-110, -100)), (100, 110)) + + def test_size(self): + """Size of the scale""" + self.assertEqual(BoundingInterval(0, 0).size, 0) + self.assertEqual(BoundingInterval(10, 30).size, 20) + self.assertEqual(BoundingInterval(-10, 10).size, 20) + self.assertEqual(BoundingInterval(-30, -10).size, 20) + + def test_combine(self): + """Combine scales together""" + self.assertEqual(BoundingInterval(9, 10) + BoundingInterval(4, 5), (4, 10)) + self.assertEqual( + sum([BoundingInterval(4), BoundingInterval(3), BoundingInterval(10)], None), + (3, 10), + ) + self.assertEqual(BoundingInterval(2, 2) * 2, (4, 4)) + + def test_errors(self): + """Expected errors""" + self.assertRaises(ValueError, BoundingInterval, "foo") + + +class BoundingBoxTest(TestCase): + """Test bounding box calculations""" + + def test_bbox(self): + """Creating bounding boxes""" + self.assertEqual(tuple(BoundingBox(1, 3)), ((1, 1), (3, 3))) + self.assertEqual(tuple(BoundingBox((1, 2), 3)), ((1, 2), (3, 3))) + self.assertEqual(tuple(BoundingBox(1, (3, 4))), ((1, 1), (3, 4))) + self.assertEqual(tuple(BoundingBox((1, 2), (3, 4))), ((1, 2), (3, 4))) + self.assertEqual( + repr(BoundingBox((1, 2), (3, 4))), "BoundingBox((1, 2),(3, 4))" + ) + + def test_bbox_sum(self): + """Test adding bboxes together""" + self.assertEqual( + tuple(BoundingBox((0, 10), (0, 10)) + BoundingBox((-10, 0), (-10, 0))), + ((-10, 10), (-10, 10)), + ) + ret = sum( + [ + BoundingBox((-5, 0), (0, 0)), + BoundingBox((0, 5), (0, 0)), + BoundingBox((0, 0), (-5, 0)), + BoundingBox((0, 0), (0, 5)), + ], + None, + ) + self.assertEqual(tuple(ret), ((-5, 5), (-5, 5))) + self.assertEqual(tuple(BoundingBox(-10, 2) + ret), ((-10, 5), (-5, 5))) + self.assertEqual(tuple(ret + BoundingBox(1, -10)), ((-5, 5), (-10, 5))) + + def test_bbox_neg(self): + self.assertEqual(tuple(-BoundingBox(-10, 2)), ((10, 10), (-2, -2))) + self.assertEqual( + tuple(-BoundingBox((-10, 15), (2, 10))), ((-15, 10), (-10, -2)) + ) + + def test_bbox_scale(self): + """Bounding Boxes can be scaled""" + self.assertEqual(tuple(BoundingBox(1, 3) * 2), ((2, 2), (6, 6))) + + def test_bbox_area(self): + self.assertEqual(BoundingBox((-3, 7), (-5, 5)).area, 100) + + def test_bbox_anchor_left_right(self): + """Bunding box anchoring (left to right)""" + bbox = BoundingBox((-1, 1), (10, 20)) + self.assertEqual( + [ + bbox.get_anchor("l", "t", "lr"), + bbox.get_anchor("m", "t", "lr"), + bbox.get_anchor("r", "t", "lr"), + bbox.get_anchor("l", "t", "rl"), + bbox.get_anchor("m", "t", "rl"), + bbox.get_anchor("r", "t", "rl"), + ], + [-1, 0.0, 1, 1, -0.0, -1], + ) + + def test_bbox_anchor_top_bottom(self): + """Bunding box anchoring (top to bottom)""" + bbox = BoundingBox((10, 20), (-1, 1)) + self.assertEqual( + [ + bbox.get_anchor("l", "t", "tb"), + bbox.get_anchor("l", "m", "tb"), + bbox.get_anchor("l", "b", "tb"), + bbox.get_anchor("l", "t", "bt"), + bbox.get_anchor("l", "m", "bt"), + bbox.get_anchor("l", "b", "bt"), + ], + [-1, 0.0, 1, 1, -0.0, -1], + ) + + def test_bbox_anchor_custom(self): + """Bounding box anchoring custom angle""" + bbox = BoundingBox((10, 10), (5, 5)) + self.assertEqual( + [ + bbox.get_anchor("l", "t", 0), + bbox.get_anchor("l", "t", 90), + bbox.get_anchor("l", "t", 180), + bbox.get_anchor("l", "t", 270), + bbox.get_anchor("l", "t", 45), + ], + [10, -5, -10, 5, 3.5355339059327378], + ) + + def test_bbox_anchor_radial(self): + """Bounding box anchoring radial in/out""" + bbox = BoundingBox((10, 10), (5, 5)) + self.assertRaises(ValueError, bbox.get_anchor, "m", "m", "ro") + selbox = BoundingBox((100, 100), (100, 100)) + self.assertEqual(int(bbox.get_anchor("m", "m", "ro", selbox)), 130) + + +class SegmentTest(TestCase): + """Test special Segments""" + + def test_segment_creation(self): + """Test segments""" + self.assertEqual(DirectedLineSegment((1, 2), (3, 4)), (1, 3, 2, 4)) + self.assertEqual( + repr(DirectedLineSegment((1, 2), (3, 4))), + "DirectedLineSegment((1, 2), (3, 4))", + ) + + def test_segment_maths(self): + """Segments have calculations""" + self.assertEqual(DirectedLineSegment((0, 0), (10, 0)).angle, 0) + self.assertAlmostEqual( + DirectedLineSegment((0, 0), (0.5 * sqrt(3), 0.5)).angle, pi / 6, delta=1e-6 + ) + + def test_segment_dx(self): + """Test segment dx calculation""" + self.assertEqual(DirectedLineSegment((0, 0), (0, 0)).dx, 0) + self.assertEqual(DirectedLineSegment((0, 0), (0, 3)).dx, 0) + self.assertEqual(DirectedLineSegment((0, 0), (3, 0)).dx, 3) + self.assertEqual(DirectedLineSegment((0, 0), (-3, 0)).dx, -3) + self.assertEqual(DirectedLineSegment((5, 0), (1, 0)).dx, -4) + self.assertEqual(DirectedLineSegment((-3, 0), (1, 0)).dx, 4) + + def test_segment_dy(self): + """Test segment dy calculation""" + self.assertEqual(DirectedLineSegment((0, 0), (0, 0)).dy, 0) + self.assertEqual(DirectedLineSegment((0, 0), (3, 0)).dy, 0) + self.assertEqual(DirectedLineSegment((0, 0), (0, 3)).dy, 3) + self.assertEqual(DirectedLineSegment((0, 0), (0, -3)).dy, -3) + self.assertEqual(DirectedLineSegment((0, 5), (0, 1)).dy, -4) + self.assertEqual(DirectedLineSegment((0, -3), (0, 1)).dy, 4) + + def test_segment_vector(self): + """Test segment delta vector""" + self.assertEqual(DirectedLineSegment((0, 0), (2, 3)).vector.to_tuple(), (2, 3)) + self.assertEqual( + DirectedLineSegment((-2, -3), (2, 3)).vector.to_tuple(), (4, 6) + ) + + def test_segment_length(self): + """Test segment length calculation""" + self.assertEqual(DirectedLineSegment((0, 0), (0, 0)).length, 0) + self.assertEqual(DirectedLineSegment((0, 0), (3, 0)).length, 3) + self.assertEqual(DirectedLineSegment((0, 0), (-3, 0)).length, 3) + self.assertEqual(DirectedLineSegment((0, 0), (0, 5)).length, 5) + self.assertEqual(DirectedLineSegment((0, 0), (0, -5)).length, 5) + self.assertEqual(DirectedLineSegment((2, 0), (0, 0)).length, 2) + self.assertEqual(DirectedLineSegment((-2, 0), (0, 0)).length, 2) + self.assertEqual(DirectedLineSegment((0, 4), (0, 0)).length, 4) + self.assertEqual(DirectedLineSegment((0, -4), (0, 0)).length, 4) + self.assertEqual(DirectedLineSegment((0, 0), (3, 4)).length, 5) + self.assertEqual(DirectedLineSegment((-3, -4), (0, 0)).length, 5) + + def test_segment_angle(self): + """Test segment angle calculation""" + self.assertEqual(DirectedLineSegment((0, 0), (3, 0)).angle, 0) + self.assertEqual(DirectedLineSegment((0, 0), (-3, 0)).angle, pi) + self.assertEqual(DirectedLineSegment((0, 0), (0, 5)).angle, pi / 2) + self.assertEqual(DirectedLineSegment((0, 0), (0, -5)).angle, -pi / 2) + self.assertEqual(DirectedLineSegment((2, 0), (0, 0)).angle, pi) + self.assertEqual(DirectedLineSegment((-2, 0), (0, 0)).angle, 0) + self.assertEqual(DirectedLineSegment((0, 4), (0, 0)).angle, -pi / 2) + self.assertEqual(DirectedLineSegment((0, -4), (0, 0)).angle, pi / 2) + self.assertEqual(DirectedLineSegment((0, 0), (1, 1)).angle, pi / 4) + self.assertEqual(DirectedLineSegment((0, 0), (-1, 1)).angle, 3 * pi / 4) + self.assertEqual(DirectedLineSegment((0, 0), (-1, -1)).angle, -3 * pi / 4) + self.assertEqual(DirectedLineSegment((0, 0), (1, -1)).angle, -pi / 4) + + +class ExtremaTest(TestCase): + """Test school formula implementation""" + + def test_cubic_extrema_1(self): + from inkex.transforms import cubic_extrema + + a, b, c, d = ( + 14.644651000000003194, + -4.881549508464541276, + -4.8815495084645448287, + 14.644651000000003194, + ) + cmin, cmax = cubic_extrema(a, b, c, d) + self.assertAlmostEqual(cmin, 0, delta=1e-6) + self.assertAlmostEqual(cmax, a, delta=1e-6) + + def test_quadratic_extrema_1(self): + from inkex.transforms import quadratic_extrema + + a, b = 5.0, 12.0 + cmin, cmax = quadratic_extrema(a, b, a) + self.assertAlmostEqual(cmin, 5, delta=1e-6) + self.assertAlmostEqual(cmax, 8.5, delta=1e-6) + + def test_quadratic_extrema_2(self): + from inkex.transforms import quadratic_extrema + + a = 5.0 + cmin, cmax = quadratic_extrema(a, a, a) + self.assertAlmostEqual(cmin, a, delta=1e-6) + self.assertAlmostEqual(cmax, a, delta=1e-6) diff --git a/share/extensions/tests/test_inkex_tween.py b/share/extensions/tests/test_inkex_tween.py new file mode 100644 index 0000000..f1eabf1 --- /dev/null +++ b/share/extensions/tests/test_inkex_tween.py @@ -0,0 +1,215 @@ +# coding=utf-8 +# +# Copyright (C) 2020-2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +"""Test interpolation inkex module functionality""" +from inkex.tester import TestCase + +import inkex +import inkex.tween as tween +import pytest +import numpy as np + + +class TweenTest(TestCase): + """Unit tests for the Inkscape inkex tween library""" + + black = inkex.Color("#000000") + grey50 = inkex.Color("#080808") + white = inkex.Color("#111111") + + def test_interpcoord(self): + val = tween.interpcoord(0, 1, 0.5) + assert val == pytest.approx(0.5, 1e-3) + + def test_interppoints(self): + val = tween.interppoints((0, 0), (1, 1), 0.5) + assert val == pytest.approx((0.5, 0.5), (1e-3, 1e-3)) + + def initialize_gradient(self, lg, stoparray): + for key, value in stoparray.items(): + stop = inkex.Stop() + stop.style = inkex.Style() + stop.style["stop-color"] = value + stop.offset = key + lg.add(stop) + + def initialize_linear_gradient(self, bounding_box, stoparray): + lg = inkex.LinearGradient() + self.initialize_gradient(lg, stoparray) + lg.set("x1", bounding_box.left) + lg.set("x2", bounding_box.right) + lg.set("y1", bounding_box.center.y) + lg.set("y2", bounding_box.center.y) + return lg + + def initialize_radial_gradient(self, bounding_box, stoparray): + grad = inkex.RadialGradient() + self.initialize_gradient(grad, stoparray) + grad.set("cx", bounding_box.center.x) + grad.set("cy", bounding_box.center.y) + grad.set("fx", bounding_box.center.x) + grad.set("fy", bounding_box.center.y) + grad.set("r", bounding_box.right - bounding_box.center.x) + return grad + + def test_fill_interpolator(self): + svg = inkex.SvgDocumentElement() + p1 = inkex.PathElement( + d="M 5.23564,33.586285 46.410969,-0.94834 89.873815,35.045501 Z" + ) + p2 = inkex.PathElement( + d="m 136.32372,31.390088 c 0,0 -65.213764,-4.27631 18.17433,-22.4506304 83.38809,-18.17434 64.14469,35.2795704 64.14469,35.2795704 z" + ) + p3 = inkex.Rectangle() + svg.add(p1, p2, p3) + g1 = self.initialize_linear_gradient( + p1.bounding_box(), {0: "#ff0000", 0.5: "#00ff00", 1: "#0000ff"} + ) + g2 = self.initialize_linear_gradient( + p2.bounding_box(), + {0: "#ff0000", 0.25: "#ff0000", 0.75: "#0000ff", 1: "#0000ff"}, + ) + g3 = self.initialize_radial_gradient( + p2.bounding_box(), {0: "#ff0000", 0.5: "#00ff00", 1: "#0000ff"} + ) + grad1 = tween.GradientInterpolator.append_to_doc(svg, g1) + grad2 = tween.GradientInterpolator.append_to_doc(svg, g2) + grad3 = tween.GradientInterpolator.append_to_doc(svg, g3) + expected = [ + [ + {"fill": "#640000"}, + {"fill": "#320000"}, + {"fill": [75, 0, 0]}, + ], # both only fill + [ + {"fill": "none"}, + {"fill": "#320000"}, + {"fill": [50, 0, 0], "fill-opacity": 0.5}, + ], # interpolate via fill-opacity + [{"fill": "none"}, {}, {"fill": [0, 0, 0]}], # only one fill set to None + [ + {"fill": "#00ff00"}, + {"fill": grad1}, + { + "fill/grad/stops": [ + [0, "#7f7f00"], + [0.5, "#00ff00"], + [1, "#007f7f"], + ], + "fill/grad/x1": "5.23564px", + }, + ], + [ + {"fill": "#00ff00"}, + {"fill": grad3}, + { + "fill/grad/stops": [ + [0, "#7f7f00"], + [0.5, "#00ff00"], + [1, "#007f7f"], + ], + "fill/grad/cx": "106.932px", + }, + ], + [{"fill": grad2}, {"fill": grad3}, {"fill": grad2}], + [ + {"fill": grad1}, + {"fill": grad2}, + { + "fill/grad/stops": [ + [0, "#ff0000"], + [0.25, "#bf3f00"], + [0.5, "#3f7f3f"], + [0.75, "#003fbf"], + [1, "#0000ff"], + ] + }, + ], + [ + {"fill": "none"}, + {"fill": grad1}, + { + "fill/grad/stops": [ + [0, "#ff0000"], + [0.5, "#00ff00"], + [1, "#0000ff"], + ], + "fill/grad/x1": "5.23564px", + }, + ], + ] + + for sstyle, estyle, interpstyle in expected: + p1.style = inkex.Style() + p1.style.update(sstyle) + p2.style = inkex.Style() + p2.style.update(estyle) + + interpolator = tween.StyleInterpolator(p1, p2) + p3.style = interpolator.interpolate(0.5) + for key, value in interpstyle.items(): + keys = key.split("/") + if keys[0] == "fill": + newfill = p3.style("fill") + if key == "fill": + assert newfill == value + elif keys[1] == "grad": + assert isinstance( + newfill, (inkex.LinearGradient, inkex.RadialGradient) + ) + if keys[2] == "stops": + assert len(value) == len(newfill.stops) + for idx, _ in enumerate(value): + assert ( + newfill.stops[idx].style["stop-color"] + == value[idx][1] + ) + self.assertAlmostEqual( + float(newfill.stop_offsets[idx]), + value[idx][0], + 1e-3, + ) + else: + assert newfill.get(keys[2]) == value + else: + assert p3.style(key) == value + + def test_path_interpolation(self): + p1 = inkex.Path("M 5.23564,33.586285 46.410969,-0.94834 89.873815,35.045501 Z") + p2 = inkex.Path( + "m 136.32372,31.390088 c 0,0 -65.213764,-4.27631 18.17433,-22.4506304 83.38809,-18.17434 64.14469,35.2795704 64.14469,35.2795704 z" + ) + pel1 = inkex.PathElement() + pel2 = inkex.PathElement() + pel1.path = p1 + pel2.path = p2 + result_method_1 = "M 70.7798 32.4882 C 70.7798 32.4882 58.7606 13.0827 100.455 3.99558 C 142.149 -5.09157 154.258 39.6323 154.258 39.6323 Z" + result_method_2 = "M 70.7798 32.4882 C 70.7798 32.4882 59.6785 13.1429 98.726 4.37785 C 99.2875 4.25181 100.254 4.44741 101.52 4.87808 C 126.751 3.94755 151.064 21.8659 153.864 27.4179 C 156.66 32.9612 150.143 39.5613 144.479 39.4637 C 131.98 39.2482 70.7798 32.4882 70.7798 32.4882" + calls = [ + [None, result_method_1], + [tween.FirstNodesInterpolator, result_method_1], + [tween.EqualSubsegmentsInterpolator, result_method_2], + ] + + for arg, expected in calls: + interp = tween.AttributeInterpolator.create_from_attribute( + pel1, pel2, "d", method=arg + ) + result = interp.interpolate(0.5) + print(result) + assert np.allclose(result, inkex.CubicSuperPath(inkex.Path(expected))) diff --git a/share/extensions/tests/test_inkex_units.py b/share/extensions/tests/test_inkex_units.py new file mode 100644 index 0000000..7cabf5d --- /dev/null +++ b/share/extensions/tests/test_inkex_units.py @@ -0,0 +1,71 @@ +# coding=utf-8 +"""Test units inkex module functionality""" +from inkex.units import ( + are_near_relative, + convert_unit, + discover_unit, + parse_unit, + render_unit, +) +from inkex.tester import TestCase + + +class UnitsTest(TestCase): + """Tests for Inkscape Units handling""" + + def test_parse_unit(self): + """Test parsing a unit in a document""" + self.assertEqual(parse_unit("50px"), (50.0, "px")) + self.assertEqual(parse_unit("50"), (50.0, "px")) + self.assertEqual(parse_unit("50quaks"), None) + self.assertEqual(parse_unit("50quaks", default_value=10), (10.0, "px")) + self.assertEqual(parse_unit("50%"), (50.0, "%")) + + def test_near(self): + """Test the closeness of numbers""" + self.assertFalse(are_near_relative(10.0, 5.0)) + self.assertTrue(are_near_relative(10.0, 9.99)) + + def test_discover_unit(self): + """Based on the size of a document and it's viewBox""" + self.assertEqual(discover_unit("50px", 50), "px") + self.assertEqual(discover_unit("100mm", 3.94), "in") + self.assertEqual(discover_unit("3779", 1.0), "m") + self.assertEqual(discover_unit("50quaks", 150), "px") + + def test_convert_unit(self): + """Convert units from one to another""" + self.assertEqual(convert_unit("10mm", "px"), 37.79527559055118) + self.assertEqual(convert_unit("1in", "cm"), 2.54) + self.assertEqual(convert_unit("37.79527559055118px", "mm"), 10.0) + self.assertEqual(convert_unit("1in", ""), 96.0) + self.assertEqual(convert_unit("96", "in"), 1.0) + self.assertEqual(convert_unit("10%", "mm"), 0.0) + self.assertEqual(convert_unit("1in", "grad"), 0.0) + self.assertEqual(convert_unit("10quaks", "mm"), 0.0) + self.assertEqual(convert_unit("10mm", "quaks"), 0.0) + + def test_render_unit(self): + """Convert unit and value pair into rendered unit string""" + self.assertEqual(render_unit(10.0, "mm"), "10mm") + self.assertEqual(render_unit(10.01, "mm"), "10.01mm") + self.assertEqual(render_unit(10.000001, "mm"), "10mm") + self.assertEqual(render_unit("10cm", "mm"), "10cm") + + def test_number_parsing(self): + """Width number parsing test""" + for value in ( + "100mm", + "100 mm", + " 100mm", + "100mm ", + "+100mm", + "100.0mm", + "100.0e0mm", + "10.0e1mm", + "10.0e+1mm", + "1000.0e-1mm", + ".1e+3mm", + "+.1e+3mm", + ): + self.assertEqual(parse_unit(value), (100, "mm")) diff --git a/share/extensions/tests/test_inkex_utils.py b/share/extensions/tests/test_inkex_utils.py new file mode 100644 index 0000000..8917e23 --- /dev/null +++ b/share/extensions/tests/test_inkex_utils.py @@ -0,0 +1,186 @@ +# coding=utf-8 +""" +Unit test file for ../inkex.py +""" +# Revision history: +# * 2012-01-27 (jazzynico): check errormsg function. +# +from __future__ import absolute_import, print_function + +from argparse import ArgumentTypeError + +import pytest + +from inkex.utils import ( + debug, + errormsg, + filename_arg, + Boolean, + parse_percent, + to, + strargs, + math_eval, + is_number, +) +from inkex.tester import TestCase + +from inkex import addNS + + +class TestInkexBasic(object): + """Test basic utiltiies of inkex""" + + def test_boolean(self): + """Inkscape boolean input""" + assert Boolean("TRUE") is True + assert Boolean("true") is True + assert Boolean("True") is True + assert Boolean("FALSE") is False + assert Boolean("false") is False + assert Boolean("False") is False + assert Boolean("Banana") is None + + def test_debug(self, capsys): + """Debug messages go to stderr""" + debug("Hello World") + assert capsys.readouterr().err == "Hello World\n" + + def test_to(self): + """Decorator for generators""" + + @to(list) + def mylist(a, b, c): + """Yield as a list""" + yield a + yield c + yield b + + assert isinstance(mylist(1, 2, 3), list) + assert mylist(1, 2, 3) == [1, 3, 2] + + @to(dict) + def mydict(a, b, c): + """Yield as a dictionary""" + yield ("age", a) + yield ("name", c) + yield ("home", b) + + assert isinstance(mydict(1, 2, 3), dict) + assert mydict(1, 2, 3) == {"age": 1, "name": 3, "home": 2} + + def test_filename(self): + """Filename argument input""" + assert filename_arg(__file__) == __file__ + with pytest.raises(ArgumentTypeError): + filename_arg("doesntexist.txt") + + def test_add_ns(self): + """Test addNS function""" + assert ( + addNS("inkscape:foo") == "{http://www.inkscape.org/namespaces/inkscape}foo" + ) + assert ( + addNS("bar", "inkscape") + == "{http://www.inkscape.org/namespaces/inkscape}bar" + ) + assert addNS("url", "rdf") == "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}url" + assert ( + addNS("{http://www.inkscape.org/namespaces/inkscape}bar") + == "{http://www.inkscape.org/namespaces/inkscape}bar" + ) + assert ( + addNS("http://www.inkscape.org/namespaces/inkscape:bar") + == "{http://www.inkscape.org/namespaces/inkscape}bar" + ) + assert ( + addNS("car", "http://www.inkscape.org/namespaces/inkscape") + == "{http://www.inkscape.org/namespaces/inkscape}car" + ) + assert ( + addNS("{http://www.inkscape.org/namespaces/inkscape}bar", "rdf") + == "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}bar" + ) + + def test_strargs(self): + """Test strargs function""" + assert strargs("1.0 2.0 3.0 4.0") == [1.0, 2.0, 3.0, 4.0] + assert strargs("1 -2 3 -4") == [1.0, -2.0, 3.0, -4.0] + assert strargs("1,-2,3,-4") == [1.0, -2.0, 3.0, -4.0] + assert strargs("1-2 3-4") == [1.0, -2.0, 3.0, -4.0] + assert strargs("1-2,3-4") == [1.0, -2.0, 3.0, -4.0] + assert strargs("1-2-3-4") == [1.0, -2.0, -3.0, -4.0] + assert strargs("+1 +2") == [1.0, 2.0] + assert strargs("1.2.3.4.5") == [1.2, 0.3, 0.4, 0.5] + assert strargs("1. 2..3.4") == [1.0, 2.0, 0.3, 0.4] + assert strargs("1.0e-1 -2.0e-1 3.0e10 -4.0e10") == [ + 0.1, + -0.2, + 30000000000, + -40000000000, + ] + assert strargs("1.0e-1,-2.0e-1,3.0e10,-4.0e10") == [ + 0.1, + -0.2, + 30000000000, + -40000000000, + ] + assert strargs("1.0E-1 -2.0E-1 3.0E10 -4.0E10") == [ + 0.1, + -0.2, + 30000000000, + -40000000000, + ] + assert strargs("1.0E-1,-2.0E-1,3.0E10,-4.0E10") == [ + 0.1, + -0.2, + 30000000000, + -40000000000, + ] + assert strargs("1.E2+.3E+4") == [100, 3000] + + def test_ascii(self, capsys): + """Parse ABCabc""" + errormsg("ABCabc") + assert capsys.readouterr().err == "ABCabc\n" + + def test_nonunicode_latin1(self, capsys): + # Py2 has issues with unicode in docstrings. *sigh* + # """Parse Àûïàèé""" + errormsg("Àûïàèé") + assert capsys.readouterr().err, "Àûïàèé\n" + + def test_unicode_latin1(self, capsys): + # Py2 has issues with unicode in docstrings. *sigh* + # """Parse Àûïàèé (unicode)""" + errormsg("Àûïàèé") + assert capsys.readouterr().err, "Àûïàèé\n" + + def test_parse_percent(self): + assert parse_percent("75%") == 0.75 + assert parse_percent("0.75") == 0.75 + assert parse_percent("75") == 75 + + +import math + + +class TestMathFunctions(TestCase): + def testExp(self): + """Test if the math_eval function works""" + function = "exp(x)" + f = math_eval(function) + self.assertAlmostEqual(f(1), math.exp(1)) + + def testErf(self): + """Only available in python3""" + function = "erf(x)" + f = math_eval(function) + self.assertAlmostEqual(f(1), math.erf(1)) + + def test_is_number(self): + self.assertTrue(is_number("155")) + self.assertTrue(is_number("12.5")) + self.assertTrue(is_number("12.5e-5")) + self.assertFalse(is_number("10=3")) + self.assertFalse(is_number("")) + self.assertFalse(is_number("a")) diff --git a/share/extensions/tests/test_inkscape_follow_link.py b/share/extensions/tests/test_inkscape_follow_link.py new file mode 100644 index 0000000..5c78438 --- /dev/null +++ b/share/extensions/tests/test_inkscape_follow_link.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from inkscape_follow_link import FollowLink +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestFollowLinkBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = FollowLink diff --git a/share/extensions/tests/test_inkwebeffect.py b/share/extensions/tests/test_inkwebeffect.py new file mode 100644 index 0000000..16c0c24 --- /dev/null +++ b/share/extensions/tests/test_inkwebeffect.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from inkwebeffect import InkWebEffect +from inkex.tester import InkscapeExtensionTestMixin, TestCase + + +class InkWebEffectBasicTest(InkscapeExtensionTestMixin, TestCase): + effect_class = InkWebEffect diff --git a/share/extensions/tests/test_interp.py b/share/extensions/tests/test_interp.py new file mode 100644 index 0000000..79da66a --- /dev/null +++ b/share/extensions/tests/test_interp.py @@ -0,0 +1,40 @@ +# coding=utf-8 +from interp import Interp +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class InterpBasicTest(ComparisonMixin, TestCase): + effect_class = Interp + comparisons = [ + ( + "--id=path1", + "--id=path2", + "--id=path3", + "--id=path4", + "--id=path5", + "--id=path6", + "--id=path7", + "--id=path8", + "--id=path9", + "--id=path10", + "--method=equalSubsegments", + "--style=True", + ), + ( + "--id=path1", + "--id=path2", + "--id=path3", + "--id=path4", + "--id=path5", + "--id=path6", + "--id=path7", + "--id=path8", + "--id=path9", + "--id=path10", + "--method=firstNodes", + "--style=True", + ), + ] + compare_filters = [CompareNumericFuzzy()] + compare_file = "svg/interp_shapes.svg" diff --git a/share/extensions/tests/test_interp_att_g.py b/share/extensions/tests/test_interp_att_g.py new file mode 100644 index 0000000..4f07e52 --- /dev/null +++ b/share/extensions/tests/test_interp_att_g.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# coding=utf-8 +from interp_att_g import InterpAttG +from inkex.tester import ComparisonMixin, TestCase + + +class InterpAttGBasicTest(ComparisonMixin, TestCase): + effect_class = InterpAttG + comparisons = [("--id=layer1", "--att=style/fill")] + + +class InterpAttGMultipleSelectedTest(ComparisonMixin, TestCase): + effect_class = InterpAttG + comparisons = [("--id=c1", "--id=c2", "--id=c3", "--att=style/fill")] + + +class InterpAttGColorRoundingTest(ComparisonMixin, TestCase): + effect_class = InterpAttG + compare_file = "svg/group_interpolate.svg" + comparisons = [ + # test for truncating/rounding bug inbox#1892 + ("--id=g53", "--att=style/fill", "--start-val=#181818", "--end-val=#000000"), + # test for clipping of values <= 1 + ("--id=g53", "--att=style/fill", "--start-val=#050505", "--end-val=#000000"), + ] + + +class InterpAttGOtherAttributeTest(ComparisonMixin, TestCase): + # interpolate other values (test base.arg_class) + effect_class = InterpAttG + compare_file = "svg/group_interpolate.svg" + comparisons = [ + ( + "--id=g53", + "--att=other", + "--att-other=width", + "--start-val=5", + "--end-val=10", + "--att-other-type=ValueInterpolator", + ), + ( + "--id=g53", + "--att=other", + "--att-other=fill", + "--att-other-where=style", + "--start-val=red", + "--end-val=green", + "--att-other-type=ColorInterpolator", + ), + ] + + +class InterpAttGTransformInterpolateTest(ComparisonMixin, TestCase): + effect_class = InterpAttG + compare_file = "svg/group_interpolate.svg" + comparisons = [ + ("--id=g53", "--att=transform/scale", "--start-val=0.2", "--end-val=0.9"), + ("--id=g53", "--att=transform/trans-x", "--start-val=0", "--end-val=20"), + ] + + +class InterpAttGUnitsTest(ComparisonMixin, TestCase): + effect_class = InterpAttG + compare_file = "svg/group_interpolate.svg" + comparisons = [ + ("--id=g53", "--att=width", "--start-val=0.02", "--end-val=0.1", "--unit=mm") + ] diff --git a/share/extensions/tests/test_jessyink_autotexts.py b/share/extensions/tests/test_jessyink_autotexts.py new file mode 100644 index 0000000..a252ff3 --- /dev/null +++ b/share/extensions/tests/test_jessyink_autotexts.py @@ -0,0 +1,9 @@ +#!/usr/bin/en +# coding=utf-8 +from jessyink_autotexts import AutoTexts +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkAutoTextsBasicTest(ComparisonMixin, TestCase): + effect_class = AutoTexts + comparisons = [("--autoText", "slideTitle", "--id", "t1")] diff --git a/share/extensions/tests/test_jessyink_effects.py b/share/extensions/tests/test_jessyink_effects.py new file mode 100644 index 0000000..ab9a719 --- /dev/null +++ b/share/extensions/tests/test_jessyink_effects.py @@ -0,0 +1,12 @@ +#!/usr/bin/en +# coding=utf-8 +from jessyink_effects import JessyinkEffects +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkEffectsTest(ComparisonMixin, TestCase): + effect_class = JessyinkEffects + comparisons = [ + ("--id=p1", "--id=r3", "--effectOutOrder=2"), + ("--id=p1", "--effectIn=fade", "--effectOut=pop", "--effectOutOrder=2"), + ] diff --git a/share/extensions/tests/test_jessyink_export.py b/share/extensions/tests/test_jessyink_export.py new file mode 100644 index 0000000..3eca739 --- /dev/null +++ b/share/extensions/tests/test_jessyink_export.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from jessyink_export import Export +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareSize + + +class JessyInkExportBasicTest(ComparisonMixin, TestCase): + compare_filters = [CompareSize()] + effect_class = Export + comparisons = [("--resolution=1", "--type=png")] diff --git a/share/extensions/tests/test_jessyink_install.py b/share/extensions/tests/test_jessyink_install.py new file mode 100644 index 0000000..f98f7f1 --- /dev/null +++ b/share/extensions/tests/test_jessyink_install.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from jessyink_install import Install +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkInstallBasicTest(ComparisonMixin, TestCase): + effect_class = Install diff --git a/share/extensions/tests/test_jessyink_keybindings.py b/share/extensions/tests/test_jessyink_keybindings.py new file mode 100644 index 0000000..28b19be --- /dev/null +++ b/share/extensions/tests/test_jessyink_keybindings.py @@ -0,0 +1,11 @@ +# coding=utf-8 +from jessyink_key_bindings import KeyBindings +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkCustomKeyBindingsBasicTest(ComparisonMixin, TestCase): + effect_class = KeyBindings + comparisons = [ + ("--slide_export=SPACE", "--drawing_undo=ENTER", "--index_nextPage=LEFT"), + ("--slide_export=a", "--drawing_undo=b", "--index_nextPage=c"), + ] diff --git a/share/extensions/tests/test_jessyink_masterslide.py b/share/extensions/tests/test_jessyink_masterslide.py new file mode 100644 index 0000000..87fc56e --- /dev/null +++ b/share/extensions/tests/test_jessyink_masterslide.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from jessyink_master_slide import MasterSlide +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkMasterSlideBasicTest(ComparisonMixin, TestCase): + effect_class = MasterSlide diff --git a/share/extensions/tests/test_jessyink_mousehandler.py b/share/extensions/tests/test_jessyink_mousehandler.py new file mode 100644 index 0000000..67452de --- /dev/null +++ b/share/extensions/tests/test_jessyink_mousehandler.py @@ -0,0 +1,14 @@ +# coding=utf-8 +from jessyink_mouse_handler import AddMouseHandler +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkAddMouseHandlerTest(ComparisonMixin, TestCase): + """Test jessy ink mouse handler""" + + effect_class = AddMouseHandler + comparisons = [ + ("--mouseSetting=default",), + ("--mouseSetting=noclick",), + ("--mouseSetting=draggingZoom",), + ] diff --git a/share/extensions/tests/test_jessyink_summary.py b/share/extensions/tests/test_jessyink_summary.py new file mode 100644 index 0000000..8c5c23f --- /dev/null +++ b/share/extensions/tests/test_jessyink_summary.py @@ -0,0 +1,11 @@ +# coding=utf-8 +from jessyink_summary import Summary +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import WindowsTextCompat + + +class JessyInkSummaryTest(ComparisonMixin, TestCase): + stderr_output = True + effect_class = Summary + comparisons = [()] + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_jessyink_transitions.py b/share/extensions/tests/test_jessyink_transitions.py new file mode 100644 index 0000000..c762684 --- /dev/null +++ b/share/extensions/tests/test_jessyink_transitions.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from jessyink_transitions import Transitions +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkTransitionsBasicTest(ComparisonMixin, TestCase): + effect_class = Transitions + comparisons = [("--layerName", "Slide2")] diff --git a/share/extensions/tests/test_jessyink_uninstall.py b/share/extensions/tests/test_jessyink_uninstall.py new file mode 100644 index 0000000..6272600 --- /dev/null +++ b/share/extensions/tests/test_jessyink_uninstall.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from jessyink_uninstall import Uninstall +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkUninstallBasicTest(ComparisonMixin, TestCase): + effect_class = Uninstall + comparisons = [()] diff --git a/share/extensions/tests/test_jessyink_video.py b/share/extensions/tests/test_jessyink_video.py new file mode 100644 index 0000000..43c9d95 --- /dev/null +++ b/share/extensions/tests/test_jessyink_video.py @@ -0,0 +1,9 @@ +# coding=utf-8 + +from jessyink_video import Video +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkEffectsBasicTest(ComparisonMixin, TestCase): + effect_class = Video + comparisons = [()] diff --git a/share/extensions/tests/test_jessyink_view.py b/share/extensions/tests/test_jessyink_view.py new file mode 100644 index 0000000..5b7c4f3 --- /dev/null +++ b/share/extensions/tests/test_jessyink_view.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from jessyink_view import View +from inkex.tester import ComparisonMixin, TestCase + + +class JessyInkEffectsBasicTest(ComparisonMixin, TestCase): + effect_class = View + comparisons = [("--id=r3", "--viewOrder=1")] diff --git a/share/extensions/tests/test_jitternodes.py b/share/extensions/tests/test_jitternodes.py new file mode 100644 index 0000000..81f8333 --- /dev/null +++ b/share/extensions/tests/test_jitternodes.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from jitternodes import JitterNodes +from inkex.tester import ComparisonMixin, TestCase + + +class JitterNodesBasicTest(ComparisonMixin, TestCase): + effect_class = JitterNodes + comparisons = [ + ("--id=p1", "--dist=gaussian", "--end=false", "--ctrl=true"), + ("--id=p1", "--dist=uniform", "--ctrl=false"), + ("--id=p1", "--dist=pareto", "--radiusy=100", "--ctrl=true"), + ("--id=p1", "--dist=lognorm", "--radiusx=100", "--ctrl=true"), + ] diff --git a/share/extensions/tests/test_layer2png.py b/share/extensions/tests/test_layer2png.py new file mode 100644 index 0000000..d1d7b84 --- /dev/null +++ b/share/extensions/tests/test_layer2png.py @@ -0,0 +1,42 @@ +""" +Test export slices of an image. +""" + +from inkex.tester import ComparisonMixin, TestCase +from layer2png import ExportSlices + + +class Layer2PNGTest(ComparisonMixin, TestCase): + effect_class = ExportSlices + compare_file = "svg/slicer.svg" + comparisons = [] + + def test_get_layers(self): + basic_svg = self.data_file("svg", "slicer.svg") + args = [basic_svg, "--layer=slices"] + self.effect.options = self.effect.arg_parser.parse_args(args) + self.effect.options.input_file = basic_svg + self.effect.load_raw() + nodes = self.effect.get_layer_nodes("slices") + self.assertEqual(len(nodes), 1) + self.assertEqual(nodes[0].tag, "{http://www.w3.org/2000/svg}rect") + + def test_bad_slice_layer(self): + basic_svg = self.data_file("svg", "slicer.svg") + args = [basic_svg, "--layer=slices"] + self.effect.options = self.effect.arg_parser.parse_args(args) + self.effect.options.input_file = basic_svg + self.effect.load_raw() + nodes = self.effect.get_layer_nodes("badslices") + self.assertEqual(nodes, None) + + def test_color(self): + basic_svg = self.data_file("svg", "slicer.svg") + args = [basic_svg, "--layer=slices"] + self.effect.options = self.effect.arg_parser.parse_args(args) + self.effect.options.input_file = basic_svg + self.effect.load_raw() + nodes = self.effect.get_layer_nodes("slices") + color, kwargs = self.effect.get_color_and_command_kwargs(nodes[0]) + self.assertEqual(color, self.effect.GREEN) + self.assertEqual(kwargs["export-id"], "slice1") diff --git a/share/extensions/tests/test_layers2svgfont.py b/share/extensions/tests/test_layers2svgfont.py new file mode 100644 index 0000000..8a24c31 --- /dev/null +++ b/share/extensions/tests/test_layers2svgfont.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from layers2svgfont import LayersToSvgFont +from inkex.tester import ComparisonMixin, TestCase + + +class TestLayers2SVGFontBasic(ComparisonMixin, TestCase): + effect_class = LayersToSvgFont + compare_file = ["svg/font_layers.svg", "svg/font_layers_apostrophe.svg"] + comparisons = [()] diff --git a/share/extensions/tests/test_layout_nup.py b/share/extensions/tests/test_layout_nup.py new file mode 100644 index 0000000..32f663c --- /dev/null +++ b/share/extensions/tests/test_layout_nup.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from layout_nup import Nup +from inkex.tester import InkscapeExtensionTestMixin, TestCase + + +class TestNupBasic(InkscapeExtensionTestMixin, TestCase): + effect_class = Nup diff --git a/share/extensions/tests/test_lindenmayer.py b/share/extensions/tests/test_lindenmayer.py new file mode 100644 index 0000000..2c71b3b --- /dev/null +++ b/share/extensions/tests/test_lindenmayer.py @@ -0,0 +1,22 @@ +# coding=utf-8 +from lindenmayer import Lindenmayer +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle, CompareWithPathSpace + + +class LSystemBasicTest(ComparisonMixin, TestCase): + effect_class = Lindenmayer + compare_filters = [CompareOrderIndependentStyle(), CompareWithPathSpace()] + comparisons = [ + (), + # left-looking Koch snowflake (one iteration) + ("--rules=F=F+F--F+F", "--axiom=F", "--order=1", "--langle=60", "--rangle=60"), + # test multiple rules: right pointing Sierpinski triangle + ( + "--rules=F=F-E+F+E-F;E=EE", + "--axiom=F-E-E", + "--order=3", + "--langle=120", + "--rangle=120", + ), + ] diff --git a/share/extensions/tests/test_lorem_ipsum.py b/share/extensions/tests/test_lorem_ipsum.py new file mode 100644 index 0000000..5147114 --- /dev/null +++ b/share/extensions/tests/test_lorem_ipsum.py @@ -0,0 +1,21 @@ +# coding=utf-8 +from lorem_ipsum import LoremIpsum +from inkex.tester import ComparisonMixin, TestCase + + +class LorumIpsumBasicTest(ComparisonMixin, TestCase): + effect_class = LoremIpsum + compare_file = "svg/shapes.svg" + comparisons = [ + (), + ["--svg2=false"], + ["--id=r1"], + ["--id=r1", "--svg2=false"], + ["--id=t4"], + ] + + +class LoremIpsumMillimeters(ComparisonMixin, TestCase): + effect_class = LoremIpsum + compare_file = "svg/complextransform.test.svg" + comparisons = [("--svg2=true",)] diff --git a/share/extensions/tests/test_markers_strokepaint.py b/share/extensions/tests/test_markers_strokepaint.py new file mode 100644 index 0000000..8a31fec --- /dev/null +++ b/share/extensions/tests/test_markers_strokepaint.py @@ -0,0 +1,26 @@ +# coding=utf-8 +# +# Unit test file for ../markers_strokepaint.py +# Revision history: +# * 2012-01-27 (jazzynico): checks defaulf parameters and file handling. +# +from markers_strokepaint import MarkersStrokePaint +from inkex.tester import ComparisonMixin, TestCase + + +class MarkerStrokePaintBasicTest(ComparisonMixin, TestCase): + effect_class = MarkersStrokePaint + compare_file = "svg/markers.svg" + comparisons = [ + ('--tab="object"', "--id=dimension", "--type=stroke"), + ('--tab="custom"', "--id=dimension", "--type=stroke"), + ] + + def test_basic(self): + args = ["--id=dimension", self.data_file("svg", "markers.svg")] + eff = MarkersStrokePaint() + eff.run(args) + old_markers = eff.original_document.getroot().xpath("//svg:defs//svg:marker") + new_markers = eff.svg.xpath("//svg:defs//svg:marker") + self.assertEqual(len(old_markers), 2) + self.assertEqual(len(new_markers), 4) diff --git a/share/extensions/tests/test_measure.py b/share/extensions/tests/test_measure.py new file mode 100644 index 0000000..81f8b14 --- /dev/null +++ b/share/extensions/tests/test_measure.py @@ -0,0 +1,33 @@ +# coding=utf-8 +from inkex.utils import filename_arg +from measure import MeasureLength +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + +olddefaults = ("--fontsize=20", "--unit=mm", "--scale=1.1") + + +class LengthBasicTest(ComparisonMixin, TestCase): + effect_class = MeasureLength + compare_filters = [CompareNumericFuzzy()] + comparisons = [ + ("--id=p1", "--id=p2", "--presetFormat=TaP_start") + olddefaults, + ("--method=presets", "--presetFormat=TaP_start", "--id=p1") + olddefaults, + ("--method=presets", "--presetFormat=TaP_end", "--id=p2") + olddefaults, + ("--method=presets", "--presetFormat=FT_start", "--id=p1") + olddefaults, + ("--method=presets", "--presetFormat=FT_bbox", "--id=p2") + olddefaults, + ("--method=presets", "--presetFormat=FT_bbox", "--id=p2") + olddefaults, + ("--type=area", "--id=p1", "--presetFormat=TaP_start") + olddefaults, + ("--type=cofm", "--id=c3", "--presetFormat=TaP_start") + olddefaults, + ] + + +class LengthComplexTransformTest(ComparisonMixin, TestCase): + effect_class = MeasureLength + compare_filters = [CompareNumericFuzzy()] + compare_file = "svg/complextransform.test.svg" + comparisons = [ + ("--method=presets", "--presetFormat=TaP_start", "--id=D") + olddefaults, + ("--method=presets", "--presetFormat=FT_start", "--id=D") + olddefaults, + ("--type=cofm", "--id=D", "--presetFormat=TaP_start") + olddefaults, + ] diff --git a/share/extensions/tests/test_media_zip.py b/share/extensions/tests/test_media_zip.py new file mode 100644 index 0000000..674283a --- /dev/null +++ b/share/extensions/tests/test_media_zip.py @@ -0,0 +1,56 @@ +# coding=utf-8 +import io +import zipfile + +import re + +from media_zip import CompressedMedia +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareSize + + +class CmoTestEmbed(TestCase): + def test_complex(self): + params = (self.data_file("svg", "embed.svg"), "--font_list=True") + cmo = CompressedMedia() + out = io.BytesIO() + cmo.run(params, output=out) + + result = io.BytesIO(out.getvalue()) + + with zipfile.ZipFile(result, mode="r") as f: + files = f.filelist + files = {i.filename for i in files} + self.assertEqual( + files, + { + "images/linecap.png", # this file is referenced twice + # this file has the same filename, but + # different source path, so a 1 is appended + "images/linecap1.png", + "images/markers.svg", + "embed.svg", + "fontlist.txt", + }, + ) + # Assert that the image tags have updated links + svg = f.read("embed.svg").decode("utf8") + matches = re.finditer(r'xlink:href="(.*)"', svg) + self.assertEqual(len(list(matches)), 5) + for match in matches: + if match.groups(1).startswith("data"): + continue + self.assertTrue(match.groups(1).startswith("images/")) + + # Assert that the font list is correct + fontlist = f.read("fontlist.txt").decode("utf8") + fontlist = fontlist.splitlines()[1:] + self.assertEqual( + fontlist, + [ + "'Courier New' normal", + "'Times New Roman'", + "Arial normal", + "Verdana normal", + ], + ) diff --git a/share/extensions/tests/test_merge_styles.py b/share/extensions/tests/test_merge_styles.py new file mode 100644 index 0000000..b0a31cd --- /dev/null +++ b/share/extensions/tests/test_merge_styles.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from merge_styles import MergeStyles +from inkex.tester import ComparisonMixin, TestCase + + +class TestMergeStylesBasic(ComparisonMixin, TestCase): + """Test merging of styles""" + + effect_class = MergeStyles + comparisons = [("--id=c2", "--id=c3")] diff --git a/share/extensions/tests/test_motion.py b/share/extensions/tests/test_motion.py new file mode 100644 index 0000000..23aabbe --- /dev/null +++ b/share/extensions/tests/test_motion.py @@ -0,0 +1,30 @@ +# coding=utf-8 +from motion import Motion +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class MotionBasicTest(ComparisonMixin, TestCase): + effect_class = Motion + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [ + ("--id=c3", "--id=p2"), + ] + + +class MotionSubpathsTest(ComparisonMixin, TestCase): + """Tests the motion extension on paths with (a) transforms and (b) multiple closed subpaths + (b): see https://gitlab.com/inkscape/extensions/-/issues/266""" + + compare_file = "svg/motion_tests.svg" + effect_class = Motion + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [ + ( + "--magnitude=2", + "--angle=45", + "--fillwithstroke=True", + "--id=path23053", + "--id=path28636", + ) + ] diff --git a/share/extensions/tests/test_new_glyph_layer.py b/share/extensions/tests/test_new_glyph_layer.py new file mode 100644 index 0000000..edeb112 --- /dev/null +++ b/share/extensions/tests/test_new_glyph_layer.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from new_glyph_layer import NewGlyphLayer +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestNewGlyphLayerBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = NewGlyphLayer diff --git a/share/extensions/tests/test_next_glyph_layer.py b/share/extensions/tests/test_next_glyph_layer.py new file mode 100644 index 0000000..48126b2 --- /dev/null +++ b/share/extensions/tests/test_next_glyph_layer.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from next_glyph_layer import NextLayer +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestNextLayerBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = NextLayer diff --git a/share/extensions/tests/test_nicechart.py b/share/extensions/tests/test_nicechart.py new file mode 100644 index 0000000..66bb1e0 --- /dev/null +++ b/share/extensions/tests/test_nicechart.py @@ -0,0 +1,23 @@ +# coding=utf-8 +from nicechart import NiceChart +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + +old_params = ("--blur=True", "--headings=True", "--font-color=black", "--what=22,11,67") + + +class TestNiceChartBasic(ComparisonMixin, TestCase): + effect_class = NiceChart + compare_file = "svg/default-plain-SVG.svg" + compare_filters = [CompareNumericFuzzy()] + + @property + def comparisons(self): + filename = self.data_file("io/nicechart_01.csv") + filearg = "--file={}".format(filename) + return ( + (filearg,) + old_params, + (filearg, "--type=pie") + old_params, + (filearg, "--type=pie_abs") + old_params, + (filearg, "--type=stbar") + old_params, + ) diff --git a/share/extensions/tests/test_output_scour.py b/share/extensions/tests/test_output_scour.py new file mode 100644 index 0000000..9c10666 --- /dev/null +++ b/share/extensions/tests/test_output_scour.py @@ -0,0 +1,11 @@ +# coding=utf-8 +import os + +from output_scour import ScourInkscape +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class ScourBasicTests(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + stderr_protect = False + effect_class = ScourInkscape + comparisons = [()] diff --git a/share/extensions/tests/test_param_curves.py b/share/extensions/tests/test_param_curves.py new file mode 100644 index 0000000..8869c66 --- /dev/null +++ b/share/extensions/tests/test_param_curves.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from param_curves import ParamCurves +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class TestParamCurvesBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = ParamCurves + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [ + ("-s=8", "--isoscale=True", "--drawaxis=True"), + ("--id=p1", "--id=r3", "-s=8", "--isoscale=True", "--drawaxis=True"), + ] diff --git a/share/extensions/tests/test_path_envelope.py b/share/extensions/tests/test_path_envelope.py new file mode 100644 index 0000000..4b65c80 --- /dev/null +++ b/share/extensions/tests/test_path_envelope.py @@ -0,0 +1,18 @@ +# coding=utf-8 + +from path_envelope import Envelope +from inkex.tester import ComparisonMixin, TestCase + + +class PathEnvelopeTest(ComparisonMixin, TestCase): + """Test envelope similar to perspective""" + + effect_class = Envelope + comparisons = [("--id=text", "--id=envelope")] + compare_file = "svg/perspective.svg" + + +class PathEnvelopeGroupTest(ComparisonMixin, TestCase): + effect_class = Envelope + comparisons = [("--id=obj", "--id=envelope")] + compare_file = "svg/perspective_groups.svg" diff --git a/share/extensions/tests/test_path_mesh.py b/share/extensions/tests/test_path_mesh.py new file mode 100644 index 0000000..07c8a43 --- /dev/null +++ b/share/extensions/tests/test_path_mesh.py @@ -0,0 +1,31 @@ +# coding=utf-8 + +from path_mesh_m2p import MeshToPath +from path_mesh_p2m import PathToMesh + +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class PathToMeshTest(ComparisonMixin, TestCase): + """Test path to mesh with comparisons""" + + effect_class = PathToMesh + comparisons = [ + ("--id=path1", "--id=path9"), + ] + compare_file = "svg/mesh.svg" + + +class MeshToPathTest(ComparisonMixin, TestCase): + """Test mesh to path with comparisons""" + + compare_filters = [CompareNumericFuzzy()] + effect_class = MeshToPath + comparisons = [ + ("--id=mesh1", "--mode=outline"), + ("--id=mesh1", "--mode=gridlines"), + ("--id=mesh1", "--mode=meshpatches"), + ("--id=mesh1", "--mode=faces"), + ] + compare_file = "svg/mesh.svg" diff --git a/share/extensions/tests/test_path_number_nodes.py b/share/extensions/tests/test_path_number_nodes.py new file mode 100644 index 0000000..4b24182 --- /dev/null +++ b/share/extensions/tests/test_path_number_nodes.py @@ -0,0 +1,14 @@ +# coding=utf-8 +from path_number_nodes import NumberNodes +from inkex.tester import ComparisonMixin, TestCase + + +class NumberNodesTest(ComparisonMixin, TestCase): + effect_class = NumberNodes + comparisons = [("--id=p1", "--id=r3")] + + +class LengthComplexTransformTest(ComparisonMixin, TestCase): + effect_class = NumberNodes + compare_file = "svg/complextransform.test.svg" + comparisons = [["--id=D"]] diff --git a/share/extensions/tests/test_path_to_absolute.py b/share/extensions/tests/test_path_to_absolute.py new file mode 100644 index 0000000..3b4af14 --- /dev/null +++ b/share/extensions/tests/test_path_to_absolute.py @@ -0,0 +1,19 @@ +# coding=utf-8 + +from path_to_absolute import ToAbsolute +from inkex.tester import ComparisonMixin, TestCase + + +class PathToAbsoluteTest(ComparisonMixin, TestCase): + """Test converting objects to absolute""" + + effect_class = ToAbsolute + comparisons = [ + ( + "--id=c1", + "--id=c2", + "--id=c3", + ), + ("--id=r1", "--id=r2", "--id=r3", "--id=slicerect1"), + ("--id=p1", "--id=p2", "--id=s1", "--id=u1"), + ] diff --git a/share/extensions/tests/test_pathalongpath.py b/share/extensions/tests/test_pathalongpath.py new file mode 100644 index 0000000..ab17a21 --- /dev/null +++ b/share/extensions/tests/test_pathalongpath.py @@ -0,0 +1,77 @@ +# coding=utf-8 +from pathalongpath import PathAlongPath +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class TestPathAlongPathBasic(ComparisonMixin, TestCase): + compare_file = "svg/pattern_along_path.svg" + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [ + # Settings: Repeated, Snake, no distance. Tests a path with fillrule=evenodd + ("--copymode=Repeated", "--kind=Snake", "--id=g3427", "--id=path2551"), + # Settings: Repeated, Stretched, Ribbon, Vertical. + # Tests a group pattern with multiple nested transforms + ( + "--copymode=Repeated, stretched", + "--kind=Ribbon", + "--vertical=True", + "--id=g3961", + "--id=path10007", + ), + # Settings: Repeated, Stretched, Ribbon + # Tests a group pattern with multiple nested clones + ( + "--copymode=Repeated, stretched", + "--kind=Ribbon", + "--id=g4054", + "--id=path4056", + ), + # Settings: Single, Stretched, Snake, not duplicated. + # Tests putting a text (converted to a path) on a path and stretching it to fit on the + # skeleton path + ( + "--copymode=Single, stretched", + "--kind=Snake", + "--id=text4418", + "--id=path4412", + ), + # Settings: Single, Stretched, Snake. + # Tests selecting multiple sceleton paths, one consisting of multiple subpaths + ( + "--copymode=Single, stretched", + "--kind=Snake", + "--id=path4585", + "--id=path4608", + "--id=path4610", + "--id=path4612", + ), + # Settings: Repeated, Stretched, Snake, Space between copies=5, Normal offset=5. + # Tests putting a path with multiple subpaths with a gradient on a closed path + ( + "--copymode=Repeated, stretched", + "--kind=Snake", + "--noffset=5", + "--space=5", + "--id=path2408", + "--id=path2405", + ), + ] + effect_class = PathAlongPath + + +class TestPathAlongPathCloneTransforms(ComparisonMixin, TestCase): + """Tests for issue https://gitlab.com/inkscape/extensions/-/issues/241""" + + effect_class = PathAlongPath + compare_file = "svg/pattern_along_path_clone_transform.svg" + comparisons = [ + # a clone with a transform in a group with a transform + ( + "--copymode=Single", + "--duplicate=True", + "--kind=Snake", + "--id=g5848", + "--id=path3336", + ) + ] diff --git a/share/extensions/tests/test_pathscatter.py b/share/extensions/tests/test_pathscatter.py new file mode 100644 index 0000000..9274ad1 --- /dev/null +++ b/share/extensions/tests/test_pathscatter.py @@ -0,0 +1,41 @@ +# coding=utf-8 +from pathscatter import PathScatter +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareWithoutIds + + +class TestPathScatterBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = PathScatter + compare_file = "svg/scatter.svg" + comparisons = [ + # Test simple case + ("--id=g12668", "--id=path8143", "--stretch=False", "--follow=False"), + # Test follow and stretch of a path around a skeleton with multiple closed subpaths + ( + "--id=path3990", + "--id=path3982", + "--stretch=True", + "--follow=True", + "--copymode=copy", + ), + # Test cloning and rotating + ( + "--id=g12668", + "--id=path8143", + "--stretch=True", + "--rotate=True", + "--copymode=clone", + ), + # Test picking from a group pattern + ( + "--id=g12668", + "--id=path8143", + "--stretch=True", + "--copymode=copy", + "--grouppick=True", + "--pickmode=seq", + ), + # Test stretch and spac + ("--id=g12668", "--id=path8143", "--stretch=True", "--space=10"), + ] + compare_filters = [CompareWithoutIds()] diff --git a/share/extensions/tests/test_pdflatex.py b/share/extensions/tests/test_pdflatex.py new file mode 100644 index 0000000..647f94d --- /dev/null +++ b/share/extensions/tests/test_pdflatex.py @@ -0,0 +1,56 @@ +# coding=utf-8 +""" +Test calling pdflatex to convert formule to svg. + +This test uses cached output from the `pdflatex` command because this +test is not a test of pdflatex, but of the extension only. The mocked +output also allows testing in the CI builder without dependancies. + +To re-generate the cached files, run the pytest command: + +NO_MOCK_COMMANDS=1 pytest tests/test_pdflatex.py + +This will use pdflatex, but will also store the output of the call +to `tests/data/cmd/pdflatex/[key].msg.output (and also to `cmd/inkscape/...`) + +The key depends on the comparison arguments, so changing them will invalidate +the file and you must regenerate them. + +Remove the `.output` extension from the above file and commit it to the +repository only AFTER all the tests pass and you are happy with them. + +Clean up any old `.msg` files with invalid or old keys. + +(use EXPORT_COMPARE to generate the output svgs, see inkex.tester docs) +""" +from pdflatex import PdfLatex +from inkex.tester import ComparisonMixin, TestCase + + +class PdfLatexTest(ComparisonMixin, TestCase): + """Test some basic latex formulas""" + + compare_file = "svg/empty.svg" + effect_class = PdfLatex + comparisons = [ + ("--font_size=15",), # pdflatex 6cb1964 + ("--font_size=15", "--standalone=False"), # pdflatex acb7040 + ( + "--font_size=8", + r"""--formule=\(\begin{matrix} + a & b & c \\ + d & e & f \\ + g & h & i + \end{matrix}\)""", + ), # pdflatex fa0bf1f8 + ] + + +class PdfLatexTestmm(ComparisonMixin, TestCase): + compare_file = "svg/empty_mm.svg" + effect_class = PdfLatex + comparisons = [ + ("--font_size=20", r"--formule=\(\frac{1+\sqrt{5}}{2}\)"), # pdflatex 93c25fa3 + # pdflatex b78a3100 + ("--font_size=20", "--standalone=False", r"--formule=\(\frac{1+\sqrt{5}}{2}\)"), + ] diff --git a/share/extensions/tests/test_perfectboundcover.py b/share/extensions/tests/test_perfectboundcover.py new file mode 100644 index 0000000..92b6e51 --- /dev/null +++ b/share/extensions/tests/test_perfectboundcover.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from perfectboundcover import PerfectBoundCover +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class PerfectBoundCoverBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = PerfectBoundCover + comparisons = [()] diff --git a/share/extensions/tests/test_perspective.py b/share/extensions/tests/test_perspective.py new file mode 100644 index 0000000..1040d31 --- /dev/null +++ b/share/extensions/tests/test_perspective.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# coding=utf-8 + +from perspective import Perspective +from inkex.tester import ComparisonMixin, TestCase + + +class PerspectiveBasicTest(ComparisonMixin, TestCase): + effect_class = Perspective + comparisons = [("--id=text", "--id=envelope")] + compare_file = "svg/perspective.svg" + + +class PerspectiveGroupTest(ComparisonMixin, TestCase): + effect_class = Perspective + comparisons = [("--id=obj", "--id=envelope")] + compare_file = "svg/perspective_groups.svg" diff --git a/share/extensions/tests/test_pixelsnap.py b/share/extensions/tests/test_pixelsnap.py new file mode 100644 index 0000000..074abe0 --- /dev/null +++ b/share/extensions/tests/test_pixelsnap.py @@ -0,0 +1,36 @@ +# coding=utf-8 +from pixelsnap import PixelSnap +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class TestPixelSnapEffectBasic(ComparisonMixin, TestCase): + effect_class = PixelSnap + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [("--id=p1", "--id=r3", "--snap_to=bl")] + + +class TestPixelSnapEffectMM(ComparisonMixin, TestCase): + """Test pixel snap in mm based documents""" + + effect_class = PixelSnap + compare_file = "svg/pixelsnap_simple.svg" + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [ + ( + "--id=rect1144", + "--id=path1302", + "--id=path1430", + "--id=path1434", + "--id=path1434", + "--snap_to=tl", + ), + ( + "--id=rect1144", + "--id=path1302", + "--id=path1430", + "--id=path1434", + "--id=path1434", + "--snap_to=bl", + ), + ] diff --git a/share/extensions/tests/test_plotter.py b/share/extensions/tests/test_plotter.py new file mode 100644 index 0000000..3e505c5 --- /dev/null +++ b/share/extensions/tests/test_plotter.py @@ -0,0 +1,27 @@ +"""Test Plotter extension""" +import pytest +import sys +from plotter import Plot +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareReplacement + + +@pytest.mark.skipif(sys.platform == "win32", reason="termios not available on Windows") +class TestPlotter(ComparisonMixin, TestCase): + """Test the plotter extension""" + + stderr_output = True + effect_class = Plot + compare_filter_save = True + compare_filters = [CompareReplacement((";", "\n"))] + old_defaults = ( + "--serialFlowControl=0", + "--force=24", + "--speed=20", + "--orientation=90", + ) + comparisons = [ + ("--serialPort=[test]",) + old_defaults, # HPGL + ("--serialPort=[test]", "--commandLanguage=DMPL") + old_defaults, + ("--serialPort=[test]", "--commandLanguage=KNK") + old_defaults, + ] diff --git a/share/extensions/tests/test_polyhedron_3d.py b/share/extensions/tests/test_polyhedron_3d.py new file mode 100644 index 0000000..7e7b6d8 --- /dev/null +++ b/share/extensions/tests/test_polyhedron_3d.py @@ -0,0 +1,53 @@ +# coding=utf-8 +from polyhedron_3d import Poly3D +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class Poly3DBasicTest(ComparisonMixin, TestCase): + effect_class = Poly3D + comparisons = [ + ( + "--show=fce", + "--obj=cube", + "--r1_ax=x", + "--r1_ang=45", + "--r2_ax=y", + "--r2_ang=45", + "--cw_wound=True", + ), + ( + "--show=fce", + "--obj=cube", + "--r1_ax=y", + "--r1_ang=45", + "--z_sort=cent", + "--cw_wound=True", + ), + ( + "--show=fce", + "--obj=cube", + "--r1_ax=z", + "--r1_ang=45", + "--z_sort=max", + "--cw_wound=True", + ), + ( + "--show=edg", + "--obj=oct", + "--r1_ax=z", + "--r1_ang=45", + "--th=4", + "--cw_wound=True", + ), + ("--show=vtx", "--obj=methane", "--cw_wound=True"), + ("--show=edg", "--obj=methane", "--cw_wound=True"), + ( + "--show=fce", + "--obj=from_file", + "--spec_file=great_stel_dodec.obj", + "--cw_wound=True", + ), + ] + compare_filters = [CompareNumericFuzzy()] + compare_file = "svg/empty.svg" diff --git a/share/extensions/tests/test_prepare_file_save_as.py b/share/extensions/tests/test_prepare_file_save_as.py new file mode 100644 index 0000000..d99e339 --- /dev/null +++ b/share/extensions/tests/test_prepare_file_save_as.py @@ -0,0 +1,10 @@ +# coding=utf-8 +import pytest + +from prepare_file_save_as import PreProcess +from inkex.tester import ComparisonMixin, TestCase + + +class TestPrepareFileSaveBasic(ComparisonMixin, TestCase): + effect_class = PreProcess + comparisons = [()] diff --git a/share/extensions/tests/test_previous_glyph_layer.py b/share/extensions/tests/test_previous_glyph_layer.py new file mode 100644 index 0000000..7ce961e --- /dev/null +++ b/share/extensions/tests/test_previous_glyph_layer.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from previous_glyph_layer import PreviousLayer +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestPreviousLayerBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = PreviousLayer diff --git a/share/extensions/tests/test_print_win32_vector.py b/share/extensions/tests/test_print_win32_vector.py new file mode 100644 index 0000000..2621deb --- /dev/null +++ b/share/extensions/tests/test_print_win32_vector.py @@ -0,0 +1,31 @@ +# coding=utf-8 +import sys + +import pytest + +from print_win32_vector import PrintWin32Vector +from inkex.tester import InkscapeExtensionTestMixin, TestCase + + +@pytest.mark.skipif(sys.platform != "win32", reason="Only runs on windows") +class TestPrintWin32VectorBasic(InkscapeExtensionTestMixin, TestCase): + effect_class = PrintWin32Vector + + +class TestPrintWin32VectorDocumentName(TestCase): + effect_class = PrintWin32Vector + python3_only = True + + def test_empty_doc_name_generated(self): + """Extension generates name for svg file without one""" + self.effect.parse_arguments([self.empty_svg]) + self.effect.load_raw() + lpszDocName = self.effect.doc_name() + self.assertEqual(lpszDocName.value, b"Inkscape New document 1") + + def test_doc_name_read(self): + """Uses document name from svg""" + self.effect.parse_arguments([self.data_file("svg/shapes.svg")]) + self.effect.load_raw() + lpszDocName = self.effect.doc_name() + self.assertEqual(lpszDocName.value, b"Inkscape test.svg") diff --git a/share/extensions/tests/test_printing_marks.py b/share/extensions/tests/test_printing_marks.py new file mode 100644 index 0000000..f8698f2 --- /dev/null +++ b/share/extensions/tests/test_printing_marks.py @@ -0,0 +1,34 @@ +# coding=utf-8 +from printing_marks import PrintingMarks +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import ( + CompareNumericFuzzy, + CompareWithPathSpace, + CompareOrderIndependentStyle, +) + + +class PrintingMarksBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = PrintingMarks + compare_filters = [ + CompareNumericFuzzy(), + CompareWithPathSpace(), + CompareOrderIndependentStyle(), + ] + compare_file = "svg/shapes.svg" + comparisons = { + ( + "--crop_marks", + "True", + "--bleed_marks", + "True", + "--registration_marks", + "True", + "--star_target", + "True", + "--colour_bars", + "True", + "--page_info", + "True", + ) + } diff --git a/share/extensions/tests/test_ps_input.py b/share/extensions/tests/test_ps_input.py new file mode 100644 index 0000000..3666497 --- /dev/null +++ b/share/extensions/tests/test_ps_input.py @@ -0,0 +1,18 @@ +# coding=utf-8 + +import re + +from ps_input import PostscriptInput + +from inkex.tester.filters import CompareSize +from inkex.tester import ComparisonMixin, TestCase + + +class TestPostscriptInput(ComparisonMixin, TestCase): + effect_class = PostscriptInput + compare_filters = [CompareSize()] + compare_file = [ + "io/test.ps", + "io/test.eps", + ] + comparisons = [()] diff --git a/share/extensions/tests/test_render_alphabetsoup.py b/share/extensions/tests/test_render_alphabetsoup.py new file mode 100644 index 0000000..44cfcc3 --- /dev/null +++ b/share/extensions/tests/test_render_alphabetsoup.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from render_alphabetsoup import AlphabetSoup +from inkex.tester import InkscapeExtensionTestMixin, TestCase + + +class AlphabetSoupBasicTest(InkscapeExtensionTestMixin, TestCase): + effect_class = AlphabetSoup diff --git a/share/extensions/tests/test_render_barcode.py b/share/extensions/tests/test_render_barcode.py new file mode 100644 index 0000000..e148691 --- /dev/null +++ b/share/extensions/tests/test_render_barcode.py @@ -0,0 +1,103 @@ +# coding=utf-8 +# +# Copyright (C) 2018 Martin Owens +# +# 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, USA. +# +""" +Written to test the coding of generating barcodes. +""" +from collections import defaultdict + +from barcode import get_barcode +from render_barcode import Barcode + +from inkex.tester import ComparisonMixin, TestCase + + +class BarcodeBasicTest(ComparisonMixin, TestCase): + effect_class = Barcode + comparisons = [ + ("--type", "Ean2", "--text", "55"), + ("--type", "Code93", "--text", "3332222"), + ("--type", "Upce", "--text", "123456"), + ] + + +class GetBarcodeTest(TestCase): + """Test each available barcode type""" + + data = defaultdict(list) + + @classmethod + def setUpClass(cls): + with open(cls.data_file("batches/barcodes.dat"), "r") as fhl: + for line in fhl: + (btype, text, code) = line.strip().split(":", 2) + cls.data[btype].append((text, code)) + + def test_render_barcode_ian5(self): + """Barcode IAN5""" + self.barcode_test("Ean5") + + def test_render_barcode_ian8(self): + """Barcode IAN5""" + self.barcode_test("Ean8") + + def test_render_barcode_ian13(self): + """Barcode IAN5""" + self.barcode_test("Ean13") + + def test_render_barcode_upca(self): + """Barcode IAN5""" + self.barcode_test("Upca") + + def test_render_barcode_upce(self): + """Barcode UPCE""" + self.barcode_test("Upce") + + def test_render_barcode_code128(self): + """Barcode Code128""" + self.barcode_test("Code128") + + def test_render_barcode_code25i(self): + """Barcode Code25i""" + self.barcode_test("Code25i") + + def test_render_barcode_code39(self): + """Barcode Code39""" + self.barcode_test("Code39") + + def test_render_barcode_code39ext(self): + """Barcode Code39Ext""" + self.barcode_test("Code39Ext") + + def test_render_barcode_ean2(self): + """Barcode Ean2""" + self.barcode_test("Ean2") + + def test_render_barcode_royal_mail(self): + """Barcode RM4CC/RM4SCC""" + self.barcode_test("Rm4scc") + + def barcode_test(self, name): + """Base module for all barcode testing""" + + assert self.data[name.lower()], "No test data available for {}".format(name) + for datum in self.data[name.lower()]: + (text, code) = datum + coder = get_barcode(name, text=text) + code2 = coder.encode(text) + assert code == code2 diff --git a/share/extensions/tests/test_render_barcode_datamatrix.py b/share/extensions/tests/test_render_barcode_datamatrix.py new file mode 100644 index 0000000..564f0ee --- /dev/null +++ b/share/extensions/tests/test_render_barcode_datamatrix.py @@ -0,0 +1,14 @@ +# coding=utf-8 +from render_barcode_datamatrix import DataMatrix +from inkex.tester import ComparisonMixin, TestCase + + +class TestDataMatrixBasic(ComparisonMixin, TestCase): + effect_class = DataMatrix + compare_file = "svg/empty.svg" + comparisons = [ + ("--symbol=sq10",), + ("--symbol=sq96", "--text=Sunshine"), + ("--symbol=sq144", "--text=HelloTest"), + ("--symbol=rect8x32", "--text=1234Foo"), + ] diff --git a/share/extensions/tests/test_render_barcode_qrcode.py b/share/extensions/tests/test_render_barcode_qrcode.py new file mode 100644 index 0000000..2375891 --- /dev/null +++ b/share/extensions/tests/test_render_barcode_qrcode.py @@ -0,0 +1,101 @@ +# coding=utf-8 +from render_barcode_qrcode import QrCode, QRCode +from inkex.tester import ComparisonMixin, TestCase + + +class TestQRCodeInkscapeBasic(ComparisonMixin, TestCase): + """Test basic use of QR codes""" + + effect_class = QrCode + compare_file = "svg/empty.svg" + comparisons = [ + ( + "--text=0123456789", + "--typenumber=0", + "--modulesize=10", + "--drawtype=smooth", + "--smoothness=greedy", + ), + ( + "--text=BreadRolls", + "--typenumber=2", + "--encoding=utf8", + "--modulesize=10", + "--drawtype=smooth", + "--smoothness=greedy", + ), + ( + "--text=Blue Front Yard", + "--typenumber=3", + "--correctionlevel=1", + "--modulesize=10", + "--drawtype=smooth", + "--smoothness=greedy", + ), + ( + "--text=Waterfall", + "--typenumber=1", + "--drawtype=pathpreset", + "--pathtype=circle", + "--modulesize=10", + ), + ( + "--text=groupid", + "--groupid=testid", + "--modulesize=10", + "--drawtype=smooth", + "--smoothness=greedy", + ), + ] + + +class TestQRCodeInkscapeSelection(ComparisonMixin, TestCase): + """Test QR code with a selection as input""" + + effect_class = QrCode + compare_file = "svg/shapes.svg" + comparisons = [ + ("--text=test", "--drawtype=selection", "--id=r3", "--modulesize=10") + ] + + +class TestQRCodeInkscapeSymbol(ComparisonMixin, TestCase): + """Test symbols in qr codes""" + + effect_class = QrCode + compare_file = "svg/symbol.svg" + comparisons = [ + ( + "--text=ThingOne", + "--drawtype=symbol", + "--correctionlevel=2", + "--symbolid=AirTransportation_Inv", + "--modulesize=10", + ), + ] + + +class TestLargeQRCodes(ComparisonMixin, TestCase): + """Test large qr codes with up to 2953 bytes of payload. Also tests numeric mode""" + + effect_class = QrCode + compare_file = "svg/empty.svg" + comparisons = [ + # the largest numeric QR code has 7089 characters + ("--text=" + (("12345" * 2000)[0:7089]), "--qrmode=1", "--correctionlevel=1"), + ] + + +class TestQRCodeClasses(ComparisonMixin, TestCase): + """Test alphanumeric barcode""" + + effect_class = QrCode + compare_file = "svg/empty.svg" + comparisons = [ + ( + "--text=THIS IS A TEST OF AN ALPHANUMERIC QRCODE. IT CAN STORE A LARGER NUMBER OF " + "UPPERSPACE CHARACTERS THAN A BYTE-ENCODED QRCODE: 123", + "--qrmode=2", + "--correctionlevel=1", + ), + ] diff --git a/share/extensions/tests/test_render_gear_rack.py b/share/extensions/tests/test_render_gear_rack.py new file mode 100644 index 0000000..14caa25 --- /dev/null +++ b/share/extensions/tests/test_render_gear_rack.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from render_gear_rack import RackGear +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class TestRackGearBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = RackGear + compare_filters = [CompareOrderIndependentStyle()] diff --git a/share/extensions/tests/test_render_gears.py b/share/extensions/tests/test_render_gears.py new file mode 100644 index 0000000..9131293 --- /dev/null +++ b/share/extensions/tests/test_render_gears.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from render_gears import Gears +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class GearsBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = Gears + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [ + ("--centerdiameter=10.0",), + ("--id=p1", "--id=r3", "--centerdiameter=10.0"), + ] diff --git a/share/extensions/tests/test_replace_font.py b/share/extensions/tests/test_replace_font.py new file mode 100644 index 0000000..2150ac9 --- /dev/null +++ b/share/extensions/tests/test_replace_font.py @@ -0,0 +1,26 @@ +# coding=utf-8 +from replace_font import ReplaceFont +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle +from inkex.tester.filters import WindowsTextCompat + + +class TestReplaceFontBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = ReplaceFont + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [ + ( + "--action=find_replace", + "--fr_find=sans-serif", + "--fr_replace=monospace", + ) + ] + + +class TestFontList(ComparisonMixin, TestCase): + effect_class = ReplaceFont + comparisons = [ + ("--action=list_only",), + ] + stderr_output = True + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_restack.py b/share/extensions/tests/test_restack.py new file mode 100644 index 0000000..620a906 --- /dev/null +++ b/share/extensions/tests/test_restack.py @@ -0,0 +1,40 @@ +# coding=utf-8 +from restack import Restack +from inkex.tester import ComparisonMixin, TestCase + + +class RestackBasicTest(ComparisonMixin, TestCase): + effect_class = Restack + old_defaults = ("--direction=tb", "--xanchor=m", "--yanchor=m") + comparisons = [ + ("--tab=positional", "--id=p1", "--id=r3") + old_defaults, + ("--tab=z_order", "--id=p1", "--id=r3") + old_defaults, + ("--tab=z_order", "--id=r3", "--id=p1", "--id=t5", "--id=r2") + old_defaults, + ("--tab=z_order", "--id=r2", "--id=t5", "--id=p1", "--id=r3") + old_defaults, + ( + "--nb_direction=custom", + "--angle=50.0", + "--id=s1", + "--id=p1", + "--id=c3", + "--id=slicerect1", + ) + + old_defaults, + ] + + +class RestackMillimeterGrouped(ComparisonMixin, TestCase): + """Test for https://gitlab.com/inkscape/extensions/-/issues/372""" + + effect_class = Restack + compare_file = "svg/restack_grouped.svg" + comparisons = [ + ( + "--id=g20858", + "--id=g21085", + "--id=g20940", + "--id=g26580", + "--id=g21081", + "--id=g20854", + ), + ] diff --git a/share/extensions/tests/test_rtree.py b/share/extensions/tests/test_rtree.py new file mode 100644 index 0000000..78ed19d --- /dev/null +++ b/share/extensions/tests/test_rtree.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from rtree import TurtleRtree +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class RTreeTurtleBasicTest(ComparisonMixin, TestCase): + effect_class = TurtleRtree + comparisons = [()] + compare_filters = [ + CompareNumericFuzzy(), + ] + comparisons = [("--minimum=4.0",)] diff --git a/share/extensions/tests/test_rubberstretch.py b/share/extensions/tests/test_rubberstretch.py new file mode 100644 index 0000000..3324eda --- /dev/null +++ b/share/extensions/tests/test_rubberstretch.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from rubberstretch import RubberStretch +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestRubberStretchBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = RubberStretch + compare_file = "svg/rubber-stretch-test.svg" + comparisons = [ + ("--id=path3997", "--ratio=50", "--curve=0"), + ("--id=path3997", "--ratio=0", "--curve=50"), + ("--id=path3997", "--ratio=25", "--curve=25"), + ] diff --git a/share/extensions/tests/test_scribus_pdf.py b/share/extensions/tests/test_scribus_pdf.py new file mode 100644 index 0000000..d6b2a21 --- /dev/null +++ b/share/extensions/tests/test_scribus_pdf.py @@ -0,0 +1,15 @@ +# coding=utf-8 +""" +Unit test file for ../scribus_pdf_export.py +""" + +from scribus_export_pdf import Scribus +from inkex.tester import ComparisonMixin, TestCase + + +class ScribusBasicTest(ComparisonMixin, TestCase): + """Test the Scribus PDF file saving functionality""" + + effect_class = Scribus + compare_file = "svg/shapes_cmyk.svg" + comparisons = [("--pdf-version=13", "--bleed=0")] diff --git a/share/extensions/tests/test_setup_typography_canvas.py b/share/extensions/tests/test_setup_typography_canvas.py new file mode 100644 index 0000000..3c28303 --- /dev/null +++ b/share/extensions/tests/test_setup_typography_canvas.py @@ -0,0 +1,11 @@ +# coding=utf-8 +from setup_typography_canvas import SetupTypographyCanvas +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase + + +class TestSetupTypographyCanvasBasic( + ComparisonMixin, InkscapeExtensionTestMixin, TestCase +): + effect_class = SetupTypographyCanvas + compare_file = ["svg/empty.svg", "svg/shapes.svg"] + comparisons = [()] diff --git a/share/extensions/tests/test_spirograph.py b/share/extensions/tests/test_spirograph.py new file mode 100644 index 0000000..de4ac8a --- /dev/null +++ b/share/extensions/tests/test_spirograph.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from spirograph import Spirograph +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class SpirographBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = Spirograph + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [("--primaryr=60.0", "--secondaryr=100.0")] diff --git a/share/extensions/tests/test_straightseg.py b/share/extensions/tests/test_straightseg.py new file mode 100644 index 0000000..5c4165e --- /dev/null +++ b/share/extensions/tests/test_straightseg.py @@ -0,0 +1,11 @@ +# coding=utf-8 +from straightseg import SegmentStraightener +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + + +class SegmentStraightenerBasicTest( + ComparisonMixin, InkscapeExtensionTestMixin, TestCase +): + effect_class = SegmentStraightener + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] diff --git a/share/extensions/tests/test_svgcalendar.py b/share/extensions/tests/test_svgcalendar.py new file mode 100644 index 0000000..e69739c --- /dev/null +++ b/share/extensions/tests/test_svgcalendar.py @@ -0,0 +1,122 @@ +# coding=utf-8 +""" +All tests for the svg calendar extension +""" +import calendar +import datetime + +from svgcalendar import Calendar +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle, CompareNumericFuzzy +from inkex.tester.mock import MockMixin + + +class FrozenDateTime(datetime.datetime): + @classmethod + def today(cls): + return cls(2019, 11, 5) + + +class CalendarArguments(ComparisonMixin, TestCase): + """Test arguments to calendar extensions""" + + effect_class = Calendar + compare_filters = [CompareOrderIndependentStyle(), CompareNumericFuzzy()] + comparisons = [ + ( + "--color-year=#888", + "--color-month=#666", + "--color-day-name=#999", + "--color-day=#000", + "--color-weekend=#777", + "--color-nmd=#BBB", + "--color-weeknr=#808080", + "--encoding=UTF-8", + ) + ] + mocks = [(datetime, "datetime", FrozenDateTime)] + + def test_default_names_list(self): + """Test default names""" + effect = self.assertEffect() + self.assertEqual(effect.options.month_names[0], "January") + self.assertEqual(effect.options.month_names[11], "December") + self.assertEqual(effect.options.day_names[0], "Sun") + self.assertEqual(effect.options.day_names[6], "Sat") + self.assertEqual(effect.options.year, datetime.datetime.today().year) + self.assertEqual(calendar.firstweekday(), 6) + + def test_modifyed_names_list(self): + """Test modified names list""" + effect = self.assertEffect( + args=[ + "--month-names=JAN FEV MAR ABR MAI JUN JUL AGO SET OUT NOV DEZ", + "--day-names=DOM SEG TER QUA QUI SEX SAB", + ] + ) + self.assertEqual(effect.options.month_names[0], "JAN") + self.assertEqual(effect.options.month_names[11], "DEZ") + self.assertEqual(effect.options.day_names[0], "DOM") + self.assertEqual(effect.options.day_names[6], "SAB") + + def test_starting_names_list(self): + """Starting or ending spaces must not affect names""" + effect = self.assertEffect( + args=[ + "--month-names= JAN FEV MAR ABR MAI JUN JUL AGO SET OUT NOV DEZ ", + "--day-names= DOM SEG TER QUA QUI SEX SAB ", + ] + ) + self.assertEqual(effect.options.month_names[0], "JAN") + self.assertEqual(effect.options.month_names[11], "DEZ") + self.assertEqual(effect.options.day_names[0], "DOM") + self.assertEqual(effect.options.day_names[6], "SAB") + + def test_inner_extra_spaces(self): + """Extra spaces must not affect names""" + effect = self.assertEffect( + args=[ + "--month-names=JAN FEV MAR ABR MAI JUN JUL AGO SET OUT NOV DEZ", + "--day-names=DOM SEG TER QUA QUI SEX SAB", + ] + ) + self.assertEqual(effect.options.month_names[0], "JAN") + self.assertEqual(effect.options.month_names[2], "MAR") + self.assertEqual(effect.options.month_names[11], "DEZ") + self.assertEqual(effect.options.day_names[0], "DOM") + self.assertEqual(effect.options.day_names[2], "TER") + self.assertEqual(effect.options.day_names[6], "SAB") + + def test_converted_year_zero(self): + """Year equal to 0 is converted to correct year""" + effect = self.assertEffect(args=["--year=0"]) + self.assertEqual(effect.options.year, datetime.datetime.today().year) + + def test_converted_year_thousand(self): + """Year equal to 2000 configuration""" + effect = self.assertEffect(args=["--year=2000"]) + self.assertEqual(effect.options.year, 2000) + + def test_configuring_week_start_sun(self): + """Week start is set to Sunday""" + self.assertEffect(args=["--start-day=sun"]) + self.assertEqual(calendar.firstweekday(), 6) + + def test_configuring_week_start_mon(self): + """Week start is set to Monday""" + self.assertEffect(args=["--start-day=mon"]) + self.assertEqual(calendar.firstweekday(), 0) + + def test_recognize_a_weekend(self): + """Recognise a weekend""" + effect = self.assertEffect( + args=[ + "--start-day=sun", + "--weekend=sat+sun", + ] + ) + self.assertTrue(effect.is_weekend(0), "Sunday is weekend in this configuration") + self.assertTrue( + effect.is_weekend(6), "Saturday is weekend in this configuration" + ) + self.assertFalse(effect.is_weekend(1), "Monday is NOT weekend") diff --git a/share/extensions/tests/test_svgfont2layers.py b/share/extensions/tests/test_svgfont2layers.py new file mode 100644 index 0000000..65d615e --- /dev/null +++ b/share/extensions/tests/test_svgfont2layers.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from svgfont2layers import SvgFontToLayers +from inkex.tester import ComparisonMixin, TestCase + + +class TestSVGFont2LayersBasic(ComparisonMixin, TestCase): + effect_class = SvgFontToLayers + compare_file = "svg/font.svg" + comparisons = [("--count=3",)] diff --git a/share/extensions/tests/test_synfig_fileformat.py b/share/extensions/tests/test_synfig_fileformat.py new file mode 100644 index 0000000..4cc4d21 --- /dev/null +++ b/share/extensions/tests/test_synfig_fileformat.py @@ -0,0 +1,7 @@ +# coding=utf-8 +from synfig_fileformat import defaultLayerVersion + + +class TestSynFigDefaultLayerVersion(object): + def test_layer_version(self): + assert defaultLayerVersion("outline") == "0.2" diff --git a/share/extensions/tests/test_synfig_output.py b/share/extensions/tests/test_synfig_output.py new file mode 100644 index 0000000..c9d6a47 --- /dev/null +++ b/share/extensions/tests/test_synfig_output.py @@ -0,0 +1,22 @@ +# coding=utf-8 +import re +from synfig_output import SynfigExport +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import Compare, CompareNumericFuzzy + + +class CompareWithoutGuids(Compare): + """ + Remove guid attributes + """ + + @staticmethod + def filter(contents): + contents = re.sub(b'guid="[0-9a-f]{32}"', b"", contents) + return contents + + +class TestSynfigExportBasic(ComparisonMixin, TestCase): + effect_class = SynfigExport # Inkscape call 9f18b1246e864e6f3945f8cd64d6ca14 + compare_filters = [CompareWithoutGuids(), CompareNumericFuzzy()] + comparisons = [()] diff --git a/share/extensions/tests/test_tar_layers.py b/share/extensions/tests/test_tar_layers.py new file mode 100644 index 0000000..60cf84f --- /dev/null +++ b/share/extensions/tests/test_tar_layers.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from tar_layers import TarLayers +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareSize + + +class LayersOutputBasicTest(ComparisonMixin, TestCase): + effect_class = TarLayers + compare_filters = [CompareSize()] diff --git a/share/extensions/tests/test_template.py b/share/extensions/tests/test_template.py new file mode 100644 index 0000000..bc88ab4 --- /dev/null +++ b/share/extensions/tests/test_template.py @@ -0,0 +1,14 @@ +# coding=utf-8 +from template import InxDefinedTemplate +from inkex.tester import ComparisonMixin, TestCase + + +class TemplateTestCase(ComparisonMixin, TestCase): + effect_class = InxDefinedTemplate + compare_file = "svg/empty.svg" + comparisons = [ + ("--size=custom", "--width=100", "--height=100", "--unit=in"), + ("--size=100x50", "--grid=true", "--orientation=horizontal"), + ("--size=100x50", "--grid=true", "--orientation=vertical"), + ("--size=5mmx15mm", "--background=black", "--noborder=true"), + ] diff --git a/share/extensions/tests/test_template_dvd_cover.py b/share/extensions/tests/test_template_dvd_cover.py new file mode 100644 index 0000000..ffcd18c --- /dev/null +++ b/share/extensions/tests/test_template_dvd_cover.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from template_dvd_cover import DvdCover +from inkex.tester import ComparisonMixin, TestCase + + +class TestDvdCoverBasic(ComparisonMixin, TestCase): + effect_class = DvdCover + compare_file = "svg/empty.svg" + comparisons = [("-s", "10", "-b", "10")] diff --git a/share/extensions/tests/test_template_seamless_pattern.py b/share/extensions/tests/test_template_seamless_pattern.py new file mode 100644 index 0000000..343c027 --- /dev/null +++ b/share/extensions/tests/test_template_seamless_pattern.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from template_seamless_pattern import SeamlessPattern +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy + + +class SeamlessPatternBasicTest(ComparisonMixin, TestCase): + effect_class = SeamlessPattern + compare_filters = [CompareNumericFuzzy()] + comparisons = [("--width=100", "--height=100")] diff --git a/share/extensions/tests/test_text_braille.py b/share/extensions/tests/test_text_braille.py new file mode 100644 index 0000000..e18b9b0 --- /dev/null +++ b/share/extensions/tests/test_text_braille.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from text_braille import Braille +from inkex.tester import ComparisonMixin, TestCase + + +class TestBrailleBasic(ComparisonMixin, TestCase): + effect_class = Braille + python3_only = True + comparisons = [()] diff --git a/share/extensions/tests/test_text_extract.py b/share/extensions/tests/test_text_extract.py new file mode 100644 index 0000000..bdf2a6e --- /dev/null +++ b/share/extensions/tests/test_text_extract.py @@ -0,0 +1,16 @@ +# coding=utf-8 +from inkex.tester import ComparisonMixin, TestCase +from text_extract import Extract +from inkex.tester.filters import WindowsTextCompat + + +class TestExtractBasic(ComparisonMixin, TestCase): + effect_class = Extract + stderr_output = True + comparisons = [ + ("--direction=tb", "--xanchor=center_x", "--yanchor=center_y"), + ("--direction=bt", "--xanchor=center_x", "--yanchor=center_y"), + ("--direction=lr", "--xanchor=center_x", "--yanchor=center_y"), + ("--direction=rl", "--xanchor=center_x", "--yanchor=center_y"), + ] + compare_filters = [WindowsTextCompat()] diff --git a/share/extensions/tests/test_text_flipcase.py b/share/extensions/tests/test_text_flipcase.py new file mode 100644 index 0000000..214fc14 --- /dev/null +++ b/share/extensions/tests/test_text_flipcase.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from text_flipcase import FlipCase +from inkex.tester import ComparisonMixin, TestCase + + +class TestFlipCaseBasic(ComparisonMixin, TestCase): + effect_class = FlipCase + comparisons = [()] diff --git a/share/extensions/tests/test_text_lowercase.py b/share/extensions/tests/test_text_lowercase.py new file mode 100644 index 0000000..b6be323 --- /dev/null +++ b/share/extensions/tests/test_text_lowercase.py @@ -0,0 +1,57 @@ +# coding=utf-8 +"""Test the lowercase effect""" +import string + +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.word import word_generator +from text_lowercase import Lowercase + + +class LowerCase(ComparisonMixin, TestCase): + effect_class = Lowercase + comparisons = [()] + + def test_uppercase(self): + var = word_generator(15) + var_new = var.upper() + self.assertEqual(self.effect.process_chardata(var_new), var.lower()) + + def test_lowercase(self): + var = word_generator(15) + var_new = var.lower() + + self.assertEqual(self.effect.process_chardata(var_new), var.lower()) + + def test_titlecase(self): + var = word_generator(5) + var1 = word_generator(8) + var2 = word_generator(7) + word = var + " " + var1 + " " + var2 + + word_new = word.title() + + self.assertEqual(self.effect.process_chardata(word_new), word_new.lower()) + + def test_sentencecase(self): + var = word_generator(5) + var1 = word_generator(8) + var2 = word_generator(7) + word = var + " " + var1 + " " + var2 + + word_new = word[0].upper() + word[1:] + + self.assertEqual(self.effect.process_chardata(word_new), word_new.lower()) + + def test_numbers_before(self): + var = word_generator(15) + var_upper = var.upper() + var_new = var_upper.zfill(20) + + self.assertEqual(self.effect.process_chardata(var_new), var_new.lower()) + + def test_punctuation_before(self): + var = word_generator(15) + var_upper = var.upper() + var_new = string.punctuation + var_upper + + self.assertEqual(self.effect.process_chardata(var_new), var_new.lower()) diff --git a/share/extensions/tests/test_text_merge.py b/share/extensions/tests/test_text_merge.py new file mode 100644 index 0000000..eba832d --- /dev/null +++ b/share/extensions/tests/test_text_merge.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +from text_merge import Merge +from inkex.tester import ComparisonMixin, TestCase + + +class TestMergeBasic(ComparisonMixin, TestCase): + effect_class = Merge + comparisons = [()] diff --git a/share/extensions/tests/test_text_randomcase.py b/share/extensions/tests/test_text_randomcase.py new file mode 100644 index 0000000..d1d2a34 --- /dev/null +++ b/share/extensions/tests/test_text_randomcase.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from inkex.tester import ComparisonMixin, TestCase +from text_randomcase import RandomCase + + +class TestRandomCaseBasic(ComparisonMixin, TestCase): + effect_class = RandomCase + comparisons = [()] diff --git a/share/extensions/tests/test_text_sentencecase.py b/share/extensions/tests/test_text_sentencecase.py new file mode 100644 index 0000000..11c43ea --- /dev/null +++ b/share/extensions/tests/test_text_sentencecase.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from inkex.tester import ComparisonMixin, TestCase +from text_sentencecase import SentenceCase + + +class TestSentenceCaseBasic(ComparisonMixin, TestCase): + effect_class = SentenceCase + comparisons = [()] diff --git a/share/extensions/tests/test_text_split.py b/share/extensions/tests/test_text_split.py new file mode 100644 index 0000000..944387a --- /dev/null +++ b/share/extensions/tests/test_text_split.py @@ -0,0 +1,36 @@ +# coding=utf-8 +from inkex.tester.filters import CompareWithoutIds +from text_split import TextSplit +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareWithoutIds + + +class TestSplitBasic(ComparisonMixin, TestCase): + """Test split effect""" + + effect_class = TextSplit + compare_filters = [CompareWithoutIds()] + compare_file = "svg/text_types.svg" + all_shapes = ( + "--id=regular", + "--id=regular-transform", + "--id=inline-size", + "--id=kerning", + "--id=flowroot", + "--id=flowroot-abs-lineheight", + "--id=flowroot-no-lineheight", + "--id=manual-kerns", + "--id=rtl", + "--id=shape-inside", + ) + comparisons = [ + all_shapes + ("--splittype=line", "--preserve=True"), # ad3188 + all_shapes + ("--splittype=line", "--preserve=False"), # c242ad + all_shapes + ("--splittype=word", "--preserve=True"), # 547875 + all_shapes + ("--splittype=word", "--preserve=False"), # d8b155 + all_shapes + + ("--splittype=word", "--preserve=False", "--separation=0.0"), # 897ab8 + all_shapes + ("--splittype=letter", "--preserve=True"), # 74947d + all_shapes + ("--splittype=letter", "--preserve=False"), # dd77d3 + ] + print("test") diff --git a/share/extensions/tests/test_text_titlecase.py b/share/extensions/tests/test_text_titlecase.py new file mode 100644 index 0000000..85fb655 --- /dev/null +++ b/share/extensions/tests/test_text_titlecase.py @@ -0,0 +1,70 @@ +# coding=utf-8 +""" +Test titlecase extension +""" + +import string + +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.word import sentencecase, word_generator +from text_titlecase import TitleCase + + +class TitleCaseTest(ComparisonMixin, TestCase): + effect_class = TitleCase + comparisons = [()] + + def test_lowercase(self): + var = word_generator(6) + var1 = word_generator(9) + var2 = word_generator(10) + words = var.lower() + " " + var1.lower() + " " + var2.lower() + titlecase = self.effect.process_chardata(words) + self.assertEqual(self.effect.process_chardata(words), titlecase) + + def test_uppercase(self): + var = word_generator(6) + var1 = word_generator(9) + var2 = word_generator(10) + words = var.upper() + " " + var1.upper() + " " + var2.upper() + titlecase = self.effect.process_chardata(words) + self.assertEqual(self.effect.process_chardata(words), titlecase) + + def test_sentencecase(self): + var = word_generator(5) + var1 = word_generator(8) + var2 = word_generator(7) + words = var + " " + var1 + " " + var2 + word_new = sentencecase(words) + titlecase = self.effect.process_chardata(word_new) + self.assertEqual(self.effect.process_chardata(word_new), titlecase) + + def test_numbers_before(self): + words = word_generator(15) + word_new = words.zfill(20) + titlecase = self.effect.process_chardata(word_new) + self.assertEqual(self.effect.process_chardata(word_new), titlecase) + + def test_punctuation_before(self): + words = word_generator(15) + word_new = string.punctuation + words + titlecase = self.effect.process_chardata(word_new) + self.assertEqual(self.effect.process_chardata(word_new), titlecase) + + def test_check_strings(self): + titlecase_strings = [ + ("i love inkscape", "I Love Inkscape"), + ("i LOVE inkscape", "I Love Inkscape"), + ("I love Inkscape", "I Love Inkscape"), + ("I LOVE INKSCAPE", "I Love Inkscape"), + ("ThIs Is VeRy AwEsOmE", "This Is Very Awesome"), + ("!$this is Very awesome.", "!$This Is Very Awesome."), + ("this *is @very ^awesome.", "This *Is @Very ^Awesome."), + ("there is a space.", "There Is A Space."), + ("9these 5are 7numbers", "9These 5Are 7Numbers"), + ("thisworddidnotend", "Thisworddidnotend"), + ("This Should Not Change", "This Should Not Change"), + ] + + for item in titlecase_strings: + self.assertEqual(self.effect.process_chardata(item[0]), item[1]) diff --git a/share/extensions/tests/test_text_uppercase.py b/share/extensions/tests/test_text_uppercase.py new file mode 100644 index 0000000..3b38317 --- /dev/null +++ b/share/extensions/tests/test_text_uppercase.py @@ -0,0 +1,45 @@ +# coding=utf-8 +"""Test string uppercase extension""" +import string + +from text_uppercase import Uppercase +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.word import word_generator + + +class UpperCase(ComparisonMixin, TestCase): + effect_class = Uppercase + comparisons = [()] + + def test_lowercase(self): + var = word_generator(15) + var_new = var.lower() + self.assertEqual(self.effect.process_chardata(var_new), var.upper()) + + def test_titlecase(self): + var = word_generator(5) + var1 = word_generator(8) + var2 = word_generator(7) + word = var + " " + var1 + " " + var2 + + word_new = word.title() + self.assertEqual(self.effect.process_chardata(word_new), word_new.upper()) + + def test_sentencecase(self): + var = word_generator(5) + var1 = word_generator(8) + var2 = word_generator(7) + word = var + " " + var1 + " " + var2 + + word_new = word[0].upper() + word[1:] + self.assertEqual(self.effect.process_chardata(word_new), word_new.upper()) + + def test_numbers_before(self): + var = word_generator(15) + var_new = var.zfill(20) + self.assertEqual(self.effect.process_chardata(var_new), var_new.upper()) + + def test_punctuation_before(self): + var = word_generator(15) + var_new = string.punctuation + var + self.assertEqual(self.effect.process_chardata(var_new), var_new.upper()) diff --git a/share/extensions/tests/test_triangle.py b/share/extensions/tests/test_triangle.py new file mode 100644 index 0000000..b8138c3 --- /dev/null +++ b/share/extensions/tests/test_triangle.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +from triangle import Triangle +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareOrderIndependentStyle + + +class TriangleBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = Triangle + compare_filters = [CompareNumericFuzzy(), CompareOrderIndependentStyle()] diff --git a/share/extensions/tests/test_ungroup_deep.py b/share/extensions/tests/test_ungroup_deep.py new file mode 100644 index 0000000..7da73ca --- /dev/null +++ b/share/extensions/tests/test_ungroup_deep.py @@ -0,0 +1,32 @@ +# coding=utf-8 +from ungroup_deep import UngroupDeep +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class TestUngroupBasic(ComparisonMixin, TestCase): + effect_class = UngroupDeep + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [(), ("--id=layer2",)] + + +class TestUngroupComplex(ComparisonMixin, TestCase): + effect_class = UngroupDeep + compare_filters = [CompareOrderIndependentStyle()] + compare_file = "svg/deep-ungroup-complex.svg" + comparisons = [ + # first one: Paths with clip-path:none (https://gitlab.com/inkscape/extensions/-/issues/184#note_490847336) + # second one: Paths with nested transforms (https://gitlab.com/inkscape/extensions/-/issues/340) + # third one: Transformed group with transformed clip-path, https://gitlab.com/inkscape/extensions/-/issues/184 + ("--id=g1935", "--id=g6577", "--id=g115") + ] + + +class TestUngroupComments(ComparisonMixin, TestCase): + effect_class = UngroupDeep + compare_filters = [CompareOrderIndependentStyle()] + compare_file = "svg/ellipse_group_comment.svg" + comparisons = [ + # Groups with comment child elements (https://gitlab.com/inkscape/extensions/-/issues/405) + ("--id=g13",) + ] diff --git a/share/extensions/tests/test_voronoi.py b/share/extensions/tests/test_voronoi.py new file mode 100644 index 0000000..6f15fca --- /dev/null +++ b/share/extensions/tests/test_voronoi.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from voronoi import Site + + +class TestVoronoiSiteBasic(object): + def test_site_basic(self): + new_site = Site(1, 2) + assert new_site.x == 1 + assert new_site.y == 2 diff --git a/share/extensions/tests/test_voronoi2svg.py b/share/extensions/tests/test_voronoi2svg.py new file mode 100644 index 0000000..5a26adc --- /dev/null +++ b/share/extensions/tests/test_voronoi2svg.py @@ -0,0 +1,53 @@ +# coding=utf-8 +from voronoi2svg import Voronoi +from inkex.tester import ComparisonMixin, TestCase +from inkex.tester.filters import CompareOrderIndependentStyle + + +class TestVoronoi2svgBasic(ComparisonMixin, TestCase): + effect_class = Voronoi + compare_filters = [CompareOrderIndependentStyle()] + comparisons = [ + ( + "--id=c1", + "--id=c2", + "--id=c3", + "--id=p1", + "--id=p2", + "--id=s1", + "--id=u1", + "--diagram-type=Both", + "--clip-box=Automatic from seeds", + "--show-clip-box=True", + ), + ( + "--id=c1", + "--id=c2", + "--id=c3", + "--id=p1", + "--id=p2", + "--id=s1", + "--diagram-type=Voronoi", + "--clip-box=Page", + ), + ( + "--id=r1", + "--id=r3", + "--id=c1", + "--id=c3", + "--id=s1", + "--diagram-type=Both", + "--delaunay-fill-options=delaunay-fill", + ), + ] + + +class TestVoronoi2svgmm(ComparisonMixin, TestCase): + """Test voronoi for mm based documents (https://gitlab.com/inkscape/extensions/-/issues/403)""" + + effect_class = Voronoi + compare_file = "svg/interp_shapes.svg" + comparisons = [ + tuple(f"--id=path{i}" for i in range(1, 11)) + + ("--diagram-type=Voronoi", "--clip-box=Page") + ] diff --git a/share/extensions/tests/test_web_interactive_mockup.py b/share/extensions/tests/test_web_interactive_mockup.py new file mode 100644 index 0000000..93d7085 --- /dev/null +++ b/share/extensions/tests/test_web_interactive_mockup.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from web_interactive_mockup import InteractiveMockup +from inkex.tester import ComparisonMixin, TestCase + + +class TestInkWebInteractiveMockupBasic(ComparisonMixin, TestCase): + effect_class = InteractiveMockup + comparisons = [("--id=p1", "--id=r3")] diff --git a/share/extensions/tests/test_web_set_att.py b/share/extensions/tests/test_web_set_att.py new file mode 100644 index 0000000..cb0b58f --- /dev/null +++ b/share/extensions/tests/test_web_set_att.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from web_set_att import SetAttribute +from inkex.tester import ComparisonMixin, TestCase + + +class SetAttributeBasic(ComparisonMixin, TestCase): + effect_class = SetAttribute + comparisons = [("--id=p1", "--id=r3", "--att=fill", "--val=red")] diff --git a/share/extensions/tests/test_web_transmit_att.py b/share/extensions/tests/test_web_transmit_att.py new file mode 100644 index 0000000..9c7bb11 --- /dev/null +++ b/share/extensions/tests/test_web_transmit_att.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from web_transmit_att import TransmitAttribute +from inkex.tester import ComparisonMixin, TestCase + + +class TestInkWebTransmitAttBasic(ComparisonMixin, TestCase): + effect_class = TransmitAttribute + comparisons = [("--id=p1", "--id=r3")] diff --git a/share/extensions/tests/test_webslicer_create_group.py b/share/extensions/tests/test_webslicer_create_group.py new file mode 100644 index 0000000..e5e5e60 --- /dev/null +++ b/share/extensions/tests/test_webslicer_create_group.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +from webslicer_create_group import CreateGroup +from inkex.tester import ComparisonMixin, TestCase + + +class TestWebSlicerCreateGroupBasic(ComparisonMixin, TestCase): + effect_class = CreateGroup + comparisons = [("--id", "slicerect1")] diff --git a/share/extensions/tests/test_webslicer_create_rect.py b/share/extensions/tests/test_webslicer_create_rect.py new file mode 100644 index 0000000..807c0fa --- /dev/null +++ b/share/extensions/tests/test_webslicer_create_rect.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +from webslicer_create_rect import CreateRect +from inkex.tester import ComparisonMixin, TestCase + + +class TestWebSlicerCreateRectBasic(ComparisonMixin, TestCase): + effect_class = CreateRect diff --git a/share/extensions/tests/test_webslicer_export.py b/share/extensions/tests/test_webslicer_export.py new file mode 100644 index 0000000..62a2e86 --- /dev/null +++ b/share/extensions/tests/test_webslicer_export.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +from webslicer_export import Export +from inkex.tester import ComparisonMixin, TestCase + + +class TestWebSlicerExportBasic(ComparisonMixin, TestCase): + stderr_protect = False # Cover lack of ImageMagic in CI builder + effect_class = Export + + @property + def comparisons(self): + return [("--dir", self.tempdir)] diff --git a/share/extensions/tests/test_whirl.py b/share/extensions/tests/test_whirl.py new file mode 100644 index 0000000..eb7a5c2 --- /dev/null +++ b/share/extensions/tests/test_whirl.py @@ -0,0 +1,11 @@ +# coding=utf-8 +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareWithPathSpace + +from whirl import Whirl + + +class WhirlBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = Whirl + compare_filters = [CompareNumericFuzzy(), CompareWithPathSpace()] + comparisons = [("--id=p1", "--id=r3", "--whirl=1.0")] diff --git a/share/extensions/tests/test_wireframe_sphere.py b/share/extensions/tests/test_wireframe_sphere.py new file mode 100644 index 0000000..b35dd05 --- /dev/null +++ b/share/extensions/tests/test_wireframe_sphere.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from wireframe_sphere import WireframeSphere +from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase +from inkex.tester.filters import CompareNumericFuzzy, CompareOrderIndependentStyle + + +class TestWireframeSphereBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase): + effect_class = WireframeSphere + compare_filters = [CompareNumericFuzzy(), CompareOrderIndependentStyle()] diff --git a/share/extensions/text_braille.inx b/share/extensions/text_braille.inx new file mode 100644 index 0000000..d302bde --- /dev/null +++ b/share/extensions/text_braille.inx @@ -0,0 +1,14 @@ + + + Convert to Braille + org.inkscape.text.braille + + all + + + + + + diff --git a/share/extensions/text_braille.py b/share/extensions/text_braille.py new file mode 100755 index 0000000..1ce2bdd --- /dev/null +++ b/share/extensions/text_braille.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +"""Convert the text to braille text""" + +import inkex + +# https://en.wikipedia.org/wiki/Braille_ASCII#Braille_ASCII_values +U2800_MAP = " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=" + + +class Braille(inkex.TextExtension): + """Convert to ASCII Braille""" + + @staticmethod + def map_char(char): + """Map a single letter to braille""" + assert isinstance(char, str) + try: + mapint = U2800_MAP.index(char.upper()) + except ValueError: + return char + return chr(mapint + 0x2800) + + +if __name__ == "__main__": + Braille().run() diff --git a/share/extensions/text_extract.inx b/share/extensions/text_extract.inx new file mode 100644 index 0000000..05dddeb --- /dev/null +++ b/share/extensions/text_extract.inx @@ -0,0 +1,30 @@ + + + Extract + org.inkscape.text.extract + + + + + + + + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/text_extract.py b/share/extensions/text_extract.py new file mode 100755 index 0000000..212fde9 --- /dev/null +++ b/share/extensions/text_extract.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Nicolas Dufour (jazzynico) +# Direction code from the Restack extension, by Rob Antonishen +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +""" +Extract text and print it to the error console. +""" + +from lxml.etree import tostring + +import inkex +from inkex import TextElement, FlowRoot +from inkex.utils import KeyDict + +# Old settings, supported because users click 'ok' without looking. +XAN = KeyDict({"l": "left", "r": "right", "m": "center_x"}) +YAN = KeyDict({"t": "top", "b": "bottom", "m": "center_y"}) + + +class Extract(inkex.EffectExtension): + """Extract text and print out""" + + select_all = (TextElement, FlowRoot) + + def add_arguments(self, pars): + pars.add_argument( + "-d", "--direction", default="lr", help="direction to extract text" + ) + pars.add_argument( + "-x", "--xanchor", default="left", help="horiz point to compare" + ) + pars.add_argument( + "-y", "--yanchor", default="top", help="vertical point to compare" + ) + + def effect(self): + # move them to the top of the object stack in this order. + for node in sorted( + self.svg.selection.get(TextElement, FlowRoot), key=self._sort + ): + self.recurse(node) + + def _sort(self, node): + return node.bounding_box().get_anchor( + self.options.xanchor, self.options.yanchor, self.options.direction + ) + + def recurse(self, node): + """Go through each node and recusively self call for all children""" + if node.text is not None or node.tail is not None: + for child in node: + if child.get("sodipodi:role"): + child.tail = "\n" + inkex.errormsg(tostring(node, encoding="unicode", method="text").strip()) + else: + for child in node: + self.recurse(child) + + +if __name__ == "__main__": + Extract().run() diff --git a/share/extensions/text_flipcase.inx b/share/extensions/text_flipcase.inx new file mode 100644 index 0000000..40e59db --- /dev/null +++ b/share/extensions/text_flipcase.inx @@ -0,0 +1,16 @@ + + + fLIP cASE + org.inkscape.text.flip_case + + all + + + + + + + + diff --git a/share/extensions/text_flipcase.py b/share/extensions/text_flipcase.py new file mode 100755 index 0000000..c1cc4e6 --- /dev/null +++ b/share/extensions/text_flipcase.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +"""Flip upper to lower and lower to upper cases""" + +import inkex + + +class FlipCase(inkex.TextExtension): + """Change the case, cHANGE THE CASE""" + + @staticmethod + def map_char(char): + return char.upper() if char.islower() else char.lower() + + +if __name__ == "__main__": + FlipCase().run() diff --git a/share/extensions/text_lowercase.inx b/share/extensions/text_lowercase.inx new file mode 100644 index 0000000..68d27d9 --- /dev/null +++ b/share/extensions/text_lowercase.inx @@ -0,0 +1,16 @@ + + + lowercase + org.inkscape.text.lowercase + + all + + + + + + + + diff --git a/share/extensions/text_lowercase.py b/share/extensions/text_lowercase.py new file mode 100755 index 0000000..866c50f --- /dev/null +++ b/share/extensions/text_lowercase.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Make text lower case""" + +import inkex + + +class Lowercase(inkex.TextExtension): + """Convert to lowercase""" + + def process_chardata(self, text): + return text.lower() + + +if __name__ == "__main__": + Lowercase().run() diff --git a/share/extensions/text_merge.inx b/share/extensions/text_merge.inx new file mode 100644 index 0000000..567d30f --- /dev/null +++ b/share/extensions/text_merge.inx @@ -0,0 +1,32 @@ + + + Merge + org.inkscape.text.merge + + + + + + + + + + + + + + + + + false + true + + all + + + + + + diff --git a/share/extensions/text_merge.py b/share/extensions/text_merge.py new file mode 100755 index 0000000..6085647 --- /dev/null +++ b/share/extensions/text_merge.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2013 Nicolas Dufour (jazzynico) +# Direction code from the Restack extension, by Rob Antonishen +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +""" +Merge text blocks together. +""" + +import inkex +from inkex.utils import KeyDict +from inkex import Rectangle, FlowRoot, FlowPara, FlowRegion, TextElement, Tspan + +# Old settings, supported because users click 'ok' without looking. +XAN = KeyDict({"l": "left", "r": "right", "m": "center_x"}) +YAN = KeyDict({"t": "top", "b": "bottom", "m": "center_y"}) + + +class Merge(inkex.EffectExtension): + """Merge text blocks together""" + + def add_arguments(self, pars): + pars.add_argument( + "-d", "--direction", default="lr", help="direction to merge text" + ) + pars.add_argument( + "-x", "--xanchor", default="left", help="horiz point to compare" + ) + pars.add_argument( + "-y", "--yanchor", default="top", help="vertical point to compare" + ) + pars.add_argument("-k", "--keepstyle", type=inkex.Boolean, help="keep format") + pars.add_argument( + "-t", + "--flowtext", + type=inkex.Boolean, + help="use a flow text structure instead of a normal text element", + ) + + def effect(self): + if not self.svg.selection: + for node in self.svg.xpath("//svg:text | //svg:flowRoot"): + self.svg.selection[node.get("id")] = node + + if not self.svg.selection: + return + + parentnode = self.svg.get_current_layer() + + if self.options.flowtext: + text_element = FlowRoot + text_span = FlowPara + else: + text_element = TextElement + text_span = Tspan + + text_root = parentnode.add(text_element()) + text_root.set("xml:space", "preserve") + text_root.style = { + "font-size": "20px", + "font-style": "normal", + "font-weight": "normal", + "line-height": "125%", + "letter-spacing": "0px", + "word-spacing": "0px", + "fill": "#000000", + "fill-opacity": 1, + "stroke": "none", + } + + for node in sorted(self.svg.selection.values(), key=self._sort): + self.recurse(text_span, node, text_root) + + if self.options.flowtext: + region = text_root.add(FlowRegion()) + region.set("xml:space", "preserve") + rect = region.add(Rectangle()) + rect.set("xml:space", "preserve") + rect.set("height", 200) + rect.set("width", 200) + + def _sort(self, node): + return node.bounding_box().get_anchor( + self.options.xanchor, self.options.yanchor, self.options.direction + ) + + def recurse(self, text_span, node, span): + """Recursively go through each node self calling on child nodes""" + if not isinstance(node, FlowRegion): + + newspan = span.add(text_span()) + newspan.set("xml:space", "preserve") + + newspan.set("sodipodi:role", node.get("sodipodi:role")) + if isinstance(node, (TextElement, FlowPara)): + newspan.set("sodipodi:role", "line") + + if self.options.keepstyle: + newspan.style = node.style + + if node.text is not None: + newspan.text = node.text + for child in node: + self.recurse(text_span, child, newspan) + if node.tail and not isinstance(node, TextElement): + newspan.tail = node.tail + + +if __name__ == "__main__": + Merge().run() diff --git a/share/extensions/text_randomcase.inx b/share/extensions/text_randomcase.inx new file mode 100644 index 0000000..d0c6a20 --- /dev/null +++ b/share/extensions/text_randomcase.inx @@ -0,0 +1,16 @@ + + + rANdOm CasE + org.inkscape.text.random_case + + all + + + + + + + + diff --git a/share/extensions/text_randomcase.py b/share/extensions/text_randomcase.py new file mode 100755 index 0000000..5a917ec --- /dev/null +++ b/share/extensions/text_randomcase.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +"""Randomise the case of the letters.""" + +import random +import inkex + + +class RandomCase(inkex.TextExtension): + """Randomise the case of the text (with bias)""" + + previous_case = 1 + + def map_char(self, char): + # bias the randomness towards inversion of the previous case: + # We use this weird way to get from a random set because + # python2 and python3 have different ways of seeding + if self.previous_case > 0: + case = [-2, -1, 1][int(random.random() * 3)] + else: + case = [-1, 1, 2][int(random.random() * 3)] + + if char.isalpha(): + self.previous_case = case + if case > 0: + return char.upper() + elif case < 0: + return char.lower() + return char + + +if __name__ == "__main__": + RandomCase().run() diff --git a/share/extensions/text_sentencecase.inx b/share/extensions/text_sentencecase.inx new file mode 100644 index 0000000..8d26ab1 --- /dev/null +++ b/share/extensions/text_sentencecase.inx @@ -0,0 +1,16 @@ + + + Sentence case + org.inkscape.text.sentence_case + + all + + + + + + + + diff --git a/share/extensions/text_sentencecase.py b/share/extensions/text_sentencecase.py new file mode 100755 index 0000000..b8bb136 --- /dev/null +++ b/share/extensions/text_sentencecase.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +"""Convert to sentence case""" + +import inkex + + +class SentenceCase(inkex.TextExtension): + """Convert text to sentence case""" + + sentence_start = True + was_punctuation = False + + def map_char(self, char): + """Turn the char into a sentence using class state""" + if char in ".!?": + self.was_punctuation = True + elif ((char.isspace() or self.newline) and self.was_punctuation) or self.newpar: + self.sentence_start = True + self.was_punctuation = False + elif char in '")': + pass + else: + self.was_punctuation = False + + if not char.isspace(): + self.newline = False + self.newpar = False + + if self.sentence_start and char.isalpha(): + self.sentence_start = False + return char.upper() + elif not self.sentence_start and char.isalpha(): + return char.lower() + return char + + +if __name__ == "__main__": + SentenceCase().run() diff --git a/share/extensions/text_split.inx b/share/extensions/text_split.inx new file mode 100644 index 0000000..e6dc942 --- /dev/null +++ b/share/extensions/text_split.inx @@ -0,0 +1,35 @@ + + + Split text + org.inkscape.text_split + + + + + + + + 1.0 + true + + + + + + + + + + text + + + + + + diff --git a/share/extensions/text_split.py b/share/extensions/text_split.py new file mode 100755 index 0000000..dee9c88 --- /dev/null +++ b/share/extensions/text_split.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 Karlisson Bezerra, contato@nerdson.com +# 2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# 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. +# +"""Splits a text element into lines, words, chars. +Supports all text elements that Inkscape can create, such as normal text, shape-inside (SVG2), +flowroot (SVG1.2), inline-size, manual kerns, and nested tspans (with possibly different kerns) + +The code is structured as followed. For each selected text element: + - preprocess_text_element duplicates the element, converts flowroots to plain text elements, + and simplifies manual kerning if requested (only for split_words and split_chars, for all, + possibly nested, children) using simplify_nested_tspans. + - if split lines: split_lines copies all top-level tspans from the previous step into their own + text element, which is otherwise a duplicate of the original text element (thus preserving + style and transforms), see append_splitted_element + - if split words or chars: split_words_or_chars: the text is recursively processed. For each tspan, + the content and tail is split (words: at spaces, chars: after each character) into their own + tspan, again using append_splitted_element. The method keeps track of the horizontal and vertical + coordinate, incrementing it with the number of characters and a multiple of font size. +""" + +import re as regex +from typing import Union, Callable + +import inkex +from inkex import TextElement, FlowRoot, FlowPara, Tspan, Rectangle, ShapeElement +from inkex.units import parse_unit +from inkex.localization import inkex_gettext as _ + +TextLike = Union[FlowRoot, TextElement] + + +class TextSplit(inkex.EffectExtension): + """Split text up.""" + + def __init__(self): + """Initialize State machine""" + super().__init__() + self.mode: Callable + self.separation: float = 1 + self.fs_multiplier: float = 0.25 + self.current_x: float = 0 + self.current_y: float = 0 + self.process_kerns: bool = True + self.current_root: TextLike + self.current_fontsize: float = 0 + + def add_arguments(self, pars): + pars.add_argument("--tab", help="The selected UI tab when OK was pressed") + pars.add_argument( + "-t", + "--splittype", + default="line", + choices=["letter", "word", "line"], + help="type of split", + ) + pars.add_argument( + "-p", + "--preserve", + type=inkex.Boolean, + default=True, + help="Preserve original", + ) + pars.add_argument( + "-s", + "--separation", + type=float, + default=1, + help="Threshold for separating text with manual kerns in multiples of" + "font-size", + ) + + def effect(self): + """Applies the effect""" + + split_type = self.options.splittype + preserve = self.options.preserve + + # checks if the selected elements are text nodes + for elem in self.svg.selection.filter_nonzero(TextElement, FlowRoot): + try: + self.separation = self.options.separation + if split_type == "line": + node = self.split_lines(elem) + elif split_type == "word": + self.mode = self.process_plain_words + node = self.split_words_or_chars(elem) + else: + self.separation = 0 + self.mode = self.process_plain_chars + node = self.split_words_or_chars(elem) + + node.getparent().remove(node) + + if not preserve and node is not None: + elem.getparent().remove(elem) + except TypeError as err: + inkex.errormsg(err) # if an element can not be processed + + @staticmethod + def get_font_size(element): + """get the font size of an element""" + return element.specified_style()("font-size") + + @staticmethod + def get_line_height(element: ShapeElement): + """get the line height of an element""" + return element.get_line_height_uu() + + def simplify_child_tspans(self, element: TextElement): + """Checks all child tspans if they have manual kerns. + If it does, try to find words (characters with a distance > separation * font-size). + Then concatenate the words with spaces, set this string as a new text and""" + for child in list(element): + # process manual kerns + if not isinstance(child, Tspan): + continue + xvals = list( + map(float, filter(len, regex.split(r"[,\s]", child.get("x") or ""))) + ) + content = child.text + if content not in [None, ""] and len(xvals) >= 2: + fsize = self.get_font_size(child) + separation = self.separation * fsize + current_word_start = 0 + for i in range(1, max(len(content), len(xvals))): + if i >= len(content) - 1 or i >= len(xvals) - 1: + # consume the entire remaining string + i = len(content) + if i == len(content) or abs(xvals[i] - xvals[i - 1]) > separation: + wordspan = Tspan(x=str(xvals[current_word_start])) + wordspan.text = content[current_word_start:i] + child.add(wordspan) + current_word_start = i + child.pop("x") + child.text = None + # process child elements + self.simplify_child_tspans(child) + + def preprocess_text_element(self, element: TextElement): + """Processes a text element and returns an element containing tspans with x and y coordinate, + possibly nested (for Inkscape-type kerning), so that the actual splitting can work as if the + text was a simple text. Manual kerns (one x value per letter) are converted to spaces + if requested (not necessary for "split characters")""" + + oldelement = element + if isinstance(element, FlowRoot): + element = TextElement() + oldelement.addnext(element) + element.style = oldelement.style + element.transform = oldelement.transform + flowref = oldelement.findone("svg:flowRegion")[0] + if isinstance(flowref, Rectangle): + flowx = element.unittouu(flowref.get("x")) + flowy = element.unittouu(float(flowref.get("y"))) + first = True + else: + raise TypeError( + _( + "Element {} uses a flow region that is not a rectangle. " + "First unflow text." + ).format(element.get_id()) + ) + for child in oldelement: + if isinstance(child, FlowPara): + # convert the flowpara "line" (note: no automatic wrapping) + # to a tspan and set the y coordinate. + # future FlowRoot improvements could add a better conversion. + newchild = Tspan() + element.append(newchild) + newchild.text = child.text + newchild.style = child.style + newchild.transform = child.transform + newchild.set("x", flowx) + if first: + flowy += self.get_font_size(child) * 1.25 + first = False + else: + flowy += self.get_line_height(child) + newchild.set("y", str(flowy)) + + else: + element = oldelement.duplicate() + oldelement.getparent().append(element) + + element.style.pop("shape-inside", None) + + # Real support for RTL text is missing, but we can emulate it by just removing the + # attribute. However, line breaks will be misaligned. + element.style.pop("direction", None) + for child in element: + child.style.pop("direction", None) + + if self.process_kerns: + self.simplify_child_tspans(element) + return element + + def append_splitted_element(self, text, prototype=None): + """Creates a new text element, sibling to self.current_root, at (self.current_x, + self.current_y) with content text. + + text: either a Tspan that should be moved to a new text element - in this case, text is + a direct child of element; or a string + prototype: if text is a string, style and transform will be taken from prototype""" + + if isinstance(text, Tspan) and text.getparent() == self.current_root: + # we just move the tspan to a new text element. + elem = self.current_root.duplicate() + elem.remove_all(Tspan) + elem.append(text) + elem.set("x", text.get("x")) + elem.set("y", text.get("y")) + else: + elem = TextElement(x=str(self.current_x), y=str(self.current_y)) + # transfer the style from all parents, including the text element (if there's a style to + # the text element's parent applied, it will be duplicated, but that doesn't really + # matter) + elem.style = prototype.specified_style() + # the element will be appended to the parent of element, but there might be nested + # tspans between the prototype and the element. The next line says + # "compose transforms until you reach the parent of element" + elem.transform = ( + -self.current_root.getparent().transform + ) @ prototype.composed_transform() + tsp = Tspan(x=str(self.current_x), y=str(self.current_y)) + tsp.text = text + elem.add(tsp) + self.current_root.addnext(elem) + + def split_lines(self, element: TextLike) -> TextElement: + """Splits a text into its lines""" + self.process_kerns = False + preprocessed = self.preprocess_text_element(element) + self.current_root = preprocessed + # Now we only have to copy each tspan into its own text element. + for child in list(preprocessed): + self.append_splitted_element(child) + + return preprocessed + + def process_plain_text(self, element, splitted): + """Appends new text elements to as sibling root for each element of splitted, starting at + self.current_x, self.current_y, incrementing those, with prototype element (that + styles and transforms will be taken from)""" + if splitted is None: + return + for word in splitted: + if word != "": + self.append_splitted_element(word, element) + # +1 since for words, we lost a space + self.current_x += ( + self.current_fontsize * (len(word) + 1) * self.fs_multiplier + ) + + def process_plain_words(self, element, text): + """Calls process_plain_text for splitting words""" + self.fs_multiplier = 0.4 + if text is not None: + self.process_plain_text(element, text.split(" ")) + + def process_plain_chars(self, element, text): + """Calls process_plain_text for splitting characters""" + self.fs_multiplier = 0.25 + self.process_plain_text(element, text) + + def split_words_or_chars(self, element: TextLike) -> TextElement: + """Splits a text into its lines""" + self.process_kerns = True + preprocessed = self.preprocess_text_element(element) + + def process_element(element) -> float: + elem_coords = { + i: element.root.unittouu(element.get(i)) + if element.get(i) is not None + else None + for i in "xy" + } + if elem_coords["x"] is not None: + self.current_x = elem_coords["x"] + if elem_coords["y"] is not None: + self.current_y = elem_coords["y"] + self.current_fontsize = self.get_font_size(element) + current_x = self.mode(element, element.text) + + for elem in element: + if isinstance(elem, Tspan): + current_x = process_element(elem) + current_x = self.mode(element, elem.tail) + return current_x + + self.current_root = preprocessed + process_element(preprocessed) + return preprocessed + + +if __name__ == "__main__": + TextSplit().run() diff --git a/share/extensions/text_titlecase.inx b/share/extensions/text_titlecase.inx new file mode 100644 index 0000000..540b4a0 --- /dev/null +++ b/share/extensions/text_titlecase.inx @@ -0,0 +1,16 @@ + + + Title Case + org.inkscape.text.title_case + + all + + + + + + + + diff --git a/share/extensions/text_titlecase.py b/share/extensions/text_titlecase.py new file mode 100755 index 0000000..818d353 --- /dev/null +++ b/share/extensions/text_titlecase.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +"""Convert to title case""" + +import inkex + + +class TitleCase(inkex.TextExtension): + """To titlecase""" + + word_ended = True + + def process_chardata(self, text): + ret = "" + newline = True + for char in text: + if char.isspace() or newline: + self.word_ended = True + if not char.isspace(): + newline = False + + if self.word_ended and char.isalpha(): + ret += char.upper() + self.word_ended = False + elif char.isalpha(): + ret += char.lower() + else: + ret += char + + return ret + + +if __name__ == "__main__": + TitleCase().run() diff --git a/share/extensions/text_uppercase.inx b/share/extensions/text_uppercase.inx new file mode 100644 index 0000000..7787ca4 --- /dev/null +++ b/share/extensions/text_uppercase.inx @@ -0,0 +1,16 @@ + + + UPPERCASE + org.inkscape.text.uppercase + + all + + + + + + + + diff --git a/share/extensions/text_uppercase.py b/share/extensions/text_uppercase.py new file mode 100755 index 0000000..9b6fb6e --- /dev/null +++ b/share/extensions/text_uppercase.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Convert text to upper case""" + +import inkex + + +class Uppercase(inkex.TextExtension): + """To upper case""" + + def process_chardata(self, text): + return text.upper() + + +if __name__ == "__main__": + Uppercase().run() diff --git a/share/extensions/tools/generate_argparse_conf.py b/share/extensions/tools/generate_argparse_conf.py new file mode 100644 index 0000000..d99337b --- /dev/null +++ b/share/extensions/tools/generate_argparse_conf.py @@ -0,0 +1,69 @@ +# coding=utf-8 +import os +from string import Template +import xml.etree.ElementTree as ET +import argparse + +parser = argparse.ArgumentParser( + description="Reads an *.inx file and generates initialization code for argparse" +) +parser.add_argument("input") +args = parser.parse_args() + +if os.path.isabs(args.input): + inpath = args.input +else: + folder = os.path.dirname(os.path.realpath(__file__)) + inpath = os.path.normpath(os.path.join(folder, args.input)) + +templateWithType = Template( + 'self.arg_parser.add_argument("--$param", type=$type, dest="$param", default=$default)' +) +templateWithoutType = Template( + 'self.arg_parser.add_argument("--$param", dest="$param", default=$default)' +) + + +def handle_param_node(node): + if node.attrib["type"] == "float": + cmd = templateWithType.substitute( + param=node.attrib["name"], type="float", default=node.text + ) + print(cmd) + elif node.attrib["type"] == "int": + cmd = templateWithType.substitute( + param=node.attrib["name"], type="int", default=node.text + ) + print(cmd) + elif node.attrib["type"] == "boolean": + cmd = templateWithType.substitute( + param=node.attrib["name"], + type="inkex.inkbool", + default='"' + node.text + '"', + ) + print(cmd) + elif node.attrib["type"] == "enum": + cmd = templateWithoutType.substitute( + param=node.attrib["name"], default='"' + node[0].text + '"' + ) + print(cmd) + elif node.attrib["type"] == "notebook": + cmd = templateWithoutType.substitute( + param=node.attrib["name"], default='"' + node[0].attrib["name"] + '"' + ) + print(cmd) + else: + # TODO: Implement other types of args + raise NotImplementedError + + +def process_node(node): + for child in node: + if child.tag.endswith("param"): + handle_param_node(child) + process_node(child) + + +tree = ET.parse(inpath) +root = tree.getroot() +process_node(root) diff --git a/share/extensions/tox.ini b/share/extensions/tox.ini new file mode 100644 index 0000000..89229d2 --- /dev/null +++ b/share/extensions/tox.ini @@ -0,0 +1,29 @@ +[tox] +envlist = py{36,37,38,39,310}-normal-{linux,win} +isolated_build = true + + +[testenv] +platform = + linux: linux + win: win32 + +setenv = + COVERAGE_FILE=.coverage-{env:TOX_ENV_NAME} + win: COVERAGE_FILE=.coverage-{env:TOX_ENV_NAME}-win + +commands = + pytest --ignore=other --cov=. --cov-report html --cov-report term {posargs} + +[pytest] +addopts = --ignore=other + +[coverage3:paths] +source = + C:\GitLab-Runner\builds\*\extensions + C:\GitLab-Runner\builds\*\*\extensions + C:\builds\*\extensions + /builds/*/extensions + +[darglint] +strictness=short \ No newline at end of file diff --git a/share/extensions/triangle.inx b/share/extensions/triangle.inx new file mode 100644 index 0000000..460ed92 --- /dev/null +++ b/share/extensions/triangle.inx @@ -0,0 +1,27 @@ + + + Triangle + math.triangle + 100.0 + 100.0 + 100.0 + 60 + 30 + 90 + + + + + + + + + all + + + + + + diff --git a/share/extensions/triangle.py b/share/extensions/triangle.py new file mode 100755 index 0000000..a9f2812 --- /dev/null +++ b/share/extensions/triangle.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2007 John Beard john.j.beard@gmail.com +# +# 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. +# +""" +This extension allows you to draw a triangle given certain information + about side length or angles. + +Measurements of the triangle + + C(x_c,y_c) + /`__ + / a_c``--__ + / ``--__ s_a + s_b / ``--__ + /a_a a_b`--__ + /--------------------------------``B(x_b, y_b) + A(x_a,y_a) s_b +""" + +import sys +from math import acos, asin, cos, pi, sin, sqrt + +import inkex +from inkex.localization import inkex_gettext as _ + +X, Y = range(2) + + +def draw_SVG_tri(point1, point2, point3, offset, width, name, parent): + style = {"stroke": "#000000", "stroke-width": str(width), "fill": "none"} + elem = parent.add(inkex.PathElement()) + elem.update( + **{ + "style": style, + "inkscape:label": name, + "d": "M " + + str(point1[X] + offset[X]) + + "," + + str(point1[Y] + offset[Y]) + + " L " + + str(point2[X] + offset[X]) + + "," + + str(point2[Y] + offset[Y]) + + " L " + + str(point3[X] + offset[X]) + + "," + + str(point3[Y] + offset[Y]) + + " L " + + str(point1[X] + offset[X]) + + "," + + str(point1[Y] + offset[Y]) + + " z", + } + ) + return elem + + +def angle_from_3_sides(a, b, c): # return the angle opposite side c + cosx = (a * a + b * b - c * c) / (2 * a * b) # use the cosine rule + return acos(cosx) + + +def third_side_from_enclosed_angle(s_a, s_b, a_c): # return the side opposite a_c + c_squared = s_a * s_a + s_b * s_b - 2 * s_a * s_b * cos(a_c) + if c_squared > 0: + return sqrt(c_squared) + else: + return 0 # means we have an invalid or degenerate triangle (zero is caught at the drawing stage) + + +def pt_on_circ(radius, angle): # return the x,y coordinate of the polar coordinate + x = radius * cos(angle) + y = radius * sin(angle) + return [x, y] + + +def v_add(point1, point2): # add an offset to coordinates + return [point1[X] + point2[X], point1[Y] + point2[Y]] + + +def is_valid_tri_from_sides( + a, b, c +): # check whether triangle with sides a,b,c is valid + return ( + (a + b) > c and (a + c) > b and (b + c) > a and a > 0 and b > 0 and c > 0 + ) # two sides must always be greater than the third + # no zero-length sides, no degenerate case + + +def draw_tri_from_3_sides( + s_a, s_b, s_c, offset, width, parent +): # draw a triangle from three sides (with a given offset + if is_valid_tri_from_sides(s_a, s_b, s_c): + a_b = angle_from_3_sides(s_a, s_c, s_b) + + a = (0, 0) # a is the origin + b = v_add(a, (s_c, 0)) # point B is horizontal from the origin + c = v_add(b, pt_on_circ(s_a, pi - a_b)) # get point c + c[1] = -c[1] + + offx = max(b[0], c[0]) / 2 # b or c could be the furthest right + offy = c[1] / 2 # c is the highest point + offset = ( + offset[0] - offx, + offset[1] - offy, + ) # add the centre of the triangle to the offset + + draw_SVG_tri(a, b, c, offset, width, "Triangle", parent) + else: + inkex.errormsg(_("Invalid Triangle Specifications.")) + + +class Triangle(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument("--s_a", type=float, default=100.0, help="Side Length a") + pars.add_argument("--s_b", type=float, default=100.0, help="Side Length b") + pars.add_argument("--s_c", type=float, default=100.0, help="Side Length c") + pars.add_argument("--a_a", type=float, default=60.0, help="Angle a") + pars.add_argument("--a_b", type=float, default=30.0, help="Angle b") + pars.add_argument("--a_c", type=float, default=90.0, help="Angle c") + pars.add_argument("--mode", default="3_sides", help="Side Length c") + + def effect(self): + tri = self.svg.get_current_layer() + offset = self.svg.namedview.center + self.options.s_a = self.svg.unittouu(str(self.options.s_a) + "px") + self.options.s_b = self.svg.unittouu(str(self.options.s_b) + "px") + self.options.s_c = self.svg.unittouu(str(self.options.s_c) + "px") + stroke_width = self.svg.unittouu("2px") + + if self.options.mode == "3_sides": + s_a = self.options.s_a + s_b = self.options.s_b + s_c = self.options.s_c + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + elif self.options.mode == "s_ab_a_c": + s_a = self.options.s_a + s_b = self.options.s_b + a_c = self.options.a_c * pi / 180 # in rad + + s_c = third_side_from_enclosed_angle(s_a, s_b, a_c) + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + elif self.options.mode == "s_ab_a_a": + s_a = self.options.s_a + s_b = self.options.s_b + a_a = self.options.a_a * pi / 180 # in rad + + if ( + (a_a < pi / 2.0) and (s_a < s_b) and (s_a > s_b * sin(a_a)) + ): # this is an ambiguous case + ambiguous = True # we will give both answers + else: + ambiguous = False + + sin_a_b = s_b * sin(a_a) / s_a + + if (sin_a_b <= 1) and (sin_a_b >= -1): # check the solution is possible + a_b = asin(sin_a_b) # acute solution + a_c = pi - a_a - a_b + error = False + else: + sys.stderr.write( + "Error:Invalid Triangle Specifications.\n" + ) # signal an error + error = True + + if ( + not error and (a_b < pi) and (a_c < pi) + ): # check that the solution is valid, if so draw acute solution + s_c = third_side_from_enclosed_angle(s_a, s_b, a_c) + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + if not error and ( + (a_b > pi) or (a_c > pi) or ambiguous + ): # we want the obtuse solution + a_b = pi - a_b + a_c = pi - a_a - a_b + s_c = third_side_from_enclosed_angle(s_a, s_b, a_c) + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + elif self.options.mode == "s_a_a_ab": + s_a = self.options.s_a + a_a = self.options.a_a * pi / 180 # in rad + a_b = self.options.a_b * pi / 180 # in rad + + a_c = pi - a_a - a_b + s_b = s_a * sin(a_b) / sin(a_a) + s_c = s_a * sin(a_c) / sin(a_a) + + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + elif self.options.mode == "s_c_a_ab": + s_c = self.options.s_c + a_a = self.options.a_a * pi / 180 # in rad + a_b = self.options.a_b * pi / 180 # in rad + + a_c = pi - a_a - a_b + s_a = s_c * sin(a_a) / sin(a_c) + s_b = s_c * sin(a_b) / sin(a_c) + + draw_tri_from_3_sides(s_a, s_b, s_c, offset, stroke_width, tri) + + +if __name__ == "__main__": + Triangle().run() diff --git a/share/extensions/ungroup_deep.inx b/share/extensions/ungroup_deep.inx new file mode 100644 index 0000000..cc93d04 --- /dev/null +++ b/share/extensions/ungroup_deep.inx @@ -0,0 +1,18 @@ + + + Deep Ungroup + mcepl.ungroup_deep + + 0 + 65535 + 0 + + all + + + + + + diff --git a/share/extensions/ungroup_deep.py b/share/extensions/ungroup_deep.py new file mode 100755 index 0000000..36a01bf --- /dev/null +++ b/share/extensions/ungroup_deep.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# coding=utf-8 +""" +see #inkscape on Freenode and +https://github.com/nikitakit/svg2sif/blob/master/synfig_prepare.py#L370 +for an example how to do the transform of parent to children. +""" + +import inkex +from inkex import ( + Group, + Anchor, + Switch, + NamedView, + Defs, + Metadata, + ForeignObject, + ClipPath, + Use, + SvgDocumentElement, +) + + +class UngroupDeep(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument( + "--startdepth", type=int, default=0, help="starting depth for ungrouping" + ) + pars.add_argument( + "--maxdepth", type=int, default=65535, help="maximum ungrouping depth" + ) + pars.add_argument( + "--keepdepth", + type=int, + default=0, + help="levels of ungrouping to leave untouched", + ) + + @staticmethod + def _merge_style(node, style): + """Propagate style and transform to remove inheritance + Originally from + https://github.com/nikitakit/svg2sif/blob/master/synfig_prepare.py#L370 + """ + + # Compose the style attribs + this_style = node.style + remaining_style = {} # Style attributes that are not propagated + + # Filters should remain on the top ancestor + non_propagated = ["filter"] + for key in non_propagated: + if key in this_style.keys(): + remaining_style[key] = this_style[key] + del this_style[key] + + # Create a copy of the parent style, and merge this style into it + parent_style_copy = style.copy() + parent_style_copy.update(this_style) + this_style = parent_style_copy + + # Merge in any attributes outside of the style + style_attribs = ["fill", "stroke"] + for attrib in style_attribs: + if node.get(attrib): + this_style[attrib] = node.get(attrib) + del node.attrib[attrib] + + if isinstance(node, (SvgDocumentElement, Anchor, Group, Switch)): + # Leave only non-propagating style attributes + if not remaining_style: + if "style" in node.keys(): + del node.attrib["style"] + else: + node.style = remaining_style + + else: + # This element is not a container + + # Merge remaining_style into this_style + this_style.update(remaining_style) + + # Set the element's style attribs + node.style = this_style + + def _merge_clippath(self, node, clippathurl): + if clippathurl and clippathurl != "none": + node_transform = node.transform + if node_transform: + # Clip-paths on nodes with a transform have the transform + # applied to the clipPath as well, which we don't want. So, we + # create new clipPath element with references to all existing + # clippath subelements, but with the inverse transform applied + new_clippath = self.svg.defs.add( + ClipPath(clipPathUnits="userSpaceOnUse") + ) + new_clippath.set_random_id("clipPath") + clippath = self.svg.getElementById(clippathurl[5:-1]) + for child in clippath.iterchildren(): + new_clippath.add(Use.new(child, 0, 0)) + + # Set the clippathurl to be the one with the inverse transform + clippathurl = "url(#" + new_clippath.get("id") + ")" + + # Reference the parent clip-path to keep clipping intersection + # Find end of clip-path chain and add reference there + node_clippathurl = node.get("clip-path") + while node_clippathurl: + node = self.svg.getElementById(node_clippathurl[5:-1]) + node_clippathurl = node.get("clip-path") + node.set("clip-path", clippathurl) + + # Flatten a group into same z-order as parent, propagating attribs + def _ungroup(self, node): + node_parent = node.getparent() + node_index = list(node_parent).index(node) + node_style = node.style + + node_transform = node.transform + node_clippathurl = node.get("clip-path") + for child in reversed(list(node)): + if not isinstance(child, inkex.BaseElement): + continue + child.transform = node_transform @ child.transform + + if node.get("style") is not None: + self._merge_style(child, node_style) + self._merge_clippath(child, node_clippathurl) + node_parent.insert(node_index, child) + node_parent.remove(node) + + # Put all ungrouping restrictions here + def _want_ungroup(self, node, depth, height): + if ( + isinstance(node, Group) + and node.getparent() is not None + and height > self.options.keepdepth + and self.options.startdepth <= depth <= self.options.maxdepth + ): + return True + return False + + def _deep_ungroup(self, node): + # using iteration instead of recursion to avoid hitting Python + # max recursion depth limits, which is a problem in converted PDFs + + # Seed the queue (stack) with initial node + q = [{"node": node, "depth": 0, "prev": {"height": None}, "height": None}] + + while q: + current = q[-1] + node = current["node"] + depth = current["depth"] + height = current["height"] + + # Recursion path + if height is None: + # Don't enter non-graphical portions of the document + if isinstance(node, (NamedView, Defs, Metadata, ForeignObject)): + q.pop() + + # Base case: Leaf node + if not isinstance(node, Group) or not list(node): + current["height"] = 0 + + # Recursive case: Group element with children + else: + depth += 1 + for child in node.iterchildren(): + q.append( + { + "node": child, + "prev": current, + "depth": depth, + "height": None, + } + ) + + # Return path + else: + # Ungroup if desired + if self._want_ungroup(node, depth, height): + self._ungroup(node) + + # Propagate (max) height up the call chain + height += 1 + previous = current["prev"] + prev_height = previous["height"] + if prev_height is None or prev_height < height: + previous["height"] = height + + # Only process each node once + q.pop() + + def effect(self): + if self.svg.selection: + for node in self.svg.selection.values(): + self._deep_ungroup(node) + else: + for node in self.document.getroot(): + self._deep_ungroup(node) + + +if __name__ == "__main__": + UngroupDeep().run() diff --git a/share/extensions/voronoi.py b/share/extensions/voronoi.py new file mode 100755 index 0000000..6015c7e --- /dev/null +++ b/share/extensions/voronoi.py @@ -0,0 +1,859 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Voronoi diagram calculator/ Delaunay triangulator +# Translated to Python by Bill Simons +# September, 2005 +# +# Calculate Delaunay triangulation or the Voronoi polygons for a set of +# 2D input points. +# +# Derived from code bearing the following notice: +# +# The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T +# Bell Laboratories. +# Permission to use, copy, modify, and distribute this software for any +# purpose without fee is hereby granted, provided that this entire notice +# is included in all copies of any software which is or includes a copy +# or modification of this software and in all copies of the supporting +# documentation for such software. +# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +# WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY +# REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY +# OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. +# +# Comments were incorporated from Shane O'Sullivan's translation of the +# original code into C++ (http://mapviewer.skynet.ie/voronoi.html) +# +# Steve Fortune's homepage: http://netlib.bell-labs.com/cm/cs/who/sjf/index.html +# +""" +voronoi - compute Voronoi diagram or Delaunay triangulation + +voronoi [-t -p -d] [filename] + +Voronoi reads from filename (or standard input if no filename given) for a set +of points in the plane and writes either the Voronoi diagram or the Delaunay +triangulation to the standard output. Each input line should consist of two +real numbers, separated by white space. + +If option -t is present, the Delaunay triangulation is produced. +Each output line is a triple i j k, which are the indices of the three points +in a Delaunay triangle. Points are numbered starting at 0. + +If option -t is not present, the Voronoi diagram is produced. +There are four output record types. + +s a b indicates that an input point at coordinates a b was seen. +l a b c indicates a line with equation ax + by = c. +v a b indicates a vertex at a b. +e l v1 v2 indicates a Voronoi segment which is a subsegment of line number l + with endpoints numbered v1 and v2. If v1 or v2 is -1, the line + extends to infinity. + +Other options include: + +d Print debugging info + +p Produce output suitable for input to plot (1), rather than the forms + described above. + +On unsorted data uniformly distributed in the unit square, voronoi uses about +20n+140 bytes of storage. + +AUTHOR +Steve J. Fortune (1987) A Sweepline Algorithm for Voronoi Diagrams, +Algorithmica 2, 153-174. +""" + +############################################################################# +# +# For programmatic use two functions are available: +# +# computeVoronoiDiagram(points) +# +# Takes a list of point objects (which must have x and y fields). +# Returns a 3-tuple of: +# +# (1) a list of 2-tuples, which are the x,y coordinates of the +# Voronoi diagram vertices +# (2) a list of 3-tuples (a,b,c) which are the equations of the +# lines in the Voronoi diagram: a*x + b*y = c +# (3) a list of 3-tuples, (l, v1, v2) representing edges of the +# Voronoi diagram. l is the index of the line, v1 and v2 are +# the indices of the vetices at the end of the edge. If +# v1 or v2 is -1, the line extends to infinity. +# +# computeDelaunayTriangulation(points): +# +# Takes a list of point objects (which must have x and y fields). +# Returns a list of 3-tuples: the indices of the points that form a +# Delaunay triangle. +# +############################################################################# + +from __future__ import print_function + +import getopt +import math +import sys + +TOLERANCE = 1e-9 +BIG_FLOAT = 1e38 + + +class CmpMixin(object): + """Upgrade python2 cmp to python3 cmp""" + + def __cmp__(self, other): + raise NotImplementedError("Shouldn't there be a __cmp__ method?") + + def __eq__(self, other): + return self.__cmp__(other) == 0 + + def __ne__(self, other): + return self.__cmp__(other) != 0 + + def __lt__(self, other): + return self.__cmp__(other) == -1 + + def __le__(self, other): + return self.__cmp__(other) in (-1, 0) + + def __gt__(self, other): + return self.__cmp__(other) == 1 + + def __ge__(self, other): + return self.__cmp__(other) in (0, 1) + + +# ------------------------------------------------------------------ +class Context(object): + def __init__(self): + self.doPrint = 0 + self.debug = 0 + self.plot = 0 + self.triangulate = False + self.vertices = [] # list of vertex 2-tuples: (x,y) + self.lines = ( + [] + ) # equation of line 3-tuple (a b c), for the equation of the line a*x+b*y = c + self.edges = ( + [] + ) # edge 3-tuple: (line index, vertex 1 index, vertex 2 index) if either vertex index is -1, the edge extends to infiinity + self.triangles = [] # 3-tuple of vertex indices + + def circle(self, x, y, rad): + pass + + def clip_line(self, edge): + pass + + def line(self, x0, y0, x1, y1): + pass + + def outSite(self, s): + if self.debug: + print("site (%d) at %f %f" % (s.sitenum, s.x, s.y)) + elif self.triangulate: + pass + elif self.plot: + self.circle(s.x, s.y, cradius) + elif self.doPrint: + print("s %f %f" % (s.x, s.y)) + + def outVertex(self, s): + self.vertices.append((s.x, s.y)) + if self.debug: + print("vertex(%d) at %f %f" % (s.sitenum, s.x, s.y)) + elif self.triangulate: + pass + elif self.doPrint and not self.plot: + print("v %f %f" % (s.x, s.y)) + + def outTriple(self, s1, s2, s3): + self.triangles.append((s1.sitenum, s2.sitenum, s3.sitenum)) + if self.debug: + print( + "circle through left=%d right=%d bottom=%d" + % (s1.sitenum, s2.sitenum, s3.sitenum) + ) + elif self.triangulate and self.doPrint and not self.plot: + print("%d %d %d" % (s1.sitenum, s2.sitenum, s3.sitenum)) + + def outBisector(self, edge): + self.lines.append((edge.a, edge.b, edge.c)) + if self.debug: + print( + "line(%d) %gx+%gy=%g, bisecting %d %d" + % ( + edge.edgenum, + edge.a, + edge.b, + edge.c, + edge.reg[0].sitenum, + edge.reg[1].sitenum, + ) + ) + elif self.triangulate: + if self.plot: + self.line(edge.reg[0].x, edge.reg[0].y, edge.reg[1].x, edge.reg[1].y) + elif self.doPrint and not self.plot: + print("l %f %f %f" % (edge.a, edge.b, edge.c)) + + def outEdge(self, edge): + sitenumL = -1 + if edge.ep[Edge.LE] is not None: + sitenumL = edge.ep[Edge.LE].sitenum + sitenumR = -1 + if edge.ep[Edge.RE] is not None: + sitenumR = edge.ep[Edge.RE].sitenum + self.edges.append((edge.edgenum, sitenumL, sitenumR)) + if not self.triangulate: + if self.plot: + self.clip_line(edge) + elif self.doPrint: + print("e %d" % edge.edgenum, end=" ") + print(" %d " % sitenumL, end=" ") + print("%d" % sitenumR) + + +# ------------------------------------------------------------------ +def voronoi(siteList, context): + edgeList = EdgeList(siteList.xmin, siteList.xmax, len(siteList)) + priorityQ = PriorityQueue(siteList.ymin, siteList.ymax, len(siteList)) + siteIter = siteList.iterator() + + bottomsite = siteIter.next() + context.outSite(bottomsite) + newsite = siteIter.next() + minpt = Site(-BIG_FLOAT, -BIG_FLOAT) + while True: + if not priorityQ.isEmpty(): + minpt = priorityQ.getMinPt() + + if newsite and (priorityQ.isEmpty() or newsite < minpt): + # newsite is smallest - this is a site event + context.outSite(newsite) + + # get first Halfedge to the LEFT and RIGHT of the new site + lbnd = edgeList.leftbnd(newsite) + rbnd = lbnd.right + + # if this halfedge has no edge, bot = bottom site (whatever that is) + # create a new edge that bisects + bot = lbnd.rightreg(bottomsite) + edge = Edge.bisect(bot, newsite) + context.outBisector(edge) + + # create a new Halfedge, setting its pm field to 0 and insert + # this new bisector edge between the left and right vectors in + # a linked list + bisector = Halfedge(edge, Edge.LE) + edgeList.insert(lbnd, bisector) + + # if the new bisector intersects with the left edge, remove + # the left edge's vertex, and put in the new one + p = lbnd.intersect(bisector) + if p is not None: + priorityQ.delete(lbnd) + priorityQ.insert(lbnd, p, newsite.distance(p)) + + # create a new Halfedge, setting its pm field to 1 + # insert the new Halfedge to the right of the original bisector + lbnd = bisector + bisector = Halfedge(edge, Edge.RE) + edgeList.insert(lbnd, bisector) + + # if this new bisector intersects with the right Halfedge + p = bisector.intersect(rbnd) + if p is not None: + # push the Halfedge into the ordered linked list of vertices + priorityQ.insert(bisector, p, newsite.distance(p)) + + newsite = siteIter.next() + + elif not priorityQ.isEmpty(): + # intersection is smallest - this is a vector (circle) event + + # pop the Halfedge with the lowest vector off the ordered list of + # vectors. Get the Halfedge to the left and right of the above HE + # and also the Halfedge to the right of the right HE + lbnd = priorityQ.popMinHalfedge() + llbnd = lbnd.left + rbnd = lbnd.right + rrbnd = rbnd.right + + # get the Site to the left of the left HE and to the right of + # the right HE which it bisects + bot = lbnd.leftreg(bottomsite) + top = rbnd.rightreg(bottomsite) + + # output the triple of sites, stating that a circle goes through them + mid = lbnd.rightreg(bottomsite) + context.outTriple(bot, top, mid) + + # get the vertex that caused this event and set the vertex number + # couldn't do this earlier since we didn't know when it would be processed + v = lbnd.vertex + siteList.setSiteNumber(v) + context.outVertex(v) + + # set the endpoint of the left and right Halfedge to be this vector + if lbnd.edge.setEndpoint(lbnd.pm, v): + context.outEdge(lbnd.edge) + + if rbnd.edge.setEndpoint(rbnd.pm, v): + context.outEdge(rbnd.edge) + + # delete the lowest HE, remove all vertex events to do with the + # right HE and delete the right HE + edgeList.delete(lbnd) + priorityQ.delete(rbnd) + edgeList.delete(rbnd) + + # if the site to the left of the event is higher than the Site + # to the right of it, then swap them and set 'pm' to RIGHT + pm = Edge.LE + if bot.y > top.y: + bot, top = top, bot + pm = Edge.RE + + # Create an Edge (or line) that is between the two Sites. This + # creates the formula of the line, and assigns a line number to it + edge = Edge.bisect(bot, top) + context.outBisector(edge) + + # create a HE from the edge + bisector = Halfedge(edge, pm) + + # insert the new bisector to the right of the left HE + # set one endpoint to the new edge to be the vector point 'v' + # If the site to the left of this bisector is higher than the right + # Site, then this endpoint is put in position 0; otherwise in pos 1 + edgeList.insert(llbnd, bisector) + if edge.setEndpoint(Edge.RE - pm, v): + context.outEdge(edge) + + # if left HE and the new bisector don't intersect, then delete + # the left HE, and reinsert it + p = llbnd.intersect(bisector) + if p is not None: + priorityQ.delete(llbnd) + priorityQ.insert(llbnd, p, bot.distance(p)) + + # if right HE and the new bisector don't intersect, then reinsert it + p = bisector.intersect(rrbnd) + if p is not None: + priorityQ.insert(bisector, p, bot.distance(p)) + else: + break + + he = edgeList.leftend.right + while he is not edgeList.rightend: + context.outEdge(he.edge) + he = he.right + + +# ------------------------------------------------------------------ +def isEqual(a, b, relativeError=TOLERANCE): + # is nearly equal to within the allowed relative error + norm = max(abs(a), abs(b)) + return (norm < relativeError) or (abs(a - b) < (relativeError * norm)) + + +# ------------------------------------------------------------------ +class Site(CmpMixin): + def __init__(self, x=0.0, y=0.0, sitenum=0): + self.x = x + self.y = y + self.sitenum = sitenum + + def dump(self): + print("Site #%d (%g, %g)" % (self.sitenum, self.x, self.y)) + + def __cmp__(self, other): + if self.y < other.y: + return -1 + elif self.y > other.y: + return 1 + elif self.x < other.x: + return -1 + elif self.x > other.x: + return 1 + return 0 + + def distance(self, other): + dx = self.x - other.x + dy = self.y - other.y + return math.sqrt(dx * dx + dy * dy) + + +# ------------------------------------------------------------------ +class Edge(object): + LE = 0 + RE = 1 + EDGE_NUM = 0 + DELETED = {} # marker value + + def __init__(self): + self.a = 0.0 + self.b = 0.0 + self.c = 0.0 + self.ep = [None, None] + self.reg = [None, None] + self.edgenum = 0 + + def dump(self): + print("(#%d a=%g, b=%g, c=%g)" % (self.edgenum, self.a, self.b, self.c)) + print("ep", self.ep) + print("reg", self.reg) + + def setEndpoint(self, lrFlag, site): + self.ep[lrFlag] = site + if self.ep[Edge.RE - lrFlag] is None: + return False + return True + + @staticmethod + def bisect(s1, s2): + newedge = Edge() + newedge.reg[0] = s1 # store the sites that this edge is bisecting + newedge.reg[1] = s2 + + # to begin with, there are no endpoints on the bisector - it goes to infinity + # ep[0] and ep[1] are None + + # get the difference in x dist between the sites + dx = float(s2.x - s1.x) + dy = float(s2.y - s1.y) + adx = abs(dx) # make sure that the difference in positive + ady = abs(dy) + + # get the slope of the line + newedge.c = float(s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * 0.5) + if adx > ady: + # set formula of line, with x fixed to 1 + newedge.a = 1.0 + newedge.b = dy / dx + newedge.c /= dx + else: + # set formula of line, with y fixed to 1 + newedge.b = 1.0 + if dy <= 0: + dy = 0.01 + newedge.a = dx / dy + newedge.c /= dy + + newedge.edgenum = Edge.EDGE_NUM + Edge.EDGE_NUM += 1 + return newedge + + +# ------------------------------------------------------------------ +class Halfedge(CmpMixin): + def __init__(self, edge=None, pm=Edge.LE): + self.left = None # left Halfedge in the edge list + self.right = None # right Halfedge in the edge list + self.qnext = None # priority queue linked list pointer + self.edge = edge # edge list Edge + self.pm = pm + self.vertex = None # Site() + self.ystar = BIG_FLOAT + + def dump(self): + print("Halfedge--------------------------") + print("left: ", self.left) + print("right: ", self.right) + print("edge: ", self.edge) + print("pm: ", self.pm) + print("vertex: ", end=" ") + if self.vertex: + self.vertex.dump() + else: + print("None") + print("ystar: ", self.ystar) + + def __cmp__(self, other): + if self.ystar > other.ystar: + return 1 + elif self.ystar < other.ystar: + return -1 + elif self.vertex.x > other.vertex.x: + return 1 + elif self.vertex.x < other.vertex.x: + return -1 + else: + return 0 + + def leftreg(self, default): + if not self.edge: + return default + elif self.pm == Edge.LE: + return self.edge.reg[Edge.LE] + else: + return self.edge.reg[Edge.RE] + + def rightreg(self, default): + if not self.edge: + return default + elif self.pm == Edge.LE: + return self.edge.reg[Edge.RE] + else: + return self.edge.reg[Edge.LE] + + # returns True if p is to right of halfedge self + def isPointRightOf(self, pt): + e = self.edge + topsite = e.reg[1] + right_of_site = pt.x > topsite.x + + if right_of_site and self.pm == Edge.LE: + return True + + if not right_of_site and self.pm == Edge.RE: + return False + + if e.a == 1.0: + dyp = pt.y - topsite.y + dxp = pt.x - topsite.x + fast = 0 + if (not right_of_site and e.b < 0.0) or (right_of_site and e.b >= 0.0): + above = dyp >= e.b * dxp + fast = above + else: + above = pt.x + pt.y * e.b > e.c + if e.b < 0.0: + above = not above + if not above: + fast = 1 + if not fast: + dxs = topsite.x - (e.reg[0]).x + above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * ( + 1.0 + 2.0 * dxp / dxs + e.b * e.b + ) + if e.b < 0.0: + above = not above + else: # e.b == 1.0 + yl = e.c - e.a * pt.x + t1 = pt.y - yl + t2 = pt.x - topsite.x + t3 = yl - topsite.y + above = t1 * t1 > t2 * t2 + t3 * t3 + + if self.pm == Edge.LE: + return above + else: + return not above + + # -------------------------- + # create a new site where the Halfedges el1 and el2 intersect + def intersect(self, other): + e1 = self.edge + e2 = other.edge + if (e1 is None) or (e2 is None): + return None + + # if the two edges bisect the same parent return None + if e1.reg[1] is e2.reg[1]: + return None + + d = e1.a * e2.b - e1.b * e2.a + if isEqual(d, 0.0): + return None + + xint = (e1.c * e2.b - e2.c * e1.b) / d + yint = (e2.c * e1.a - e1.c * e2.a) / d + if e1.reg[1] < e2.reg[1]: + he = self + e = e1 + else: + he = other + e = e2 + + rightOfSite = xint >= e.reg[1].x + if (rightOfSite and he.pm == Edge.LE) or (not rightOfSite and he.pm == Edge.RE): + return None + + # create a new site at the point of intersection - this is a new + # vector event waiting to happen + return Site(xint, yint) + + +# ------------------------------------------------------------------ +class EdgeList(object): + def __init__(self, xmin, xmax, nsites): + if xmin > xmax: + xmin, xmax = xmax, xmin + self.hashsize = int(2 * math.sqrt(nsites + 4)) + + self.xmin = xmin + self.deltax = float(xmax - xmin) + self.hash = [None] * self.hashsize + + self.leftend = Halfedge() + self.rightend = Halfedge() + self.leftend.right = self.rightend + self.rightend.left = self.leftend + self.hash[0] = self.leftend + self.hash[-1] = self.rightend + + def insert(self, left, he): + he.left = left + he.right = left.right + left.right.left = he + left.right = he + + def delete(self, he): + he.left.right = he.right + he.right.left = he.left + he.edge = Edge.DELETED + + # Get entry from hash table, pruning any deleted nodes + def gethash(self, b): + if b < 0 or b >= self.hashsize: + return None + he = self.hash[b] + if he is None or he.edge is not Edge.DELETED: + return he + + # Hash table points to deleted half edge. Patch as necessary. + self.hash[b] = None + return None + + def leftbnd(self, pt): + # Use hash table to get close to desired halfedge + bucket = int(((pt.x - self.xmin) / self.deltax * self.hashsize)) + + if bucket < 0: + bucket = 0 + + if bucket >= self.hashsize: + bucket = self.hashsize - 1 + + he = self.gethash(bucket) + if he is None: + i = 1 + while True: + he = self.gethash(bucket - i) + if he is not None: + break + he = self.gethash(bucket + i) + if he is not None: + break + i += 1 + + # Now search linear list of halfedges for the correct one + if (he is self.leftend) or (he is not self.rightend and he.isPointRightOf(pt)): + he = he.right + while he is not self.rightend and he.isPointRightOf(pt): + he = he.right + he = he.left + else: + he = he.left + while he is not self.leftend and not he.isPointRightOf(pt): + he = he.left + + # Update hash table and reference counts + if 0 < bucket < self.hashsize - 1: + self.hash[bucket] = he + return he + + +# ------------------------------------------------------------------ +class PriorityQueue(object): + def __init__(self, ymin, ymax, nsites): + self.ymin = ymin + self.deltay = ymax - ymin + self.hashsize = int(4 * math.sqrt(nsites)) + self.count = 0 + self.minidx = 0 + self.hash = [] + for i in range(self.hashsize): + self.hash.append(Halfedge()) + + def __len__(self): + return self.count + + def isEmpty(self): + return self.count == 0 + + def insert(self, he, site, offset): + he.vertex = site + he.ystar = site.y + offset + last = self.hash[self.getBucket(he)] + nxt = last.qnext + while (nxt is not None) and he > nxt: + last = nxt + nxt = last.qnext + he.qnext = last.qnext + last.qnext = he + self.count += 1 + + def delete(self, he): + if he.vertex is not None: + last = self.hash[self.getBucket(he)] + while last.qnext is not he: + last = last.qnext + last.qnext = he.qnext + self.count -= 1 + he.vertex = None + + def getBucket(self, he): + bucket = int(((he.ystar - self.ymin) / self.deltay) * self.hashsize) + if bucket < 0: + bucket = 0 + if bucket >= self.hashsize: + bucket = self.hashsize - 1 + if bucket < self.minidx: + self.minidx = bucket + return bucket + + def getMinPt(self): + while self.hash[self.minidx].qnext is None: + self.minidx += 1 + he = self.hash[self.minidx].qnext + x = he.vertex.x + y = he.ystar + return Site(x, y) + + def popMinHalfedge(self): + curr = self.hash[self.minidx].qnext + self.hash[self.minidx].qnext = curr.qnext + self.count -= 1 + return curr + + +# ------------------------------------------------------------------ +class SiteList(object): + def __init__(self, pointList): + self.__sites = [] + self.__sitenum = 0 + + self.__xmin = pointList[0].x + self.__ymin = pointList[0].y + self.__xmax = pointList[0].x + self.__ymax = pointList[0].y + for i, pt in enumerate(pointList): + self.__sites.append(Site(pt.x, pt.y, i)) + if pt.x < self.__xmin: + self.__xmin = pt.x + if pt.y < self.__ymin: + self.__ymin = pt.y + if pt.x > self.__xmax: + self.__xmax = pt.x + if pt.y > self.__ymax: + self.__ymax = pt.y + self.__sites.sort() + + def setSiteNumber(self, site): + site.sitenum = self.__sitenum + self.__sitenum += 1 + + class Iterator(object): + def __init__(this, lst): + this.generator = (s for s in lst) + + def __iter__(this): + return this + + def next(this): + try: + return next(this.generator) + except StopIteration: + return None + + def iterator(self): + return SiteList.Iterator(self.__sites) + + def __iter__(self): + return SiteList.Iterator(self.__sites) + + def __len__(self): + return len(self.__sites) + + def _getxmin(self): + return self.__xmin + + def _getymin(self): + return self.__ymin + + def _getxmax(self): + return self.__xmax + + def _getymax(self): + return self.__ymax + + xmin = property(_getxmin) + ymin = property(_getymin) + xmax = property(_getxmax) + ymax = property(_getymax) + + +# ------------------------------------------------------------------ +def computeVoronoiDiagram(points): + """Takes a list of point objects (which must have x and y fields). + Returns a 3-tuple of: + + (1) a list of 2-tuples, which are the x,y coordinates of the + Voronoi diagram vertices + (2) a list of 3-tuples (a,b,c) which are the equations of the + lines in the Voronoi diagram: a*x + b*y = c + (3) a list of 3-tuples, (l, v1, v2) representing edges of the + Voronoi diagram. l is the index of the line, v1 and v2 are + the indices of the vetices at the end of the edge. If + v1 or v2 is -1, the line extends to infinity. + """ + Edge.EDGE_NUM = 0 + siteList = SiteList(points) + context = Context() + voronoi(siteList, context) + return context.vertices, context.lines, context.edges + + +# ------------------------------------------------------------------ +def computeDelaunayTriangulation(points): + """Takes a list of point objects (which must have x and y fields). + Returns a list of 3-tuples: the indices of the points that form a + Delaunay triangle. + """ + Edge.EDGE_NUM = 0 + siteList = SiteList(points) + context = Context() + context.triangulate = True + voronoi(siteList, context) + return context.triangles + + +# ----------------------------------------------------------------------------- +if __name__ == "__main__": + optlist, args = getopt.getopt(sys.argv[1:], "thdp") + + doHelp = 0 + c = Context() + c.doPrint = 1 + for opt in optlist: + if opt[0] == "-d": + c.debug = 1 + if opt[0] == "-p": + c.plot = 1 + if opt[0] == "-t": + c.triangulate = 1 + if opt[0] == "-h": + doHelp = 1 + + if not doHelp: + pts = [] + fp = sys.stdin + if len(args) > 0: + fp = open(args[0], "r") + for line in fp: + fld = line.split() + x = float(fld[0]) + y = float(fld[1]) + pts.append(Site(x, y)) + if len(args) > 0: + fp.close() + + sl = SiteList(pts) + voronoi(sl, c) diff --git a/share/extensions/voronoi2svg.inx b/share/extensions/voronoi2svg.inx new file mode 100644 index 0000000..febd78d --- /dev/null +++ b/share/extensions/voronoi2svg.inx @@ -0,0 +1,39 @@ + + + Voronoi Diagram + org.inkscape.effect.voronoi + voronoi.py + + + + + + + + + + + + + false + + + + + + + + + + + + + all + + + + + + diff --git a/share/extensions/voronoi2svg.py b/share/extensions/voronoi2svg.py new file mode 100755 index 0000000..e4cf802 --- /dev/null +++ b/share/extensions/voronoi2svg.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2011 Vincent Nivoliers and contributors +# +# Contributors +# ~suv, +# - Voronoi Diagram algorithm and C code by Steven Fortune, 1987, http://ect.bell-labs.com/who/sjf/ +# - Python translation to file voronoi.py by Bill Simons, 2005, http://www.oxfish.com/ +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +""" +Create Voronoi diagram from seeds (midpoints of selected objects) +""" + +import random + +import inkex +from inkex import Group, Rectangle, PathElement, Vector2d as Point + +import voronoi + + +class Voronoi(inkex.EffectExtension): + """Extension to create a Voronoi diagram.""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument( + "--diagram-type", + default="Voronoi", + dest="diagramType", + choices=["Voronoi", "Delaunay", "Both"], + help="Defines the type of the diagram", + ) + pars.add_argument( + "--clip-box", + choices=["Page", "Automatic from seeds"], + default="Page", + dest="clip_box", + help="Defines the bounding box of the Voronoi diagram", + ) + pars.add_argument( + "--show-clip-box", + type=inkex.Boolean, + default=False, + dest="showClipBox", + help="Set this to true to write the bounding box", + ) + pars.add_argument( + "--delaunay-fill-options", + default="delaunay-no-fill", + dest="delaunayFillOptions", + help="Set the Delaunay triangles color options", + ) + + def dot(self, x, y): + """Clipping a line by a bounding box""" + return x[0] * y[0] + x[1] * y[1] + + def intersect_line_segment(self, line, vt1, vt2): + """Get the line intersection of the two verticies""" + sc1 = self.dot(line, vt1) - line[2] + sc2 = self.dot(line, vt2) - line[2] + if sc1 * sc2 > 0: + return 0, 0, False + + tmp = self.dot(line, vt1) - self.dot(line, vt2) + if tmp == 0: + return 0, 0, False + und = (line[2] - self.dot(line, vt2)) / tmp + vt0 = 1 - und + return und * vt1[0] + vt0 * vt2[0], und * vt1[1] + vt0 * vt2[1], True + + def clip_edge(self, vertices, lines, edge, bbox): + # bounding box corners + bbc = [ + (bbox[0], bbox[2]), + (bbox[1], bbox[2]), + (bbox[1], bbox[3]), + (bbox[0], bbox[3]), + ] + + # record intersections of the line with bounding box edges + if edge[0] >= len(lines): + return [] + line = lines[edge[0]] + interpoints = [] + for i in range(4): + pnt = self.intersect_line_segment(line, bbc[i], bbc[(i + 1) % 4]) + if pnt[2]: + interpoints.append(pnt) + + # if the edge has no intersection, return empty intersection + if len(interpoints) < 2: + return [] + + if len(interpoints) > 2: # happens when the edge crosses the corner of the box + interpoints = list(set(interpoints)) # remove doubles + + # points of the edge + vt1 = vertices[edge[1]] + interpoints.append((vt1[0], vt1[1], False)) + vt2 = vertices[edge[2]] + interpoints.append((vt2[0], vt2[1], False)) + + # sorting the points in the widest range to get them in order on the line + minx = interpoints[0][0] + miny = interpoints[0][1] + maxx = interpoints[0][0] + maxy = interpoints[0][1] + for point in interpoints: + minx = min(point[0], minx) + maxx = max(point[0], maxx) + miny = min(point[1], miny) + maxy = max(point[1], maxy) + + if (maxx - minx) > (maxy - miny): + interpoints.sort() + else: + interpoints.sort(key=lambda pt: pt[1]) + + start = [] + inside = False # true when the part of the line studied is in the clip box + start_write = False # true when the part of the line is in the edge segment + for point in interpoints: + if point[2]: # The point is a bounding box intersection + if inside: + if start_write: + return [[start[0], start[1]], [point[0], point[1]]] + return [] + else: + if start_write: + start = point + inside = not inside + else: # The point is a segment endpoint + if start_write: + if inside: + # a vertex ends the line inside the bounding box + return [[start[0], start[1]], [point[0], point[1]]] + return [] + else: + if inside: + start = point + start_write = not start_write + + def effect(self): + # Check that elements have been selected + if not self.svg.selection: + inkex.errormsg(_("Please select objects!")) + return + + linestyle = { + "stroke": "#000000", + "stroke-width": str(self.svg.to_dimensionless("1px")), + "fill": "none", + "stroke-linecap": "round", + "stroke-linejoin": "round", + } + + facestyle = { + "stroke": "#000000", + "stroke-width": str(self.svg.to_dimensionless("1px")), + "fill": "none", + "stroke-linecap": "round", + "stroke-linejoin": "round", + } + + parent_group = self.svg.selection.first().getparent() + trans = parent_group.composed_transform() + + invtrans = None + if trans: + invtrans = -trans + + # Recovery of the selected objects + pts = [] + nodes = [] + seeds = [] + fills = [] + + for node in self.svg.selection.values(): + nodes.append(node) + bbox = node.bounding_box() + if bbox: + center_x, center_y = bbox.center + point = [center_x, center_y] + if trans: + point = trans.apply_to_point(point) + pts.append(Point(*point)) + if self.options.delaunayFillOptions != "delaunay-no-fill": + fills.append(node.style.get("fill", "none")) + seeds.append(Point(center_x, center_y)) + + # Creation of groups to store the result + if self.options.diagramType != "Delaunay": + # Voronoi + group_voronoi = parent_group.add(Group()) + group_voronoi.set("inkscape:label", "Voronoi") + if invtrans: + group_voronoi.transform @= invtrans + if self.options.diagramType != "Voronoi": + # Delaunay + group_delaunay = parent_group.add(Group()) + group_delaunay.set("inkscape:label", "Delaunay") + + # Clipping box handling + if self.options.diagramType != "Delaunay": + # Clipping bounding box creation + group_bbox = sum([node.bounding_box() for node in nodes], None) + + # Clipbox is the box to which the Voronoi diagram is restricted + if self.options.clip_box == "Page": + width = self.svg.viewbox_width + height = self.svg.viewbox_height + clip_box = (0, width, 0, height) + else: + clip_box = ( + group_bbox.left, + group_bbox.right, + group_bbox.top, + group_bbox.bottom, + ) + + # Safebox adds points so that no Voronoi edge in clip_box is infinite + safe_box = ( + 2 * clip_box[0] - clip_box[1], + 2 * clip_box[1] - clip_box[0], + 2 * clip_box[2] - clip_box[3], + 2 * clip_box[3] - clip_box[2], + ) + pts.append(Point(safe_box[0], safe_box[2])) + pts.append(Point(safe_box[1], safe_box[2])) + pts.append(Point(safe_box[1], safe_box[3])) + pts.append(Point(safe_box[0], safe_box[3])) + + if self.options.showClipBox: + # Add the clip box to the drawing + rect = group_voronoi.add(Rectangle()) + rect.set("x", str(clip_box[0])) + rect.set("y", str(clip_box[2])) + rect.set("width", str(clip_box[1] - clip_box[0])) + rect.set("height", str(clip_box[3] - clip_box[2])) + rect.style = linestyle + + # Voronoi diagram generation + if self.options.diagramType != "Delaunay": + vertices, lines, edges = voronoi.computeVoronoiDiagram(pts) + for edge in edges: + vindex1, vindex2 = edge[1:] + if (vindex1 < 0) or (vindex2 < 0): + continue # infinite lines have no need to be handled in the clipped box + else: + segment = self.clip_edge(vertices, lines, edge, clip_box) + # segment = [vertices[vindex1],vertices[vindex2]] # deactivate clipping + if len(segment) > 1: + x1, y1 = segment[0] + x2, y2 = segment[1] + cmds = [["M", [x1, y1]], ["L", [x2, y2]]] + path = group_voronoi.add(PathElement()) + path.set("d", str(inkex.Path(cmds))) + path.style = linestyle + + if self.options.diagramType != "Voronoi": + triangles = voronoi.computeDelaunayTriangulation(seeds) + i = 0 + if self.options.delaunayFillOptions == "delaunay-fill": + random.seed("inkscape") + for triangle in triangles: + pt1 = seeds[triangle[0]] + pt2 = seeds[triangle[1]] + pt3 = seeds[triangle[2]] + cmds = [ + ["M", [pt1.x, pt1.y]], + ["L", [pt2.x, pt2.y]], + ["L", [pt3.x, pt3.y]], + ["Z", []], + ] + if ( + self.options.delaunayFillOptions == "delaunay-fill" + or self.options.delaunayFillOptions == "delaunay-fill-random" + ): + facestyle = { + "stroke": fills[triangle[random.randrange(0, 2)]], + "stroke-width": str(self.svg.to_dimensionless("0.005px")), + "fill": fills[triangle[random.randrange(0, 2)]], + "stroke-linecap": "round", + "stroke-linejoin": "round", + } + path = group_delaunay.add(PathElement()) + path.set("d", str(inkex.Path(cmds))) + path.style = facestyle + i += 1 + + +if __name__ == "__main__": + Voronoi().run() diff --git a/share/extensions/web_interactive_mockup.inx b/share/extensions/web_interactive_mockup.inx new file mode 100644 index 0000000..c00d6e1 --- /dev/null +++ b/share/extensions/web_interactive_mockup.inx @@ -0,0 +1,38 @@ + + + Interactive Mockup + org.inkscape.webdesign.interactive_mockup + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + + diff --git a/share/extensions/web_interactive_mockup.py b/share/extensions/web_interactive_mockup.py new file mode 100755 index 0000000..4827140 --- /dev/null +++ b/share/extensions/web_interactive_mockup.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Copyright (C) 2019 Gemy Cedric Activdesign.eu +# +# 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. +# +import inkwebeffect +import inkex +from inkex.localization import inkex_gettext as _ + + +class InteractiveMockup(inkwebeffect.InkWebEffect): + def add_arguments(self, pars): + pars.add_argument( + "--when", default="onclick", help="Event that will trigger the action" + ) + pars.add_argument("--tab") + + def effect(self): + self.ensureInkWebSupport() + + if len(self.options.ids) < 2: + raise inkex.AbortExtension( + _( + "You must select at least two elements. " + "The last one is the object you want to go to." + ) + ) + + el_from = list(self.svg.selection.values())[:-1] + + ev_code = "InkWeb.moveViewbox({from:this, to:'" + self.options.ids[-1] + "'})" + for elem in el_from: + prev_ev_code = elem.get(self.options.when) + el_ev_code = ev_code + ";" + (prev_ev_code or "") + elem.set(self.options.when, el_ev_code) + + +if __name__ == "__main__": + InteractiveMockup().run() diff --git a/share/extensions/web_set_att.inx b/share/extensions/web_set_att.inx new file mode 100644 index 0000000..4e0176b --- /dev/null +++ b/share/extensions/web_set_att.inx @@ -0,0 +1,50 @@ + + + Set Attributes + org.inkscape.web.set_attribute + + + fill stroke stroke-width + + + + + + + + + + + + + + red black 5px + + + + + + + + + + + + + + + + + + + all + + + + + + + + diff --git a/share/extensions/web_set_att.py b/share/extensions/web_set_att.py new file mode 100755 index 0000000..5b7e8ca --- /dev/null +++ b/share/extensions/web_set_att.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# +""" +This effect adds a feature visible (or usable) only on a SVG enabled web +browser (like Firefox). This effect sets one or more attributes in the second +selected element, when a defined event occurs on the first selected element. +If you want to set more than one attribute, you must separate this with a space, +and only with aspace. +""" + +# local library +import inkex +from inkex.localization import inkex_gettext as _ +import inkwebeffect + + +class SetAttribute(inkwebeffect.InkWebEffect): + """Set a web attribute accross many objects""" + + def add_arguments(self, pars): + pars.add_argument("--tab", help="The selected UI-tab when OK was pressed") + pars.add_argument( + "--att", default="fill stroke stroke-width", help="Attribute to set." + ) + pars.add_argument("--val", default="red black 5px", help="Values to set.") + pars.add_argument("--when", default="onclick", help="When it must to set?") + pars.add_argument("--from-and-to", dest="from_and_to", default="g-to-one") + pars.add_argument( + "--compatibility", + default="append", + help="Compatibility with previews code to this event.", + ) + + def effect(self): + self.ensureInkWebSupport() + + if len(self.options.ids) < 2: + raise inkex.AbortExtension(_("You must select at least two elements.")) + + # All set the last else The first set all + split = -1 if self.options.from_and_to == "g-to-one" else 1 + el_from = list(self.svg.selection.values())[:split] + id_to = list(self.svg.selection.ids)[split:] + + ev_code = "InkWeb.setAtt({{el:['{}'], att:'{}', val:'{}'}})".format( + "','".join(id_to), self.options.att, self.options.val + ) + for elem in el_from: + prev_ev_code = elem.get(self.options.when) + if prev_ev_code is None: + prev_ev_code = "" + + if self.options.compatibility == "append": + el_ev_code = prev_ev_code + ";\n" + ev_code + if self.options.compatibility == "prepend": + el_ev_code = ev_code + ";\n" + prev_ev_code + if self.options.compatibility == "replace": + el_ev_code = ev_code + + elem.set(self.options.when, el_ev_code) + + +if __name__ == "__main__": + SetAttribute().run() diff --git a/share/extensions/web_transmit_att.inx b/share/extensions/web_transmit_att.inx new file mode 100644 index 0000000..3eeef48 --- /dev/null +++ b/share/extensions/web_transmit_att.inx @@ -0,0 +1,48 @@ + + + Transmit Attributes + org.inkscape.web.transmit_attribute + + + fill + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + diff --git a/share/extensions/web_transmit_att.py b/share/extensions/web_transmit_att.py new file mode 100755 index 0000000..922739a --- /dev/null +++ b/share/extensions/web_transmit_att.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright (C) 2009 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# + +import inkex +from inkex.localization import inkex_gettext as _ + +import inkwebeffect + + +class TransmitAttribute(inkwebeffect.InkWebEffect): + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--att", default="fill", help="Attribute to transmitted.") + pars.add_argument("--when", default="onclick", help="When it must to transmit?") + pars.add_argument("--from-and-to", dest="from_and_to", default="g-to-one") + pars.add_argument( + "--compatibility", + default="append", + help="Compatibility with previews code to this event.", + ) + + def effect(self): + self.ensureInkWebSupport() + + if len(self.options.ids) < 2: + raise inkex.AbortExtension(_("You must select at least two elements.")) + + # All set the last else The first set all + split = -1 if self.options.from_and_to == "g-to-one" else 1 + el_from = list(self.svg.selection)[:split] + id_to = list(self.svg.selection.ids)[split:] + + ev_code = "InkWeb.transmitAtt({{from:this, to:['{}'], att:'{}'}})".format( + "','".join(id_to), self.options.att + ) + for elem in el_from: + prev_ev_code = elem.get(self.options.when, "") + if self.options.compatibility == "append": + el_ev_code = prev_ev_code + ";\n" + ev_code + if self.options.compatibility == "prepend": + el_ev_code = ev_code + ";\n" + prev_ev_code + if self.options.compatibility == "replace": + el_ev_code = ev_code + elem.set(self.options.when, el_ev_code) + + +if __name__ == "__main__": + TransmitAttribute().run() diff --git a/share/extensions/webslicer_create_group.inx b/share/extensions/webslicer_create_group.inx new file mode 100644 index 0000000..33053fb --- /dev/null +++ b/share/extensions/webslicer_create_group.inx @@ -0,0 +1,37 @@ + + + Set a layout group + org.inkscape.web.slicer.create_group + webslicer_effect.py + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + diff --git a/share/extensions/webslicer_create_group.py b/share/extensions/webslicer_create_group.py new file mode 100755 index 0000000..1322b9f --- /dev/null +++ b/share/extensions/webslicer_create_group.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright (C) 2010 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# +"""Create webslicer group""" + +import inkex +from inkex.localization import inkex_gettext as _ +from webslicer_effect import WebSlicerMixin + + +class CreateGroup(WebSlicerMixin, inkex.EffectExtension): + """Create new webslicer group""" + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--html-id", dest="html_id") + pars.add_argument("--html-class", dest="html_class") + pars.add_argument("--width-unity", dest="width_unity") + pars.add_argument("--height-unity", dest="height_unity") + pars.add_argument("--bg-color", dest="bg_color") + + def effect(self): + if not self.svg.selection: + raise inkex.AbortExtension( + _( + 'You must to select some "Slicer rectangles" ' + 'or other "Layout groups".' + ) + ) + + base_elements = self.get_slicer_layer().descendants() + for key, node in self.svg.selection.id_dict().items(): + if node not in base_elements: + raise inkex.AbortExtension( + _(f'The element "{key}" is not in the Web Slicer layer') + ) + g_parent = node.getparent() + + group = g_parent.add(inkex.Group()) + desc = group.add(inkex.Desc()) + desc.text = self.get_conf_text_from_list( + ["html_id", "html_class", "width_unity", "height_unity", "bg_color"] + ) + + for node in self.svg.selection.values(): + group.insert(1, node) + + +if __name__ == "__main__": + CreateGroup().run() diff --git a/share/extensions/webslicer_create_rect.inx b/share/extensions/webslicer_create_rect.inx new file mode 100644 index 0000000..1a2c99c --- /dev/null +++ b/share/extensions/webslicer_create_rect.inx @@ -0,0 +1,71 @@ + + + Create a slicer rectangle + org.inkscape.web.slicer.create_rect + webslicer_effect.py + + + + + + + 96 + + + + + + + + + 85 + + + + + + + + + 256 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + diff --git a/share/extensions/webslicer_create_rect.py b/share/extensions/webslicer_create_rect.py new file mode 100755 index 0000000..c92a554 --- /dev/null +++ b/share/extensions/webslicer_create_rect.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# +# Copyright (C) 2010 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# + +from lxml import etree + +import inkex +from webslicer_effect import WebSlicerMixin, is_empty + + +class CreateRect(WebSlicerMixin, inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument("--name") + pars.add_argument("--format", default="png") + pars.add_argument("--dpi", type=float) + pars.add_argument("--dimension") + pars.add_argument("--bg-color") + pars.add_argument("--quality", type=int) + pars.add_argument("--gif-type") + pars.add_argument("--palette-size", type=int) + pars.add_argument("--html-id") + pars.add_argument("--html-class") + pars.add_argument("--layout-disposition") + pars.add_argument("--layout-position-anchor") + # inkscape param workaround + pars.add_argument("--tab") + + def unique_slice_name(self): + name = self.options.name + el = self.svg.xpath('//*[@id="' + name + '"]') + if len(el) > 0: + if name[-3:] == "-00": + name = name[:-3] + num = 0 + num_s = "00" + while len(el) > 0: + num += 1 + num_s = str(num) + if len(num_s) == 1: + num_s = "0" + num_s + el = self.svg.xpath('//*[@id="' + name + "-" + num_s + '"]') + self.options.name = name + "-" + num_s + + def validate_options(self): + self.options.format = self.options.format.lower() + if not is_empty(self.options.dimension): + self.options.dimension + + def effect(self): + scale = self.svg.unittouu("1px") # convert to document units + self.validate_options() + layer = self.get_slicer_layer(True) + # TODO: get selected elements to define location and size + rect = etree.SubElement(layer, "rect") + if is_empty(self.options.name): + self.options.name = "slice-00" + self.unique_slice_name() + rect.set("id", self.options.name) + rect.set("fill", "red") + rect.set("opacity", "0.5") + rect.set("x", str(-scale * 100)) + rect.set("y", str(-scale * 100)) + rect.set("width", str(scale * 200)) + rect.set("height", str(scale * 200)) + desc = etree.SubElement(rect, "desc") + conf_txt = "format:" + self.options.format + "\n" + if not is_empty(self.options.dpi): + conf_txt += "dpi:" + str(self.options.dpi) + "\n" + if not is_empty(self.options.html_id): + conf_txt += "html-id:" + self.options.html_id + desc.text = self.get_conf_text_from_list(self.get_conf_list()) + + def get_conf_list(self): + conf_list = ["format"] + if self.options.format == "gif": + conf_list.extend(["gif_type", "palette_size"]) + if self.options.format == "jpg": + conf_list.extend(["quality"]) + conf_list.extend( + [ + "dpi", + "dimension", + "bg_color", + "html_id", + "html_class", + "layout_disposition", + "layout_position_anchor", + ] + ) + return conf_list + + +if __name__ == "__main__": + CreateRect().run() diff --git a/share/extensions/webslicer_effect.py b/share/extensions/webslicer_effect.py new file mode 100755 index 0000000..ae59d72 --- /dev/null +++ b/share/extensions/webslicer_effect.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright (C) 2010 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# +""" +Common elements between webslicer extensions +""" + +import inkex +from inkex import Group + + +def is_empty(val): + return val in ("", None) + + +class WebSlicerMixin(object): + def get_slicer_layer(self, force_creation=False): + # Test if webslicer-layer layer existis + layer = self.svg.getElement( + '//*[@id="webslicer-layer" and @inkscape:groupmode="layer"]' + ) + if layer is None: + if force_creation: + # Create a new layer + layer = Group(id="webslicer-layer") + layer.set("inkscape:label", "Web Slicer") + layer.set("inkscape:groupmode", "layer") + self.document.getroot().append(layer) + else: + layer = None + return layer + + def get_conf_text_from_list(self, conf_atts): + conf_list = [] + for att in conf_atts: + if not is_empty(getattr(self.options, att)): + conf_list.append( + att.replace("_", "-") + ": " + str(getattr(self.options, att)) + ) + return "\n".join(conf_list) diff --git a/share/extensions/webslicer_export.inx b/share/extensions/webslicer_export.inx new file mode 100644 index 0000000..53ab683 --- /dev/null +++ b/share/extensions/webslicer_export.inx @@ -0,0 +1,27 @@ + + + Export layout pieces and HTML+CSS code + org.inkscape.web.slicer.export + webslicer_effect.py + + + + false + true + + + + + + + all + + + + + + + + diff --git a/share/extensions/webslicer_export.py b/share/extensions/webslicer_export.py new file mode 100755 index 0000000..0bc65d6 --- /dev/null +++ b/share/extensions/webslicer_export.py @@ -0,0 +1,470 @@ +#!/usr/bin/env python +# +# Copyright (C) 2010 Aurelio A. Heckert, aurium (a) gmail dot com +# +# 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. +# +import subprocess +import os +import sys +import tempfile + +from lxml import etree + +import inkex +from inkex.localization import inkex_gettext as _ +from webslicer_effect import WebSlicerMixin, is_empty + + +class Export(WebSlicerMixin, inkex.OutputExtension): + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--dir") + pars.add_argument("--create-dir", type=inkex.Boolean, dest="create_dir") + pars.add_argument("--with-code", type=inkex.Boolean, dest="with_code") + + svgNS = "{http://www.w3.org/2000/svg}" + + def validate_inputs(self): + # The user must supply a directory to export: + if is_empty(self.options.dir): + raise inkex.AbortExtension( + _("You must give a directory to export the slices.") + ) + # No directory separator at the path end: + if self.options.dir[-1] == "/" or self.options.dir[-1] == "\\": + self.options.dir = self.options.dir[0:-1] + # Test if the directory exists: + if not os.path.exists(self.options.dir): + if self.options.create_dir: + # Try to create it: + try: + os.makedirs(self.options.dir) + except Exception as e: + raise inkex.AbortExtension( + _("Can't create '{}': {}.".format(self.options.dir, e)) + ) + else: + raise inkex.AbortExtension( + _("Dir doesn't exist '{}'.".format(self.options.dir)) + ) + # Check whether slicer layer exists (bug #1198826) + slicer_layer = self.get_slicer_layer() + if slicer_layer is None: + raise inkex.AbortExtension(_("No slicer layer found.")) + else: + self.unique_html_id(slicer_layer) + return None + + def get_cmd_output(self, cmd): + try: + pipe = subprocess.Popen(cmd) + except FileNotFoundError: + return 1, "" + stdout, _ = pipe.communicate() + sts = pipe.returncode + if sts is None: + sts = 0 + if stdout is not None and stdout[-1:] == "\n": + stdout = stdout[:-1] + return sts, stdout + + _html_ids = [] + + def unique_html_id(self, el): + for child in el.getchildren(): + if child.tag in [ + self.svgNS + "rect", + self.svgNS + "path", + self.svgNS + "circle", + self.svgNS + "g", + ]: + conf = self.get_el_conf(child) + if conf["html-id"] in self._html_ids: + inkex.errormsg( + 'You have more than one element with "{}" html-id.'.format( + conf["html-id"] + ) + ) + n = 2 + while (conf["html-id"] + "-" + str(n)) in self._html_ids: + n += 1 + conf["html-id"] += "-" + str(n) + self._html_ids.append(conf["html-id"]) + self.save_conf(conf, child) + self.unique_html_id(child) + + def test_if_has_imagemagick(self): + (status, output) = self.get_cmd_output("convert --version") + self.has_magick = status == 0 and "ImageMagick" in output + + def save(self, stream): + self.test_if_has_imagemagick() + error = self.validate_inputs() + if error: + return error + # Register the basic CSS code: + self.reg_css("body", "text-align", "center") + # Create the temporary SVG with invisible Slicer layer to export image pieces + self.create_the_temporary_svg() + # Start what we really want! + self.export_chids_of(self.get_slicer_layer()) + # Write the HTML and CSS files if asked for: + if self.options.with_code: + self.make_html_file() + self.make_css_file() + # Delete the temporary SVG with invisible Slicer layer + self.delete_the_temporary_svg() + # TODO: prevent inkex to return svg code to update Inkscape + + def make_html_file(self): + f = open(os.path.join(self.options.dir, "layout.html"), "w") + f.write( + "\n\n" + + " Web Layout Testing\n" + + ' \n" + + "\n\n" + + self.html_code() + + '

\n' + + " This HTML code is not done to the web.
\n" + + " The automatic HTML and CSS code are only a helper." + + "

\n\n" + ) + f.close() + + def make_css_file(self): + f = open(os.path.join(self.options.dir, "style.css"), "w") + f.write( + "/*\n" + + "** This CSS code is not done to the web.\n" + + "** The automatic HTML and CSS code are only a helper.\n" + + "*/\n" + + self.css_code() + ) + f.close() + + def create_the_temporary_svg(self): + (self.tmp_svg_ref, self.tmp_svg) = tempfile.mkstemp(".svg") + layer = self.get_slicer_layer() + current_style = layer.style + layer.style = "display:none" + self.document.write(self.tmp_svg) + layer.style = current_style + + def delete_the_temporary_svg(self): + try: + os.close(self.tmp_svg_ref) + os.remove(self.tmp_svg) + except (IOError, OSError, PermissionError): + pass + + noid_element_count = 0 + + def get_el_conf(self, el): + desc = el.find(self.svgNS + "desc") + conf = {} + if desc is None: + desc = etree.SubElement(el, "desc") + if desc.text is None: + desc.text = "" + for line in desc.text.split("\n"): + if line.find(":") > 0: + line = line.split(":") + conf[line[0].strip()] = line[1].strip() + if not "html-id" in conf: + if el == self.get_slicer_layer(): + return {"html-id": "#body#"} + else: + self.noid_element_count += 1 + conf["html-id"] = "element-" + str(self.noid_element_count) + desc.text += "\nhtml-id:" + conf["html-id"] + return conf + + def save_conf(self, conf, el): + desc = el.find("{http://www.w3.org/2000/svg}desc") + if desc is not None: + conf_a = [] + for k in conf: + conf_a.append(k + " : " + conf[k]) + desc.text = "\n".join(conf_a) + + def export_chids_of(self, parent): + parent_id = self.get_el_conf(parent)["html-id"] + for el in parent.getchildren(): + el_conf = self.get_el_conf(el) + if el.tag == self.svgNS + "g": + if self.options.with_code: + self.register_group_code(el, el_conf) + else: + self.export_chids_of(el) + if el.tag in [ + self.svgNS + "rect", + self.svgNS + "path", + self.svgNS + "circle", + ]: + if self.options.with_code: + self.register_unity_code(el, el_conf, parent_id) + self.export_img(el, el_conf) + + def register_group_code(self, group, conf): + self.reg_html("div", group) + selec = "#" + conf["html-id"] + self.reg_css(selec, "position", "absolute") + geometry = self.get_relative_el_geometry(group) + self.reg_css(selec, "top", str(int(geometry["y"])) + "px") + self.reg_css(selec, "left", str(int(geometry["x"])) + "px") + self.reg_css(selec, "width", str(int(geometry["w"])) + "px") + self.reg_css(selec, "height", str(int(geometry["h"])) + "px") + self.export_chids_of(group) + + def __validate_slice_conf(self, conf): + if not "layout-disposition" in conf: + conf["layout-disposition"] = "bg-el-norepeat" + if not "layout-position-anchor" in conf: + conf["layout-position-anchor"] = "mc" + return conf + + def register_unity_code(self, el, conf, parent_id): + conf = self.__validate_slice_conf(conf) + css_selector = "#" + conf["html-id"] + bg_repeat = "no-repeat" + img_name = self.img_name(el, conf) + if conf["layout-disposition"][0:2] == "bg": + if conf["layout-disposition"][0:9] == "bg-parent": + if parent_id == "#body#": + css_selector = "body" + else: + css_selector = "#" + parent_id + if conf["layout-disposition"] == "bg-parent-repeat": + bg_repeat = "repeat" + if conf["layout-disposition"] == "bg-parent-repeat-x": + bg_repeat = "repeat-x" + if conf["layout-disposition"] == "bg-parent-repeat-y": + bg_repeat = "repeat-y" + lay_anchor = conf["layout-position-anchor"] + if lay_anchor == "tl": + lay_anchor = "top left" + if lay_anchor == "tc": + lay_anchor = "top center" + if lay_anchor == "tr": + lay_anchor = "top right" + if lay_anchor == "ml": + lay_anchor = "middle left" + if lay_anchor == "mc": + lay_anchor = "middle center" + if lay_anchor == "mr": + lay_anchor = "middle right" + if lay_anchor == "bl": + lay_anchor = "bottom left" + if lay_anchor == "bc": + lay_anchor = "bottom center" + if lay_anchor == "br": + lay_anchor = "bottom right" + self.reg_css( + css_selector, + "background", + 'url("{}") {} {}'.format(img_name, bg_repeat, lay_anchor), + ) + else: # conf['layout-disposition'][0:9] == 'bg-el...' + self.reg_html("div", el) + self.reg_css( + css_selector, + "background", + 'url("{}") {}'.format(img_name, "no-repeat"), + ) + self.reg_css(css_selector, "position", "absolute") + geo = self.get_relative_el_geometry(el, True) + self.reg_css(css_selector, "top", geo["y"]) + self.reg_css(css_selector, "left", geo["x"]) + self.reg_css(css_selector, "width", geo["w"]) + self.reg_css(css_selector, "height", geo["h"]) + else: # conf['layout-disposition'] == 'img...' + self.reg_html("img", el) + if conf["layout-disposition"] == "img-pos": + self.reg_css(css_selector, "position", "absolute") + geo = self.get_relative_el_geometry(el) + self.reg_css(css_selector, "left", str(geo["x"]) + "px") + self.reg_css(css_selector, "top", str(geo["y"]) + "px") + if conf["layout-disposition"] == "img-float-left": + self.reg_css(css_selector, "float", "right") + if conf["layout-disposition"] == "img-float-right": + self.reg_css(css_selector, "float", "right") + + el_geo = {} + + def register_all_els_geometry(self): + ink_cmm = "inkscape --query-all " + self.tmp_svg + (status, output) = self.get_cmd_output(ink_cmm) + self.el_geo = {} + if status == 0: + for el in output.split("\n"): + el = el.split(",") + if len(el) == 5: + self.el_geo[el[0]] = { + "x": float(el[1]), + "y": float(el[2]), + "w": float(el[3]), + "h": float(el[4]), + } + doc_w = self.svg.unittouu(self.document.getroot().get("width")) + doc_h = self.svg.unittouu(self.document.getroot().get("height")) + self.el_geo["webslicer-layer"] = {"x": 0, "y": 0, "w": doc_w, "h": doc_h} + + def get_relative_el_geometry(self, el, value_to_css=False): + # This method return a dictionary with x, y, w and h keys. + # All values are float, if value_to_css is False, otherwise + # that is a string ended with "px". The x and y values are + # relative to parent position. + if not self.el_geo: + self.register_all_els_geometry() + parent = el.getparent() + geometry = self.el_geo[el.attrib["id"]] + geometry["x"] -= self.el_geo[parent.attrib["id"]]["x"] + geometry["y"] -= self.el_geo[parent.attrib["id"]]["y"] + if value_to_css: + for k in geometry: + geometry[k] = str(int(geometry[k])) + "px" + return geometry + + def img_name(self, el, conf): + return el.attrib["id"] + "." + conf["format"] + + def export_img(self, el, conf): + if not self.has_magick: + inkex.errormsg(_("You must install the ImageMagick to get JPG and GIF.")) + conf["format"] = "png" + img_name = os.path.join(self.options.dir, self.img_name(el, conf)) + img_name_png = img_name + if conf["format"] != "png": + img_name_png = img_name + ".png" + opts = "" + if "bg-color" in conf: + opts += ' -b "' + conf["bg-color"] + '" -y 1' + if "dpi" in conf: + opts += " -d " + conf["dpi"] + if "dimension" in conf: + dim = conf["dimension"].split("x") + opts += " -w " + dim[0] + " -h " + dim[1] + (status, output) = self.get_cmd_output( + 'inkscape {} -i "{}" -o "{}" "{}"'.format( + opts, el.attrib["id"], img_name_png, self.tmp_svg + ) + ) + if conf["format"] != "png": + opts = "" + if conf["format"] == "jpg": + opts += " -quality " + str(conf["quality"]) + if conf["format"] == "gif": + if conf["gif-type"] == "grayscale": + opts += " -type Grayscale" + else: + opts += " -type Palette" + if conf["palette-size"] < 256: + opts += " -colors " + str(conf["palette-size"]) + (status, output) = self.get_cmd_output( + 'convert "{}" {} "{}"'.format(img_name_png, opts, img_name) + ) + if status != 0: + inkex.errormsg("Upss... ImageMagick error: " + output) + os.remove(img_name_png) + + _html = {} + + def reg_html(self, el_tag, el): + parent = el.getparent() + parent_id = self.get_el_conf(parent)["html-id"] + if parent == self.get_slicer_layer(): + parent_id = "body" + conf = self.get_el_conf(el) + el_id = conf["html-id"] + if "html-class" in conf: + el_class = conf["html-class"] + else: + el_class = "" + if not parent_id in self._html: + self._html[parent_id] = [] + self._html[parent_id].append({"tag": el_tag, "id": el_id, "class": el_class}) + + def html_code(self, parent="body", ident=" "): + # inkex.errormsg( self._html ) + if not parent in self._html: + return "" + code = "" + for el in self._html[parent]: + child_code = self.html_code(el["id"], ident + " ") + tag_class = "" + if el["class"] != "": + tag_class = ' class="' + el["class"] + '"' + if el["tag"] == "img": + code += ( + ident + + '\n' + ) + else: + code += ( + ident + + "<" + + el["tag"] + + ' id="' + + el["id"] + + '"' + + tag_class + + ">\n" + ) + if child_code: + code += child_code + else: + code += ident + " Element " + el["id"] + "\n" + code += ident + "\n' + return code + + _css = [] + + def reg_css(self, selector, att, val): + pos = i = -1 + for s in self._css: + i += 1 + if s["selector"] == selector: + pos = i + if pos == -1: + pos = i + 1 + self._css.append({"selector": selector, "atts": {}}) + if not att in self._css[pos]["atts"]: + self._css[pos]["atts"][att] = [] + self._css[pos]["atts"][att].append(val) + + def css_code(self): + code = "" + for s in self._css: + code += "\n" + s["selector"] + " {\n" + for att in s["atts"]: + val = s["atts"][att] + if att == "background" and len(val) > 1: + code += " /* the next attribute needs a CSS3 enabled browser */\n" + code += " " + att + ": " + (", ".join(val)) + ";\n" + code += "}\n" + return code + + +if __name__ == "__main__": + Export().run() diff --git a/share/extensions/whirl.inx b/share/extensions/whirl.inx new file mode 100644 index 0000000..3ce9b07 --- /dev/null +++ b/share/extensions/whirl.inx @@ -0,0 +1,16 @@ + + + Whirl + org.ekips.filter.whirl + 5.0 + true + + path + + + + + + diff --git a/share/extensions/whirl.py b/share/extensions/whirl.py new file mode 100755 index 0000000..f347f61 --- /dev/null +++ b/share/extensions/whirl.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Aaron Spike, aaron@ekips.org +# +# 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. +# +"""Whirl path extension (modify path)""" + +import math +import inkex + + +class Whirl(inkex.EffectExtension): + """Modify a path by twisting the nodes around a point""" + + def add_arguments(self, pars): + pars.add_argument( + "-t", "--whirl", type=float, default=5.0, help="amount of whirl" + ) + pars.add_argument( + "-r", + "--rotation", + type=inkex.Boolean, + default=True, + help="direction of rotation", + ) + + def effect(self): + view_center = self.svg.namedview.center + rotation = 1 if self.options.rotation else -1 + whirl = self.options.whirl / 1000 + for node in self.svg.selection.filter(inkex.PathElement): + self.whirl_node(view_center, rotation, whirl, node) + + @staticmethod + def whirl_node(center, direction, ammount, node): + """Apply a whirl to a path given the center, direction and amount""" + path = node.path.to_superpath() + for sub in path: + for csp in sub: + for point in csp: + point[0] -= center[0] + point[1] -= center[1] + dist = math.sqrt((point[0] ** 2) + (point[1] ** 2)) + if dist != 0: + art = direction * dist * ammount + theta = math.atan2(point[1], point[0]) + art + point[0] = dist * math.cos(theta) + point[1] = dist * math.sin(theta) + point[0] += center[0] + point[1] += center[1] + node.path = path + + +if __name__ == "__main__": + Whirl().run() diff --git a/share/extensions/wireframe_sphere.inx b/share/extensions/wireframe_sphere.inx new file mode 100644 index 0000000..84561bb --- /dev/null +++ b/share/extensions/wireframe_sphere.inx @@ -0,0 +1,20 @@ + + + Wireframe Sphere + org.inkscape.render.wireframe_sphere + 19 + 24 + 35 + 4 + 100.0 + false + + all + + + + + + diff --git a/share/extensions/wireframe_sphere.py b/share/extensions/wireframe_sphere.py new file mode 100755 index 0000000..d94f092 --- /dev/null +++ b/share/extensions/wireframe_sphere.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2009 John Beard john.j.beard@gmail.com +# +# 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. +# +""" +This extension renders a wireframe sphere constructed from lines of latitude +and lines of longitude. + +The number of lines of latitude and longitude is independently variable. Lines +of latitude and longtude are in separate subgroups. The whole figure is also in +its own group. + +The whole sphere can be tilted towards or away from the veiwer by a given +number of degrees. If the whole sphere is then rotated normally in Inkscape, +any position can be achieved. + +There is an option to hide the lines at the back of the sphere, as if the +sphere were opaque. +""" +# FIXME: Lines of latitude only have an approximation of the function needed +# to hide the back portion. If you can derive the proper equation, +# please add it in. +# Line of longitude have the exact method already. +# Workaround: Use the Inkscape ellipse tool to edit the start and end +# points of the lines of latitude to end at the horizon circle. +# +# TODO: Add support for odd numbers of lines of longitude. This means breaking +# the line at the poles, and having two half ellipses for each line. +# The angles at which the ellipse arcs pass the poles are not constant and +# need to be derived before this can be implemented. +# TODO: Add support for prolate and oblate spheroids +# +# 0.10 2009-10-25 First version. Basic spheres supported. +# Hidden lines of latitude still not properly calculated. +# Prolate and oblate spheroids not considered. + +from math import acos, atan, cos, pi, sin, tan + +import inkex +from inkex.localization import inkex_gettext as _ + +# add a tiny value to the ellipse radii, so that if we get a +# zero radius, the ellipse still shows up as a line +EPSILON = 0.001 + + +class WireframeSphere(inkex.GenerateExtension): + """Writeframe extension, generate a wireframe""" + + container_label = "WireframeSphere" + + def container_transform(self): + transform = super(WireframeSphere, self).container_transform() + if self.options.TILT < 0: + transform *= inkex.Transform(scale=(1, -1)) + return transform + + def add_arguments(self, pars): + pars.add_argument("--num_lat", type=int, dest="NUM_LAT", default=19) + pars.add_argument("--num_long", type=int, dest="NUM_LONG", default=24) + pars.add_argument("--radius", type=float, dest="RADIUS", default=100.0) + pars.add_argument("--tilt", type=float, dest="TILT", default=35.0) + pars.add_argument("--rotation", type=float, dest="ROT_OFFSET", default=4) + pars.add_argument( + "--hide_back", type=inkex.Boolean, dest="HIDE_BACK", default=False + ) + + def generate(self): + opt = self.options + + # PARAMETER PROCESSING + if opt.NUM_LONG % 2 != 0: # lines of longitude are odd : abort + inkex.errormsg(_("Please enter an even number of lines of longitude.")) + return + + radius = self.svg.unittouu(str(opt.RADIUS) + "px") + tilt = abs(opt.TILT) * (pi / 180) # Convert to radians + rotate = opt.ROT_OFFSET * pi / 180 # Convert to radians + + # only process longitudes if we actually want some + if opt.NUM_LONG > 0: + # Yieled elements are added to generated container + yield self.longitude_lines(opt.NUM_LONG, tilt, radius, rotate) + + if opt.NUM_LAT > 0: + # Yieled elements are added to generated container + # Account for the fact that we loop over N-1 elements + yield self.latitude_lines(opt.NUM_LAT + 1, tilt, radius) + + # THE HORIZON CIRCLE - circle, centred on the sphere centre + yield self.draw_ellipse((radius, radius), (0, 0)) + + def longitude_lines(self, number, tilt, radius, rotate): + """Add lines of latitude as a group""" + # GROUP FOR THE LINES OF LONGITUDE + grp_long = inkex.Group() + grp_long.set("inkscape:label", "Lines of Longitude") + + # angle between neighbouring lines of longitude in degrees + # delta_long = 360.0 / number + + for i in range(0, number // 2): + # The longitude of this particular line in radians + long_angle = rotate + (i * (360.0 / number)) * (pi / 180.0) + if long_angle > pi: + long_angle -= 2 * pi + # the rise is scaled by the sine of the tilt + # length = sqrt(width*width+height*height) #by pythagorean theorem + # inverse = sin(acos(length/so.RADIUS)) + inverse = abs(sin(long_angle)) * cos(tilt) + + rads = (radius * inverse + EPSILON, radius) + + # The rotation of the ellipse to get it to pass through the pole (degs) + rotation = atan( + (radius * sin(long_angle) * sin(tilt)) / (radius * cos(long_angle)) + ) * (180.0 / pi) + + # remove the hidden side of the ellipses if required + # this is always exactly half the ellipse, but we need to find out which half + start_end = (0, 2 * pi) # Default start and end angles -> full ellipse + if self.options.HIDE_BACK: + if long_angle <= pi / 2: # cut out the half ellispse that is hidden + start_end = (pi / 2, 3 * pi / 2) + else: + start_end = (3 * pi / 2, pi / 2) + + # finally, draw the line of longitude + # the centre is always at the centre of the sphere + elem = grp_long.add(self.draw_ellipse(rads, (0, 0), start_end)) + # the rotation will be applied about the group centre (the centre of the sphere) + elem.transform = inkex.Transform(rotate=(rotation,)) + return grp_long + + def latitude_lines(self, number, tilt, radius): + """Add lines of latitude as a group""" + # GROUP FOR THE LINES OF LATITUDE + grp_lat = inkex.Group() + grp_lat.set("inkscape:label", "Lines of Latitude") + + # Angle between the line of latitude (subtended at the centre) + delta_lat = 180.0 / number + + for i in range(1, number): + # The angle of this line of latitude (from a pole) + lat_angle = (delta_lat * i) * (pi / 180) + + # The width of the LoLat (no change due to projection) + # The projected height of the line of latitude + rads = ( + radius * sin(lat_angle), # major + (radius * sin(lat_angle) * sin(tilt)) + EPSILON, # minor + ) + + # The x position is the sphere center, The projected y position of the LoLat + pos = (0, radius * cos(lat_angle) * cos(tilt)) + + if self.options.HIDE_BACK: + if lat_angle > tilt: # this LoLat is partially or fully visible + if lat_angle > pi - tilt: # this LoLat is fully visible + grp_lat.add(self.draw_ellipse(rads, pos)) + else: # this LoLat is partially visible + proportion = ( + -(acos(tan(lat_angle - pi / 2) / tan(pi / 2 - tilt))) / pi + + 1 + ) + # make the start and end angles (mirror image around pi/2) + start_end = (pi / 2 - proportion * pi, pi / 2 + proportion * pi) + grp_lat.add(self.draw_ellipse(rads, pos, start_end)) + + else: # just draw the full lines of latitude + grp_lat.add(self.draw_ellipse(rads, pos)) + return grp_lat + + def draw_ellipse(self, r_xy, c_xy, start_end=(0, 2 * pi)): + """Creates an elipse with all the required sodipodi attributes""" + path = inkex.PathElement.arc( + c_xy, + *r_xy, + start=start_end[0], + end=start_end[1], + open="true", + arctype="arc" + ) + path.style = { + "stroke": "#000000", + "stroke-width": str(self.svg.unittouu("1px")), + "fill": "none", + } + return path + + +if __name__ == "__main__": + WireframeSphere().run() diff --git a/share/extensions/xaml2svg.inx b/share/extensions/xaml2svg.inx new file mode 100644 index 0000000..f0855b9 --- /dev/null +++ b/share/extensions/xaml2svg.inx @@ -0,0 +1,14 @@ + + + XAML Input + org.inkscape.input.xaml + + .xaml + text/xml+xaml + Microsoft XAML (*.xaml) + Microsoft's GUI definition format + + + xaml2svg.xsl + + diff --git a/share/extensions/xaml2svg.xsl b/share/extensions/xaml2svg.xsl new file mode 100644 index 0000000..8c0e4a5 --- /dev/null +++ b/share/extensions/xaml2svg.xsl @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + visible + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + middle + end + + + + hanging + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/animation.xsl b/share/extensions/xaml2svg/animation.xsl new file mode 100644 index 0000000..e51a430 --- /dev/null +++ b/share/extensions/xaml2svg/animation.xsl @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + remove + freeze + + + + + + + + + + + + + + + x2 + opacity + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/brushes.xsl b/share/extensions/xaml2svg/brushes.xsl new file mode 100644 index 0000000..884d6db --- /dev/null +++ b/share/extensions/xaml2svg/brushes.xsl @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + userSpaceOnUse + + + + + + + boundingBox + + + + + + + userSpaceOnUse + 0 + 0 + + + + + boundingBox + 0 + 0 + 100% + 100% + + + + + + + + userSpaceOnUse + + + + + + + boundingBox + + + + + + + boundingBox + 0 + 0 + 100% + 100% + + + opacity:1 + optimizeSpeed + + + + + + + + + + userSpaceOnUse + + + + + + + boundingBox + + + + + + + userSpaceOnUse + 0 + 0 + + + + + boundingBox + 0 + 0 + 100% + 100% + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/canvas.xsl b/share/extensions/xaml2svg/canvas.xsl new file mode 100644 index 0000000..e67f0e2 --- /dev/null +++ b/share/extensions/xaml2svg/canvas.xsl @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/geometry.xsl b/share/extensions/xaml2svg/geometry.xsl new file mode 100644 index 0000000..c28e6a6 --- /dev/null +++ b/share/extensions/xaml2svg/geometry.xsl @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L + + + + + + + + + + + + + + + + + + + + + + + + + Q + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/properties.xsl b/share/extensions/xaml2svg/properties.xsl new file mode 100644 index 0000000..1cfb8ff --- /dev/null +++ b/share/extensions/xaml2svg/properties.xsl @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/shapes.xsl b/share/extensions/xaml2svg/shapes.xsl new file mode 100644 index 0000000..c28b027 --- /dev/null +++ b/share/extensions/xaml2svg/shapes.xsl @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/extensions/xaml2svg/transform.xsl b/share/extensions/xaml2svg/transform.xsl new file mode 100644 index 0000000..3d41cf4 --- /dev/null +++ b/share/extensions/xaml2svg/transform.xsl @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3