openscad-cpp-evaluator 1.38.1__tar.gz → 1.40.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.38.1 → openscad_cpp_evaluator-1.40.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/booleans.cpp +2 -1
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/builtins.hpp +8 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/function_builtins.cpp +7 -7
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/primitives_3d.cpp +116 -14
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/registry.cpp +3 -3
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/text.cpp +16 -2
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/colored_body.cpp +3 -2
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/csg_generate.cpp +9 -2
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_manifold_cache.cpp +23 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_primitives.cpp +40 -5
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_text.cpp +30 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/cmake/patch_manifold.cmake +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/import/scene_import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_undef_args.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tools/cli/main.cpp +0 -0
|
@@ -231,7 +231,8 @@ manifold::Manifold finishKeepMinuend(Evaluator& ev, std::vector<KeepPart>& parts
|
|
|
231
231
|
std::optional<manifold::Manifold> out;
|
|
232
232
|
for (KeepPart& part : parts) {
|
|
233
233
|
if (!part.body.body) continue;
|
|
234
|
-
|
|
234
|
+
// MeshGL64: rebuilt below, and float32 would move every vertex.
|
|
235
|
+
manifold::MeshGL64 mesh = part.body.body->GetMeshGL64();
|
|
235
236
|
if (mesh.triVerts.empty()) continue;
|
|
236
237
|
std::unordered_map<uint32_t, uint32_t> remap;
|
|
237
238
|
for (uint32_t& id : mesh.runOriginalID) {
|
|
@@ -268,6 +268,14 @@ std::vector<ColoredBody> generateSurface(Evaluator& ev, const CSGParams& params,
|
|
|
268
268
|
|
|
269
269
|
// text() -- text.cpp.
|
|
270
270
|
CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx);
|
|
271
|
+
|
|
272
|
+
// The font size text()/textmetrics()/fontmetrics() draw at: `size`
|
|
273
|
+
// (default 10), or `em` * 72/100 when `em` is given -- upstream's
|
|
274
|
+
// correction for the 100/72 factor that makes `size` the cap height
|
|
275
|
+
// rather than the em square (openscad #4304). `size` given alongside
|
|
276
|
+
// `em` is ignored, with upstream's warning naming `caller`.
|
|
277
|
+
double textSizeArg(Evaluator& ev, const CallArgs& args, std::optional<int> sizePos, std::optional<int> emPos,
|
|
278
|
+
const char* caller, const oscad::Position* where);
|
|
271
279
|
std::vector<ColoredBody> generateText(Evaluator& ev, const CSGParams& params,
|
|
272
280
|
const std::vector<std::unique_ptr<CSGNode>>& children, const oscad::ASTNode& node);
|
|
273
281
|
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -776,7 +776,7 @@ Value objectOf(std::vector<std::pair<std::string, Value>> items) {
|
|
|
776
776
|
}
|
|
777
777
|
|
|
778
778
|
// textmetrics(text=, size=10, font=, direction=, language=, script=,
|
|
779
|
-
// halign=, valign=, spacing=) -- measures `text` against the
|
|
779
|
+
// halign=, valign=, spacing=, em=) -- measures `text` against the
|
|
780
780
|
// FontProvider-resolved font, laid out by exactly the same shaping call
|
|
781
781
|
// text() makes, and returns an OscObject with position/size/ascent/
|
|
782
782
|
// descent/offset/advance in real OpenSCAD's key order. Going through the
|
|
@@ -784,10 +784,10 @@ Value objectOf(std::vector<std::pair<std::string, Value>> items) {
|
|
|
784
784
|
// a script positions against cannot disagree with what it draws.
|
|
785
785
|
Value builtinTextmetrics(Evaluator& ev, const CallArgs& args, const oscad::Position* pos) {
|
|
786
786
|
const std::string text = asStringOr(getArg(args, 0, "text", Value{std::string("")}), "");
|
|
787
|
-
const double size =
|
|
787
|
+
const double size = textSizeArg(ev, args, 1, 9, "textmetrics", pos);
|
|
788
788
|
// Positional indices, all of them: OpenSCAD's own signature is
|
|
789
789
|
// textmetrics(text, size, font, direction, language, script, halign,
|
|
790
|
-
// valign, spacing) and it honours every one of those positionally --
|
|
790
|
+
// valign, spacing, em) and it honours every one of those positionally --
|
|
791
791
|
// verified against the 2026.02.01 binary, not read off a doc page.
|
|
792
792
|
// `font` being name-only here is what made
|
|
793
793
|
// `textmetrics("Hi", 10, "Liberation Sans:style=Bold")` silently
|
|
@@ -817,10 +817,10 @@ Value builtinTextmetrics(Evaluator& ev, const CallArgs& args, const oscad::Posit
|
|
|
817
817
|
});
|
|
818
818
|
}
|
|
819
819
|
|
|
820
|
-
// fontmetrics(size=10, font=) -- global metrics of the FontProvider-
|
|
820
|
+
// fontmetrics(size=10, font=, em=) -- global metrics of the FontProvider-
|
|
821
821
|
// resolved font, scaled for `size`. Mirrors _builtin_fontmetrics.
|
|
822
|
-
Value builtinFontmetrics(Evaluator& ev, const CallArgs& args) {
|
|
823
|
-
const double size =
|
|
822
|
+
Value builtinFontmetrics(Evaluator& ev, const CallArgs& args, const oscad::Position* pos) {
|
|
823
|
+
const double size = textSizeArg(ev, args, 0, 2, "fontmetrics", pos);
|
|
824
824
|
// Positional too: fontmetrics(10, "Liberation Sans:style=Bold") is
|
|
825
825
|
// how the bug report was written, and how the real binary reads it.
|
|
826
826
|
const std::string fontSpec = asStringOr(getArg(args, 1, "font", Value{std::string("")}), "");
|
|
@@ -1255,7 +1255,7 @@ Value evalBuiltinFunctionResolved(Evaluator& ev, BuiltinFnId id, const std::vect
|
|
|
1255
1255
|
switch (id) {
|
|
1256
1256
|
case BuiltinFnId::None: return Value{}; // unreachable: handled above
|
|
1257
1257
|
case BuiltinFnId::TextMetrics: return builtinTextmetrics(ev, args, &node.position());
|
|
1258
|
-
case BuiltinFnId::FontMetrics: return builtinFontmetrics(ev, args);
|
|
1258
|
+
case BuiltinFnId::FontMetrics: return builtinFontmetrics(ev, args, &node.position());
|
|
1259
1259
|
case BuiltinFnId::Abs: return Value{std::fabs(toDoubleLenient(getArg(args, 0, "x", Value{})))};
|
|
1260
1260
|
case BuiltinFnId::Sign: {
|
|
1261
1261
|
const double x = toDoubleLenient(getArg(args, 0, "x", Value{}));
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/src/builtins/primitives_3d.cpp
RENAMED
|
@@ -275,6 +275,121 @@ SphereMesh buildAligned(double r, int hsides, int vsides, bool stagger) {
|
|
|
275
275
|
return m;
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
// "octa": an octahedron with each face cut into an n x n triangular grid,
|
|
279
|
+
// n = ceil(segments / 4), pushed out to the sphere -- 4n^2 + 2 vertices,
|
|
280
|
+
// one on each pole of all three axes. Vertex placement is upstream
|
|
281
|
+
// OpenSCAD's (primitives.cc, SphereNode::createGeometryOcta): an interior
|
|
282
|
+
// vertex is where the great-circle arcs through equally spaced edge points
|
|
283
|
+
// meet, the three pairwise intersections averaged.
|
|
284
|
+
//
|
|
285
|
+
// The mesh is EXACTLY symmetric under all 48 symmetries of the octahedron,
|
|
286
|
+
// not merely to rounding: every vertex is computed once, for its
|
|
287
|
+
// barycentric weights sorted largest first, and the other copies are that
|
|
288
|
+
// one point with its coordinates permuted and negated, which is exact.
|
|
289
|
+
// Within a rounding error is not good enough. Manifold::Sphere, which this
|
|
290
|
+
// used to be, is symmetric only to ~1e-15, so a copy rotated 90 degrees
|
|
291
|
+
// landed a hair off the original and difference() of the two left a mass of
|
|
292
|
+
// sliver shards where it should leave nothing.
|
|
293
|
+
//
|
|
294
|
+
// ponytail: the great-circle vertices are not bit-identical to circle()'s
|
|
295
|
+
// (Manifold's Circle reduces angles by quadrant, not octant, so it is not
|
|
296
|
+
// exactly symmetric itself); a sphere and a coaxial circle of the same $fn
|
|
297
|
+
// agree to rounding only.
|
|
298
|
+
namespace {
|
|
299
|
+
// (cos, sin) of (90 * m / n) degrees, always computed from the angle at or
|
|
300
|
+
// below 45 degrees, so the points at m and n - m are exact mirrors.
|
|
301
|
+
std::array<double, 2> quarterArc(int m, int n) {
|
|
302
|
+
if (2 * m == n) return {std::sqrt(0.5), std::sqrt(0.5)};
|
|
303
|
+
if (2 * m > n) {
|
|
304
|
+
const std::array<double, 2> p = quarterArc(n - m, n);
|
|
305
|
+
return {p[1], p[0]};
|
|
306
|
+
}
|
|
307
|
+
const double t = (std::numbers::pi / 2.0) * m / n;
|
|
308
|
+
return {std::cos(t), std::sin(t)};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
using V3 = std::array<double, 3>;
|
|
312
|
+
V3 cross(const V3& a, const V3& b) {
|
|
313
|
+
return {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]};
|
|
314
|
+
}
|
|
315
|
+
V3 normalized(const V3& v) {
|
|
316
|
+
const double l = std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
|
317
|
+
return {v[0] / l, v[1] / l, v[2] / l};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// The unit-sphere point with barycentric weights a >= b >= c (a + b + c = n)
|
|
321
|
+
// toward three orthogonal axes, as coordinates along those axes.
|
|
322
|
+
V3 octaCanonical(int a, int b, int c, int n) {
|
|
323
|
+
if (b == 0) return {1.0, 0.0, 0.0};
|
|
324
|
+
if (c == 0) {
|
|
325
|
+
const std::array<double, 2> e = quarterArc(b, n);
|
|
326
|
+
return {e[0], e[1], 0.0};
|
|
327
|
+
}
|
|
328
|
+
// Upstream's construction, with its i, j, k = a, b, c.
|
|
329
|
+
const auto ac = [&](int m) { const auto e = quarterArc(m, n); return V3{e[0], 0.0, e[1]}; };
|
|
330
|
+
const auto bc = [&](int m) { const auto e = quarterArc(m, n); return V3{0.0, e[0], e[1]}; };
|
|
331
|
+
const auto ab = [&](int m) { const auto e = quarterArc(m, n); return V3{e[0], e[1], 0.0}; };
|
|
332
|
+
const auto meet = [](const V3& p, const V3& q, const V3& r, const V3& s) {
|
|
333
|
+
V3 x = normalized(cross(cross(p, q), cross(r, s)));
|
|
334
|
+
if (x[0] + x[1] + x[2] < 0) x = {-x[0], -x[1], -x[2]}; // the octant's side
|
|
335
|
+
return x;
|
|
336
|
+
};
|
|
337
|
+
const V3 xz_k = ac(c), yz_k = bc(c);
|
|
338
|
+
const V3 xy_j = ab(b), yz_j = bc(n - b);
|
|
339
|
+
const V3 xy_i = ab(n - a), xz_i = ac(n - a);
|
|
340
|
+
const V3 p1 = meet(xz_k, yz_k, xy_j, yz_j);
|
|
341
|
+
const V3 p2 = meet(xz_k, yz_k, xy_i, xz_i);
|
|
342
|
+
const V3 p3 = meet(xy_j, yz_j, xy_i, xz_i);
|
|
343
|
+
V3 p = normalized({p1[0] + p2[0] + p3[0], p1[1] + p2[1] + p3[1], p1[2] + p2[2] + p3[2]});
|
|
344
|
+
// Equal weights must give equal coordinates exactly, or the two
|
|
345
|
+
// permutations that swap them would disagree about this one vertex.
|
|
346
|
+
if (a == b) p[1] = p[0];
|
|
347
|
+
if (b == c) p[2] = p[1];
|
|
348
|
+
return p;
|
|
349
|
+
}
|
|
350
|
+
} // namespace
|
|
351
|
+
|
|
352
|
+
SphereMesh buildOcta(double r, int segments) {
|
|
353
|
+
const int n = std::max(1, (segments + 3) / 4);
|
|
354
|
+
SphereMesh m;
|
|
355
|
+
std::map<std::array<int, 3>, int> index; // signed barycentric weights -> vertex
|
|
356
|
+
const auto vertex = [&](int i, int j, int k, int sx, int sy, int sz) {
|
|
357
|
+
const std::array<int, 3> key{sx * i, sy * j, sz * k};
|
|
358
|
+
auto [it, fresh] = index.try_emplace(key, static_cast<int>(m.verts.size() / 3));
|
|
359
|
+
if (fresh) {
|
|
360
|
+
const std::array<int, 3> w{i, j, k};
|
|
361
|
+
std::array<int, 3> axis{0, 1, 2};
|
|
362
|
+
std::stable_sort(axis.begin(), axis.end(), [&](int p, int q) { return w[p] > w[q]; });
|
|
363
|
+
const V3 c = octaCanonical(w[axis[0]], w[axis[1]], w[axis[2]], n);
|
|
364
|
+
V3 p{};
|
|
365
|
+
for (int rank = 0; rank < 3; ++rank) p[axis[rank]] = c[rank];
|
|
366
|
+
pushVert(m, {r * sx * p[0], r * sy * p[1], r * sz * p[2]});
|
|
367
|
+
}
|
|
368
|
+
return it->second;
|
|
369
|
+
};
|
|
370
|
+
for (int sx : {1, -1})
|
|
371
|
+
for (int sy : {1, -1})
|
|
372
|
+
for (int sz : {1, -1}) {
|
|
373
|
+
const bool flip = sx * sy * sz < 0;
|
|
374
|
+
const auto tri = [&](int a, int b, int c) {
|
|
375
|
+
if (flip) std::swap(b, c);
|
|
376
|
+
m.tris.insert(m.tris.end(), {a, b, c});
|
|
377
|
+
};
|
|
378
|
+
// "Up" triangles toward +x, +y, +z, then the "down" ones
|
|
379
|
+
// between them; both wind outward in the (+,+,+) octant.
|
|
380
|
+
for (int i = 0; i < n; ++i)
|
|
381
|
+
for (int j = 0; i + j < n; ++j) {
|
|
382
|
+
const int k = n - 1 - i - j;
|
|
383
|
+
tri(vertex(i + 1, j, k, sx, sy, sz), vertex(i, j + 1, k, sx, sy, sz),
|
|
384
|
+
vertex(i, j, k + 1, sx, sy, sz));
|
|
385
|
+
if (k >= 1)
|
|
386
|
+
tri(vertex(i, j + 1, k, sx, sy, sz), vertex(i + 1, j, k, sx, sy, sz),
|
|
387
|
+
vertex(i + 1, j + 1, k - 1, sx, sy, sz));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return m;
|
|
391
|
+
}
|
|
392
|
+
|
|
278
393
|
// "icosa": subdivide every icosahedral face into a triangular grid and push
|
|
279
394
|
// each sample out to the sphere. BOSL2 subsamples one face and rotates
|
|
280
395
|
// copies onto the rest; sampling each face against its own corners is the
|
|
@@ -398,18 +513,10 @@ CSGParams resolveSphere(Evaluator& ev, const oscad::ModularCall& node, EvalConte
|
|
|
398
513
|
params["segs"] = Value{static_cast<double>(hsides)};
|
|
399
514
|
params["color"] = colorToValue(effCtx.color);
|
|
400
515
|
|
|
401
|
-
if (style == "octa") {
|
|
402
|
-
// Manifold::Sphere IS a subdivided octahedron (Shape::Octahedron,
|
|
403
|
-
// then Subdivide), so this needs no mesh of our own -- generate
|
|
404
|
-
// calls it directly.
|
|
405
|
-
params["verts"] = Value{makeList()};
|
|
406
|
-
params["tris"] = Value{makeList()};
|
|
407
|
-
return params;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
516
|
const SphereMesh m = style == "aligned" ? buildAligned(r, hsides, vsides, false)
|
|
411
517
|
: style == "stagger" ? buildAligned(r, hsides, vsides, true)
|
|
412
518
|
: style == "icosa" ? buildIcosa(r, hsides)
|
|
519
|
+
: style == "octa" ? buildOcta(r, hsides)
|
|
413
520
|
: buildOrig(r, hsides, vsides);
|
|
414
521
|
|
|
415
522
|
std::vector<Value> vertsValues;
|
|
@@ -433,11 +540,6 @@ std::vector<ColoredBody> generateSphere(Evaluator& ev, const CSGParams& params,
|
|
|
433
540
|
for (const Value& t : std::get<ListPtr>(params.at("tris"))->items) {
|
|
434
541
|
mesh.triVerts.push_back(static_cast<uint64_t>(std::get<double>(t)));
|
|
435
542
|
}
|
|
436
|
-
if (std::get<std::string>(params.at("style")) == "octa") {
|
|
437
|
-
manifold::Manifold octa = manifold::Manifold::Sphere(
|
|
438
|
-
std::get<double>(params.at("r")), static_cast<int>(std::get<double>(params.at("segs"))));
|
|
439
|
-
return {ev.tagGenerated(std::move(octa), node, params.at("color"))};
|
|
440
|
-
}
|
|
441
543
|
manifold::Manifold body(mesh);
|
|
442
544
|
return {ev.tagGenerated(std::move(body), node, params.at("color"))};
|
|
443
545
|
}
|
|
@@ -138,14 +138,14 @@ const std::vector<std::string>* builtinParamNames(const std::string& name) {
|
|
|
138
138
|
{"levelset", {"field", "bounds", "isovalue", "invert", "edge"}},
|
|
139
139
|
{"offset", {"r", "delta", "chamfer"}},
|
|
140
140
|
{"surface", {"file", "center", "convexity", "invert"}},
|
|
141
|
-
{"text", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
141
|
+
{"text", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing", "em"}},
|
|
142
142
|
// breakpoint() is this port's own debugger extension, no upstream
|
|
143
143
|
// equivalent to mirror.
|
|
144
144
|
{"breakpoint", {"condition"}},
|
|
145
145
|
|
|
146
146
|
// -- the three builtin FUNCTIONS that do use Parameters::parse ----
|
|
147
|
-
{"textmetrics", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing"}},
|
|
148
|
-
{"fontmetrics", {"size", "font"}},
|
|
147
|
+
{"textmetrics", {"text", "size", "font", "direction", "language", "script", "halign", "valign", "spacing", "em"}},
|
|
148
|
+
{"fontmetrics", {"size", "font", "em"}},
|
|
149
149
|
};
|
|
150
150
|
auto it = table.find(name);
|
|
151
151
|
return it == table.end() ? nullptr : &it->second;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include <algorithm>
|
|
9
9
|
|
|
10
|
-
// text(text=, size=10
|
|
10
|
+
// text(text=, size=10 | em=, font=, halign="default", valign="default", spacing=1,
|
|
11
11
|
// direction=, language=, script=) -- renders `text` as 2D glyph outlines
|
|
12
12
|
// through the FontProvider (Evaluator::fontProvider(), lazily the built-in
|
|
13
13
|
// FreetypeFontProvider if none was injected).
|
|
@@ -30,10 +30,24 @@ std::string asStringOr(const Value& v, const std::string& fallback) {
|
|
|
30
30
|
}
|
|
31
31
|
} // namespace
|
|
32
32
|
|
|
33
|
+
double textSizeArg(Evaluator& ev, const CallArgs& args, std::optional<int> sizePos, std::optional<int> emPos,
|
|
34
|
+
const char* caller, const oscad::Position* where) {
|
|
35
|
+
const Value em = getArg(args, emPos, "em");
|
|
36
|
+
const Value size = getArg(args, sizePos, "size");
|
|
37
|
+
if (std::holds_alternative<std::monostate>(em)) {
|
|
38
|
+
return std::holds_alternative<std::monostate>(size) ? 10.0 : toDoubleLenient(size);
|
|
39
|
+
}
|
|
40
|
+
if (!std::holds_alternative<std::monostate>(size)) {
|
|
41
|
+
ev.warn(std::string(caller) + ": \"size\" ignored when \"em\" is set", where);
|
|
42
|
+
}
|
|
43
|
+
return toDoubleLenient(em) * 72.0 / 100.0;
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext& ctx) {
|
|
34
47
|
auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
|
|
35
48
|
const std::string text = asStringOr(getArg(args, 0, "text", Value{std::string("")}), "");
|
|
36
|
-
|
|
49
|
+
// em is name-only, like everything after font here.
|
|
50
|
+
const double size = textSizeArg(ev, args, 1, std::nullopt, "text", &node.position());
|
|
37
51
|
// font is POSITIONAL, at index 2: `text("Hi", 10, "Liberation Sans")`
|
|
38
52
|
// is how people write it and how the reference reads it -- measured
|
|
39
53
|
// against the 2026.02.01 binary, whose bounding box for the
|
|
@@ -40,9 +40,10 @@ std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodi
|
|
|
40
40
|
// slab finds the node that built the shape (see
|
|
41
41
|
// ColoredBody::sectionId). Manifold keeps a MeshGL's
|
|
42
42
|
// runOriginalID when it is given one.
|
|
43
|
-
|
|
43
|
+
// MeshGL64: rebuilt below, and float32 would move every vertex.
|
|
44
|
+
manifold::MeshGL64 mesh = flat.body->GetMeshGL64();
|
|
44
45
|
mesh.runOriginalID = {*cb.sectionId};
|
|
45
|
-
mesh.runIndex = {0,
|
|
46
|
+
mesh.runIndex = {0, mesh.triVerts.size()};
|
|
46
47
|
mesh.runTransform.clear();
|
|
47
48
|
mesh.faceID.clear();
|
|
48
49
|
flat.body = manifold::Manifold(mesh);
|
|
@@ -364,7 +364,7 @@ std::shared_ptr<const std::vector<ColoredBody>> remapParts(const std::vector<Col
|
|
|
364
364
|
for (ColoredBody part : parts) {
|
|
365
365
|
if (part.mergedFrom) part.mergedFrom = remapParts(*part.mergedFrom, remap);
|
|
366
366
|
if (part.body && !part.body->IsEmpty()) {
|
|
367
|
-
manifold::
|
|
367
|
+
manifold::MeshGL64 mesh = part.body->GetMeshGL64();
|
|
368
368
|
for (uint32_t& id : mesh.runOriginalID) {
|
|
369
369
|
auto found = remap.find(id);
|
|
370
370
|
if (found != remap.end()) id = found->second;
|
|
@@ -417,7 +417,14 @@ void Evaluator::restampCachedIds(std::vector<ColoredBody>& bodies, const oscad::
|
|
|
417
417
|
cb.sectionId = fresh;
|
|
418
418
|
}
|
|
419
419
|
if (!cb.body || cb.body->IsEmpty()) continue;
|
|
420
|
-
|
|
420
|
+
// MeshGL64, not MeshGL: the body is rebuilt from this mesh below,
|
|
421
|
+
// and MeshGL is float32. Rounding every vertex made a cache hit a
|
|
422
|
+
// slightly different solid from the same shape built fresh, so
|
|
423
|
+
// difference() { sphere(50); sphere(50); } left a shell of slivers
|
|
424
|
+
// wherever one operand came from the cache -- only in the GUI,
|
|
425
|
+
// which has a cache, never in the CLI. A cube survived because its
|
|
426
|
+
// coordinates are exact in float32.
|
|
427
|
+
manifold::MeshGL64 mesh = cb.body->GetMeshGL64();
|
|
421
428
|
if (mesh.runOriginalID.empty()) continue;
|
|
422
429
|
std::unordered_map<uint32_t, uint32_t> remap;
|
|
423
430
|
// fresh ID -> the colour its triangles carried, multi-colour
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/tests/test_manifold_cache.cpp
RENAMED
|
@@ -496,3 +496,26 @@ TEST(ManifoldCache, AHitOnAQuietSubtreeStaysQuiet) {
|
|
|
496
496
|
EXPECT_EQ(countLines(), 0);
|
|
497
497
|
EXPECT_EQ(countLines(), 0);
|
|
498
498
|
}
|
|
499
|
+
|
|
500
|
+
// A cache hit used to come back rebuilt through float32 (MeshGL), so the
|
|
501
|
+
// second of two identical spheres was a slightly different solid from the
|
|
502
|
+
// first and difference() left a shell of slivers -- in the GUI only, since
|
|
503
|
+
// the CLI has no cache. A cube hid it: its coordinates are exact in float.
|
|
504
|
+
// Covers the hit within one render, across renders, and the keep-minuend
|
|
505
|
+
// path, which rebuilt its parts the same way.
|
|
506
|
+
TEST(ManifoldCache, AHitIsTheSameSolidNotAFloatRoundedCopy) {
|
|
507
|
+
const std::string srcs[] = {
|
|
508
|
+
"difference() { sphere(d=100, $fn=16); sphere(d=100, $fn=16); }",
|
|
509
|
+
"difference() { sphere(d=100, style=\"octa\", $fn=16); sphere(d=100, style=\"octa\", $fn=16); }",
|
|
510
|
+
"difference() { rotate([10, 20, 30]) cylinder(h=7.3, r=3.1); rotate([10, 20, 30]) cylinder(h=7.3, r=3.1); }",
|
|
511
|
+
};
|
|
512
|
+
for (const std::string& src : srcs) {
|
|
513
|
+
auto cache = std::make_shared<ManifoldCache>();
|
|
514
|
+
for (int render = 0; render < 2; ++render) {
|
|
515
|
+
Evaluated e = evalSrcWithCache(src, cache);
|
|
516
|
+
for (const ColoredBody& b : e.bodies) {
|
|
517
|
+
EXPECT_TRUE(!b.body || b.body->IsEmpty()) << src << " render " << render;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
#include "test_helpers.hpp"
|
|
5
5
|
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <array>
|
|
6
8
|
#include <cmath>
|
|
9
|
+
#include <set>
|
|
10
|
+
#include <string>
|
|
7
11
|
#include <gtest/gtest.h>
|
|
8
12
|
#include <numbers>
|
|
9
13
|
|
|
@@ -398,14 +402,45 @@ TEST(SphereStyle, EveryStyleMatchesBosl2sCounts) {
|
|
|
398
402
|
}
|
|
399
403
|
|
|
400
404
|
TEST(SphereStyle, EveryStyleMatchesBosl2sVolume) {
|
|
401
|
-
// aligned/stagger/icosa agree with BOSL2 to the last digit. "octa"
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
//
|
|
405
|
+
// aligned/stagger/icosa agree with BOSL2 to the last digit. "octa" is
|
|
406
|
+
// upstream OpenSCAD's construction (sphere(style="octa"), 2026-09), not
|
|
407
|
+
// BOSL2's -- same 146/288 topology. 4026.4886 is the hull volume of an
|
|
408
|
+
// independent port of upstream's createGeometryOcta.
|
|
405
409
|
EXPECT_NEAR(sphereStats("sphere(r=10, style=\"aligned\", $fn=24);").volume, 4070.5524, 1e-3);
|
|
406
410
|
EXPECT_NEAR(sphereStats("sphere(r=10, style=\"stagger\", $fn=24);").volume, 4082.1246, 1e-3);
|
|
407
411
|
EXPECT_NEAR(sphereStats("sphere(r=10, style=\"icosa\", $fn=24);").volume, 4097.2467, 1e-3);
|
|
408
|
-
EXPECT_NEAR(sphereStats("sphere(r=10, style=\"octa\", $fn=24);").volume,
|
|
412
|
+
EXPECT_NEAR(sphereStats("sphere(r=10, style=\"octa\", $fn=24);").volume, 4026.4886, 1e-3);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// "octa" must be EXACTLY symmetric under the octahedron's 48 symmetries, not
|
|
416
|
+
// to rounding: a copy rotated 90 degrees otherwise lands a hair off the
|
|
417
|
+
// original, and difference() of the two leaves a mass of sliver shards
|
|
418
|
+
// instead of nothing. It used to be Manifold::Sphere, symmetric to ~1e-15.
|
|
419
|
+
TEST(SphereStyle, OctaIsExactlyOctahedrallySymmetric) {
|
|
420
|
+
for (int fn : {3, 8, 16, 21, 37, 64}) {
|
|
421
|
+
const std::string sphere = "sphere(d=100, style=\"octa\", $fn=" + std::to_string(fn) + ")";
|
|
422
|
+
Evaluated e = evalSrc(sphere + ";");
|
|
423
|
+
const manifold::MeshGL64 mesh = e.bodies[0].body->GetMeshGL64();
|
|
424
|
+
const size_t n = static_cast<size_t>(std::max(1, (fn + 3) / 4));
|
|
425
|
+
EXPECT_EQ(mesh.vertProperties.size() / 3, 4 * n * n + 2) << fn;
|
|
426
|
+
std::set<std::array<double, 3>> verts;
|
|
427
|
+
for (size_t v = 0; v < mesh.vertProperties.size(); v += 3)
|
|
428
|
+
verts.insert({mesh.vertProperties[v] + 0.0, mesh.vertProperties[v + 1] + 0.0, mesh.vertProperties[v + 2] + 0.0});
|
|
429
|
+
std::array<int, 3> perm{0, 1, 2};
|
|
430
|
+
do {
|
|
431
|
+
for (int signs = 0; signs < 8; ++signs) {
|
|
432
|
+
for (const std::array<double, 3>& p : verts) {
|
|
433
|
+
std::array<double, 3> q{};
|
|
434
|
+
for (int a = 0; a < 3; ++a) q[a] = ((signs >> a) & 1 ? -p[perm[a]] : p[perm[a]]) + 0.0;
|
|
435
|
+
EXPECT_TRUE(verts.count(q)) << fn;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
} while (std::next_permutation(perm.begin(), perm.end()));
|
|
439
|
+
for (const char* rot : {"[90,0,0]", "[0,90,0]", "[0,0,90]", "[180,0,0]"}) {
|
|
440
|
+
Evaluated d = evalSrc("difference() { " + sphere + "; rotate(" + rot + ") " + sphere + "; }");
|
|
441
|
+
for (const ColoredBody& b : d.bodies) EXPECT_TRUE(!b.body || b.body->IsEmpty()) << fn << " " << rot;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
409
444
|
}
|
|
410
445
|
|
|
411
446
|
TEST(SphereStyle, EveryStyleIsAClosedSolidUnderTheTrueVolume) {
|
|
@@ -192,6 +192,36 @@ TEST(Textmetrics, MultiByteUtf8CodepointsDecodeWithoutCrashing) {
|
|
|
192
192
|
EXPECT_GT(asNum(items[0]), 0.0);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
// em (upstream 2026-03, openscad #4304): `em` sets the em square, i.e.
|
|
196
|
+
// size = em * 72/100, and wins over `size` with a warning. Positional at
|
|
197
|
+
// index 9 in textmetrics and 2 in fontmetrics, as upstream's parameter
|
|
198
|
+
// lists put it; text() takes it by name only, like its other options.
|
|
199
|
+
TEST(Text, EmIsSizeTimes72Over100) {
|
|
200
|
+
const std::pair<const char*, std::vector<std::string>> cases[] = {
|
|
201
|
+
{"echo(str(textmetrics(\"Hi\", em=10)) == str(textmetrics(\"Hi\", size=7.2)));", {"ECHO: true"}},
|
|
202
|
+
{"echo(str(textmetrics(\"Hi\", 3, \"\", \"ltr\", \"en\", \"latin\", \"left\", \"baseline\", 1, 10))"
|
|
203
|
+
" == str(textmetrics(\"Hi\", size=7.2)));",
|
|
204
|
+
{"WARNING: textmetrics: \"size\" ignored when \"em\" is set in file <string>, line 1", "ECHO: true"}},
|
|
205
|
+
{"echo(str(fontmetrics(em=10)) == str(fontmetrics(size=7.2)));", {"ECHO: true"}},
|
|
206
|
+
// Inside a function, so the compiled (VM) call path is covered too.
|
|
207
|
+
{"function f() = textmetrics(\"Hi\", em=10); echo(str(f()) == str(textmetrics(\"Hi\", size=7.2)));",
|
|
208
|
+
{"ECHO: true"}},
|
|
209
|
+
{"echo(str(fontmetrics(undef, \"\", 10)) == str(fontmetrics(size=7.2)));", {"ECHO: true"}},
|
|
210
|
+
{"m = fontmetrics(size=3, em=10);",
|
|
211
|
+
{"WARNING: fontmetrics: \"size\" ignored when \"em\" is set in file <string>, line 1"}},
|
|
212
|
+
{"text(\"Hi\", size=3, em=10);",
|
|
213
|
+
{"WARNING: text: \"size\" ignored when \"em\" is set in file <string>, line 1"}},
|
|
214
|
+
};
|
|
215
|
+
for (const auto& [src, want] : cases) {
|
|
216
|
+
std::vector<std::string> log;
|
|
217
|
+
evalSrc(src, [&](const std::string& m) { log.push_back(m); });
|
|
218
|
+
EXPECT_EQ(log, want) << src;
|
|
219
|
+
}
|
|
220
|
+
Evaluated em = evalSrc("text(\"A\", em=10, $fn=32);");
|
|
221
|
+
Evaluated size = evalSrc("text(\"A\", size=7.2, $fn=32);");
|
|
222
|
+
EXPECT_NEAR(em.bodies[0].section->Area(), size.bodies[0].section->Area(), 1e-9);
|
|
223
|
+
}
|
|
224
|
+
|
|
195
225
|
// -- fontmetrics() --------------------------------------------------------
|
|
196
226
|
|
|
197
227
|
TEST(Fontmetrics, ReturnsAllExpectedKeysInOrder) {
|
|
File without changes
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.38.1 → openscad_cpp_evaluator-1.40.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|