openscad-cpp-evaluator 1.9.0__tar.gz → 1.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/CLAUDE.md +33 -6
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/bindings/module.cpp +63 -3
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/colored_body.hpp +4 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/export.hpp +96 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/zip_stored.hpp +8 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/python/openscad_cpp_evaluator/__init__.py +24 -2
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/colored_body.cpp +7 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/export.cpp +482 -1
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/zip_stored.cpp +10 -0
- openscad_cpp_evaluator-1.11.0/tests/test_export.cpp +735 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_python_bindings.py +84 -0
- openscad_cpp_evaluator-1.9.0/tests/test_export.cpp +0 -260
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.9.0 → openscad_cpp_evaluator-1.11.0}/uv.lock +0 -0
|
@@ -916,8 +916,8 @@ grep for `ponytail:`.
|
|
|
916
916
|
— skip it and the mesh comes out non-manifold at the seam). Self-contained 2D geometry math here
|
|
917
917
|
(`dot2`/`len2`/`norm2`, the parabola-canonical-frame rotation in `discretizeArc`) exists nowhere
|
|
918
918
|
else in this codebase.
|
|
919
|
-
- `include/openscad_cpp_evaluator/export.hpp`, `src/export.cpp` — the writers for all
|
|
920
|
-
formats `exportExtensions()` lists: 3MF, AMF, STL, OBJ, OFF, PLY, VRML, X3D (3MF via
|
|
919
|
+
- `include/openscad_cpp_evaluator/export.hpp`, `src/export.cpp` — the writers for all ten
|
|
920
|
+
formats `exportExtensions()` lists: 3MF, AMF, PDF, STL, OBJ, OFF, PLY, SVG, VRML, X3D (3MF via
|
|
921
921
|
`zip_stored.hpp`'s `writeDeflateZip`). **`exportExtensions()` is the one source of truth for
|
|
922
922
|
which formats exist** — the Python facade and BelfrySCAD's dialog/CLI all ask it rather than
|
|
923
923
|
restating the list, because three hand-written copies had already drifted far enough that `.off`
|
|
@@ -927,11 +927,38 @@ grep for `ponytail:`.
|
|
|
927
927
|
than the face, so an object whose triangles are not all one colour is written as one volume per
|
|
928
928
|
colour — per-triangle `<color>` is legal in the spec but poorly supported by the slicers that are
|
|
929
929
|
the audience for it.
|
|
930
|
+
**`writeSvg` is the one 2D writer**, and the only one that reads `ColoredBody::section` rather
|
|
931
|
+
than `.body`: SVG 1.1, millimetres at 1:1, every contour of a body (holes included) a
|
|
932
|
+
`M .. L .. z` subpath of that body's single `<path>`. Model space is Y-up and SVG's is Y-down, so
|
|
933
|
+
the whole point transform is a Y negation; the page is the bounding box padded by **half the
|
|
934
|
+
stroke width** and rounded outward to whole millimetres, which is why the margin is not a
|
|
935
|
+
constant and why `stroke=false` shrinks the document. Both rules are OpenSCAD's, read from its
|
|
936
|
+
`export_svg.cc` — `ExportSvg.MatchesRealOpenscadByteForByte` pins the output against the real
|
|
937
|
+
binary's, vertex order and 6-vertex line wrap included. A 3D body in the list throws
|
|
938
|
+
("Current top level object is not a 2D object"), as OpenSCAD refuses too: there is no projection
|
|
939
|
+
to fall back on. `ExportOptions::svg` carries OpenSCAD's five `-O export-svg/...` settings.
|
|
940
|
+
**`writePdf` is the other 2D writer**, and shares `collect2d()` with `writeSvg` so the all-2D
|
|
941
|
+
rule and its refusal have one implementation. Everything else differs from SVG: the drawing is
|
|
942
|
+
**centred on a fixed paper size** rather than the page being cut to fit, and **PDF user space is
|
|
943
|
+
Y-up like the model's, so there is NO Y negation** — `pt = mm * 72/25.4` plus a centring offset,
|
|
944
|
+
symmetric in both axes. (OpenSCAD's own file negates Y only because Cairo draws Y-down and then
|
|
945
|
+
flips the whole page; its centring is also a fraction of a point off, because it truncates the
|
|
946
|
+
span to an `int` — a bug, not a spec, so ours centres exactly.) With `showScale` it draws
|
|
947
|
+
OpenSCAD's ruler: two axes at a 30pt margin, ticks every **10mm of model space** (hard-coded —
|
|
948
|
+
`gridSize` drives only the optional grid), labels on every second tick, and the caption telling
|
|
949
|
+
you what to measure. That ruler is the point of the format: it is what lets a printed page reveal
|
|
950
|
+
a printer's scaling error. Text is the **base-14 `/Helvetica`** every reader supplies, so nothing
|
|
951
|
+
is embedded and no font metrics are needed — Cairo's subset-embedded font is a Cairo habit, not a
|
|
952
|
+
PDF requirement, and skipping it is what turned this from a project into a writer. The content
|
|
953
|
+
stream is Flate-compressed through `zip_stored.hpp`'s `zlibCompress` (PDF's `/FlateDecode` *is* a
|
|
954
|
+
zlib stream), falling back to raw when that would not shrink it. `writePdf` returns warnings
|
|
955
|
+
rather than `void`: a model too big for the page is drawn anyway and said so.
|
|
930
956
|
`colored_body.hpp`/`.cpp`'s `toRenderableBodies()` (thin-extrudes any top-level 2D-only result to
|
|
931
|
-
a
|
|
932
|
-
writers — none of them look at `ColoredBody::section` at all, only `.body`.
|
|
933
|
-
|
|
934
|
-
|
|
957
|
+
a 1-unit-tall `flatPreview` Manifold) must run on a body list before handing it to any of the
|
|
958
|
+
MESH writers — none of them look at `ColoredBody::section` at all, only `.body`. Not before
|
|
959
|
+
`writeSvg`, which needs the sections that step throws away, and which says so rather than writing
|
|
960
|
+
the slab's outline. `tools/cli/cli_lib.cpp` is the only current caller; a future GUI/renderer
|
|
961
|
+
caller needs the same call before passing results to its own mesh consumer.
|
|
935
962
|
- `include/openscad_cpp_evaluator/function_builtins.hpp`, `src/builtins/function_builtins.cpp` —
|
|
936
963
|
the math/string/list/type-check builtin *function* dispatch (`isBuiltinFunctionName`/
|
|
937
964
|
`evalBuiltinFunction`), a completely separate namespace/table from `dispatch.hpp`'s builtin
|
|
@@ -356,16 +356,65 @@ struct Geometry {
|
|
|
356
356
|
|
|
357
357
|
// exportModel, with the path/format/warnings marshalling. Releases the GIL:
|
|
358
358
|
// a large export is seconds of Manifold work with no Python involved.
|
|
359
|
+
// The PDF option set is big enough (paper size, orientation, four
|
|
360
|
+
// ruler switches, fill/stroke, four metadata fields) that a dict keyed the
|
|
361
|
+
// way OpenSCAD names its own `-O export-pdf/...` settings is kinder than
|
|
362
|
+
// fourteen keyword arguments. Unknown keys raise rather than being ignored
|
|
363
|
+
// -- a silently dropped "paper-size" would print the wrong page size with
|
|
364
|
+
// nothing to explain it.
|
|
365
|
+
void applyPdfOptions(const nb::dict& d, oscadeval::ExportPdfOptions& pdf) {
|
|
366
|
+
for (auto item : d) {
|
|
367
|
+
const std::string key = nb::cast<std::string>(item.first);
|
|
368
|
+
const nb::handle v = item.second;
|
|
369
|
+
if (key == "paper-size") {
|
|
370
|
+
const std::string name = nb::cast<std::string>(v);
|
|
371
|
+
if (!oscadeval::paperFromName(name, pdf.paper))
|
|
372
|
+
throw std::runtime_error("unknown paper-size '" + name +
|
|
373
|
+
"' (a6, a5, a4, a3, letter, legal, tabloid)");
|
|
374
|
+
} else if (key == "orientation") {
|
|
375
|
+
const std::string name = nb::cast<std::string>(v);
|
|
376
|
+
if (!oscadeval::orientationFromName(name, pdf.orientation))
|
|
377
|
+
throw std::runtime_error("unknown orientation '" + name + "' (portrait, landscape, auto)");
|
|
378
|
+
} else if (key == "show-scale") pdf.showScale = nb::cast<bool>(v);
|
|
379
|
+
else if (key == "show-scale-message") pdf.showScaleMsg = nb::cast<bool>(v);
|
|
380
|
+
else if (key == "show-grid") pdf.showGrid = nb::cast<bool>(v);
|
|
381
|
+
else if (key == "grid-size") pdf.gridSize = nb::cast<double>(v);
|
|
382
|
+
else if (key == "show-filename") pdf.showFilename = nb::cast<bool>(v);
|
|
383
|
+
else if (key == "design-filename") pdf.designFilename = nb::cast<std::string>(v);
|
|
384
|
+
else if (key == "fill") pdf.fill = nb::cast<bool>(v);
|
|
385
|
+
else if (key == "fill-color") pdf.fillColor = nb::cast<std::string>(v);
|
|
386
|
+
else if (key == "stroke") pdf.stroke = nb::cast<bool>(v);
|
|
387
|
+
else if (key == "stroke-color") pdf.strokeColor = nb::cast<std::string>(v);
|
|
388
|
+
else if (key == "stroke-width") pdf.strokeWidth = nb::cast<double>(v);
|
|
389
|
+
else if (key == "add-meta-data") pdf.addMetaData = nb::cast<bool>(v);
|
|
390
|
+
else if (key == "title") pdf.metaTitle = nb::cast<std::string>(v);
|
|
391
|
+
else if (key == "author") pdf.metaAuthor = nb::cast<std::string>(v);
|
|
392
|
+
else if (key == "subject") pdf.metaSubject = nb::cast<std::string>(v);
|
|
393
|
+
else if (key == "keywords") pdf.metaKeywords = nb::cast<std::string>(v);
|
|
394
|
+
else throw std::runtime_error("unknown pdf option '" + key + "'");
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
359
398
|
nb::list exportModelPy(const std::string& path, const Geometry& geom, const std::string& format, bool asciiStl,
|
|
360
|
-
bool stripSlivers, bool splitComponents
|
|
399
|
+
bool stripSlivers, bool splitComponents, bool svgFill, const std::string& svgFillColor,
|
|
400
|
+
bool svgStroke, const std::string& svgStrokeColor, double svgStrokeWidth,
|
|
401
|
+
nb::object pdfOptions) {
|
|
402
|
+
oscadeval::ExportPdfOptions pdf;
|
|
403
|
+
if (!pdfOptions.is_none()) applyPdfOptions(nb::cast<nb::dict>(pdfOptions), pdf);
|
|
361
404
|
std::vector<std::string> warnings;
|
|
362
405
|
{
|
|
363
406
|
nb::gil_scoped_release rel;
|
|
364
407
|
oscadeval::ExportOptions opts;
|
|
408
|
+
opts.pdf = pdf;
|
|
365
409
|
opts.format = format;
|
|
366
410
|
opts.asciiStl = asciiStl;
|
|
367
411
|
opts.stripSlivers = stripSlivers;
|
|
368
412
|
opts.splitComponents = splitComponents;
|
|
413
|
+
opts.svg.fill = svgFill;
|
|
414
|
+
opts.svg.fillColor = svgFillColor;
|
|
415
|
+
opts.svg.stroke = svgStroke;
|
|
416
|
+
opts.svg.strokeColor = svgStrokeColor;
|
|
417
|
+
opts.svg.strokeWidth = svgStrokeWidth;
|
|
369
418
|
warnings = oscadeval::exportModel(path, geom.bodies, opts);
|
|
370
419
|
}
|
|
371
420
|
nb::list out;
|
|
@@ -793,14 +842,25 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
|
793
842
|
|
|
794
843
|
m.def("export_model", &exportModelPy, nb::arg("path"), nb::arg("geometry"), nb::arg("format") = std::string(),
|
|
795
844
|
nb::arg("ascii_stl") = false, nb::arg("strip_slivers") = true,
|
|
796
|
-
nb::arg("split_components") = false,
|
|
845
|
+
nb::arg("split_components") = false, nb::arg("svg_fill") = false,
|
|
846
|
+
nb::arg("svg_fill_color") = std::string("white"), nb::arg("svg_stroke") = true,
|
|
847
|
+
nb::arg("svg_stroke_color") = std::string("black"), nb::arg("svg_stroke_width") = 0.35,
|
|
848
|
+
nb::arg("pdf_options") = nb::none(),
|
|
797
849
|
"Write `geometry` to `path`, format taken from the extension unless `format` says otherwise. "
|
|
798
850
|
"Returns the warnings to surface (open shells, mesh problems, slivers removed) rather than "
|
|
799
851
|
"logging them. Raises RuntimeError when there is no geometry, the format is unknown, or the "
|
|
800
852
|
"file cannot be opened.\n\n"
|
|
801
853
|
"`split_components` gives every disconnected piece its own object in the multi-object formats "
|
|
802
854
|
"(3MF, AMF, OBJ, PLY, VRML, X3D). Off by default, matching OpenSCAD, which writes one object "
|
|
803
|
-
"per colour however many pieces it is in
|
|
855
|
+
"per colour however many pieces it is in.\n\n"
|
|
856
|
+
"The svg_* arguments are OpenSCAD's -O export-svg/... set and apply to .svg only. "
|
|
857
|
+
"svg_stroke/svg_stroke_width also pad the page, so they are not purely cosmetic. An .svg "
|
|
858
|
+
"export needs an all-2D model and raises otherwise, as OpenSCAD does.\n\n"
|
|
859
|
+
"pdf_options is a dict keyed as OpenSCAD names its -O export-pdf/... settings "
|
|
860
|
+
"(paper-size, orientation, show-scale, show-scale-message, show-grid, grid-size, "
|
|
861
|
+
"show-filename, design-filename, fill, fill-color, stroke, stroke-color, stroke-width, "
|
|
862
|
+
"add-meta-data, title, author, subject, keywords). An unknown key raises rather than "
|
|
863
|
+
"being ignored. .pdf is 2D-only too, and centres the drawing on a fixed paper size.");
|
|
804
864
|
|
|
805
865
|
m.def("export_extensions", []() { return oscadeval::exportExtensions(); },
|
|
806
866
|
"The file extensions export_model understands, dot-prefixed. Read from the C++ writer table "
|
|
@@ -16,6 +16,10 @@ enum class BodyRole { Normal, Highlight, Background, ShowOnly };
|
|
|
16
16
|
// A single piece of evaluated geometry: exactly one of `body` (3D) or
|
|
17
17
|
// `section` (2D) is set, never both -- mirrors the Python reference's
|
|
18
18
|
// ColoredBody (body: Optional[Manifold] XOR section: Optional[CrossSection]).
|
|
19
|
+
// ONE exception, and it is deliberate: toRenderableBodies() leaves the
|
|
20
|
+
// `section` in place on the `flatPreview` body it extrudes, so a 2D writer
|
|
21
|
+
// downstream still has the contours. `flatPreview` is the flag that says
|
|
22
|
+
// so; nothing else sets both.
|
|
19
23
|
// `role`/`triColors` are later-phase fields (modifier tagging -- Phase 3;
|
|
20
24
|
// multi-color CSG merges -- Phase 3/8) included now so the struct shape
|
|
21
25
|
// doesn't need reworking when those land.
|
|
@@ -127,6 +127,98 @@ void writeOff(const std::string& path, const std::vector<ColoredBody>& bodies);
|
|
|
127
127
|
// no geometry to export.
|
|
128
128
|
void writeThreeMf(const std::string& path, const std::vector<ExportObject>& objects);
|
|
129
129
|
|
|
130
|
+
// -- 2D ------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
// Options for the SVG writer, named and defaulted after OpenSCAD's own
|
|
133
|
+
// `-O export-svg/...` set. `stroke`/`strokeWidth` are not purely cosmetic:
|
|
134
|
+
// half the stroke width pads the page, so turning the stroke off shrinks
|
|
135
|
+
// the document.
|
|
136
|
+
struct ExportSvgOptions {
|
|
137
|
+
bool fill = false;
|
|
138
|
+
std::string fillColor = "white";
|
|
139
|
+
bool stroke = true;
|
|
140
|
+
std::string strokeColor = "black";
|
|
141
|
+
double strokeWidth = 0.35;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// SVG 1.1 of a 2D-only model, in millimetres at 1:1 -- so a print of it
|
|
145
|
+
// measures what the script says. Every contour of a body, holes included,
|
|
146
|
+
// becomes a `M .. L .. z` subpath of that body's single `<path>`.
|
|
147
|
+
//
|
|
148
|
+
// Model space is Y-up and SVG's is Y-down, so the whole point transform is
|
|
149
|
+
// a Y negation. The page is the bounding box padded by half the stroke
|
|
150
|
+
// width and rounded OUTWARD to whole millimetres, which is why the margin
|
|
151
|
+
// is not a constant (0 to just under 1mm per side, depending where the
|
|
152
|
+
// bounds fall). Both rules are OpenSCAD's, read from its export_svg.cc and
|
|
153
|
+
// checked against its binary.
|
|
154
|
+
//
|
|
155
|
+
// Throws std::runtime_error if any top-level body is 3D -- OpenSCAD's rule,
|
|
156
|
+
// and the only honest answer, since there is no projection to fall back on.
|
|
157
|
+
void writeSvg(const std::string& path, const std::vector<ColoredBody>& bodies,
|
|
158
|
+
const ExportSvgOptions& opts = {});
|
|
159
|
+
|
|
160
|
+
// Options for the PDF writer, named and defaulted after OpenSCAD's own
|
|
161
|
+
// `-O export-pdf/...` set.
|
|
162
|
+
struct ExportPdfOptions {
|
|
163
|
+
enum class Paper { A6, A5, A4, A3, Letter, Legal, Tabloid };
|
|
164
|
+
// AUTO picks landscape when the model is wider than it is tall.
|
|
165
|
+
enum class Orientation { Portrait, Landscape, Auto };
|
|
166
|
+
|
|
167
|
+
Paper paper = Paper::A4;
|
|
168
|
+
Orientation orientation = Orientation::Portrait;
|
|
169
|
+
// The ruler, its labels and the caption that explains them. This is
|
|
170
|
+
// what makes a printed page a measuring tool rather than a plot, and
|
|
171
|
+
// is why the format was asked for at all.
|
|
172
|
+
bool showScale = true;
|
|
173
|
+
bool showScaleMsg = true;
|
|
174
|
+
bool showGrid = false;
|
|
175
|
+
double gridSize = 10.0;
|
|
176
|
+
// Drawn bottom-left when set. The DESIGN's name -- the writer has no
|
|
177
|
+
// way to know it, so a caller that wants it must pass it.
|
|
178
|
+
bool showFilename = false;
|
|
179
|
+
std::string designFilename;
|
|
180
|
+
bool fill = false;
|
|
181
|
+
std::string fillColor = "black";
|
|
182
|
+
bool stroke = true;
|
|
183
|
+
std::string strokeColor = "black";
|
|
184
|
+
double strokeWidth = 0.35;
|
|
185
|
+
bool addMetaData = true;
|
|
186
|
+
std::string metaTitle;
|
|
187
|
+
std::string metaAuthor;
|
|
188
|
+
std::string metaSubject;
|
|
189
|
+
std::string metaKeywords;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// "a4"/"letter"/... (case-insensitive) -> Paper. Returns false for a name
|
|
193
|
+
// it does not know, leaving `out` untouched.
|
|
194
|
+
bool paperFromName(const std::string& name, ExportPdfOptions::Paper& out);
|
|
195
|
+
// "portrait"/"landscape"/"auto" -> Orientation, same contract.
|
|
196
|
+
bool orientationFromName(const std::string& name, ExportPdfOptions::Orientation& out);
|
|
197
|
+
|
|
198
|
+
// PDF 1.4 of a 2D-only model, drawn at 1:1 and CENTRED on a fixed paper
|
|
199
|
+
// size -- unlike SVG, where the page is cut to fit the model.
|
|
200
|
+
//
|
|
201
|
+
// PDF user space is Y-up like model space, so unlike writeSvg there is NO
|
|
202
|
+
// Y negation: the placement is `pt = mm * 72/25.4` plus a centring offset,
|
|
203
|
+
// symmetric in both axes. (OpenSCAD's own file negates Y only because
|
|
204
|
+
// Cairo draws Y-down and then flips the whole page.)
|
|
205
|
+
//
|
|
206
|
+
// With `showScale` on it also draws OpenSCAD's ruler: a left and bottom
|
|
207
|
+
// axis at a 30pt margin, ticks every 10mm of MODEL space (hard-coded --
|
|
208
|
+
// `gridSize` belongs to the optional grid, not to this), numeric labels on
|
|
209
|
+
// every second tick, and the caption explaining what to measure. That
|
|
210
|
+
// ruler is the point of the format: it is what lets a printed page tell
|
|
211
|
+
// you how far off your printer's scaling is.
|
|
212
|
+
//
|
|
213
|
+
// Text uses the base-14 Helvetica every PDF reader supplies, so nothing is
|
|
214
|
+
// embedded and no font metrics are needed.
|
|
215
|
+
//
|
|
216
|
+
// Returns the warnings to surface (a model too large for the page is drawn
|
|
217
|
+
// anyway, and said so). Throws std::runtime_error if any top-level body is
|
|
218
|
+
// 3D, if there is nothing to draw, or if the file cannot be opened.
|
|
219
|
+
std::vector<std::string> writePdf(const std::string& path, const std::vector<ColoredBody>& bodies,
|
|
220
|
+
const ExportPdfOptions& opts = {});
|
|
221
|
+
|
|
130
222
|
// -- one entry point ------------------------------------------------------
|
|
131
223
|
|
|
132
224
|
struct ExportOptions {
|
|
@@ -144,6 +236,10 @@ struct ExportOptions {
|
|
|
144
236
|
// pieces it is in; see that function's own comment for why the default
|
|
145
237
|
// moved here.
|
|
146
238
|
bool splitComponents = false;
|
|
239
|
+
// .svg only.
|
|
240
|
+
ExportSvgOptions svg;
|
|
241
|
+
// .pdf only.
|
|
242
|
+
ExportPdfOptions pdf;
|
|
147
243
|
};
|
|
148
244
|
|
|
149
245
|
// Writes `bodies` to `path`, choosing the writer from the extension (or
|
|
@@ -28,6 +28,14 @@ void writeStoredZip(const std::string& path, const std::vector<ZipEntry>& entrie
|
|
|
28
28
|
// std::runtime_error if the file can't be opened for writing.
|
|
29
29
|
void writeDeflateZip(const std::string& path, const std::vector<ZipEntry>& entries);
|
|
30
30
|
|
|
31
|
+
// Compresses `data` to a zlib stream (RFC 1950: 2-byte header, DEFLATE
|
|
32
|
+
// data, Adler-32 trailer) -- which is exactly what PDF's /FlateDecode
|
|
33
|
+
// filter reads, so the PDF writer uses this rather than growing its own
|
|
34
|
+
// compressor. Same stb_image_write.h implementation the ZIP writer above
|
|
35
|
+
// deflates with, only without the wrapper stripped off. Empty if
|
|
36
|
+
// compression fails; the caller can always write the data uncompressed.
|
|
37
|
+
std::vector<uint8_t> zlibCompress(const uint8_t* data, size_t size);
|
|
38
|
+
|
|
31
39
|
// Reads one entry (by exact name match) from a ZIP archive via its central
|
|
32
40
|
// directory (authoritative regardless of how local headers were written).
|
|
33
41
|
// Supports both STORED (method 0, this project's own writeStoredZip()
|
|
@@ -292,7 +292,10 @@ def strip_slivers(verts, tris):
|
|
|
292
292
|
|
|
293
293
|
|
|
294
294
|
def export_model(path: str, geometry, format: str = "", ascii_stl: bool = False,
|
|
295
|
-
strip_slivers: bool = True, split_components: bool = False
|
|
295
|
+
strip_slivers: bool = True, split_components: bool = False,
|
|
296
|
+
svg_fill: bool = False, svg_fill_color: str = "white",
|
|
297
|
+
svg_stroke: bool = True, svg_stroke_color: str = "black",
|
|
298
|
+
svg_stroke_width: float = 0.35, pdf_options: dict | None = None) -> list:
|
|
296
299
|
"""Write `geometry` to `path`. Returns the warnings to surface.
|
|
297
300
|
|
|
298
301
|
`geometry` is the handle an Evaluator stashes on itself as
|
|
@@ -312,10 +315,29 @@ def export_model(path: str, geometry, format: str = "", ascii_stl: bool = False,
|
|
|
312
315
|
|
|
313
316
|
`split_components` gives every disconnected piece its own object in the
|
|
314
317
|
multi-object formats. Off by default, which is what OpenSCAD writes.
|
|
318
|
+
|
|
319
|
+
The `svg_*` arguments are OpenSCAD's `-O export-svg/...` set and apply
|
|
320
|
+
to `.svg` only, which writes a 2D model at 1:1 in millimetres.
|
|
321
|
+
`svg_stroke`/`svg_stroke_width` also pad the page, so they are not
|
|
322
|
+
purely cosmetic. An `.svg` export of anything 3D raises, as OpenSCAD's
|
|
323
|
+
does -- there is no projection to fall back on.
|
|
324
|
+
|
|
325
|
+
`pdf_options` is a dict keyed the way OpenSCAD names its own
|
|
326
|
+
`-O export-pdf/...` settings: `paper-size`, `orientation`,
|
|
327
|
+
`show-scale`, `show-scale-message`, `show-grid`, `grid-size`,
|
|
328
|
+
`show-filename`, `design-filename`, `fill`, `fill-color`, `stroke`,
|
|
329
|
+
`stroke-color`, `stroke-width`, `add-meta-data`, `title`, `author`,
|
|
330
|
+
`subject`, `keywords`. An unknown key raises rather than being
|
|
331
|
+
ignored -- a silently dropped `paper-size` would print the wrong page
|
|
332
|
+
size with nothing to explain it. `.pdf` is 2D-only like `.svg`, and
|
|
333
|
+
centres the drawing on a fixed paper size instead of cutting the page
|
|
334
|
+
to fit.
|
|
315
335
|
"""
|
|
316
336
|
try:
|
|
317
337
|
return list(_ext.export_model(path, geometry, format, ascii_stl, strip_slivers,
|
|
318
|
-
split_components
|
|
338
|
+
split_components, svg_fill, svg_fill_color,
|
|
339
|
+
svg_stroke, svg_stroke_color, svg_stroke_width,
|
|
340
|
+
pdf_options))
|
|
319
341
|
except Exception as e:
|
|
320
342
|
raise EvalError(str(e)) from e
|
|
321
343
|
|
|
@@ -43,6 +43,13 @@ std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodi
|
|
|
43
43
|
flat.body = flat.body->Transform(cb.sectionXform);
|
|
44
44
|
flat.color = cb.color;
|
|
45
45
|
flat.flatPreview = true;
|
|
46
|
+
// Carried, not consumed: the 2D writers (writeSvg) need the
|
|
47
|
+
// contours, and every caller that exports goes through this
|
|
48
|
+
// conversion first -- the Python binding hands ONE body list to
|
|
49
|
+
// both the renderer and export. Dropping it here made an SVG
|
|
50
|
+
// export of any 2D script impossible from Python.
|
|
51
|
+
flat.section = cb.section;
|
|
52
|
+
flat.sectionXform = cb.sectionXform;
|
|
46
53
|
flat.role = cb.role;
|
|
47
54
|
out.push_back(std::move(flat));
|
|
48
55
|
} else {
|