openscad-cpp-evaluator 1.28.1__tar.gz → 1.28.2__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.28.1 → openscad_cpp_evaluator-1.28.2}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/text_metrics.hpp +13 -3
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/function_builtins.cpp +4 -4
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/text.cpp +3 -3
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/text/freetype_font_provider.cpp +41 -6
- openscad_cpp_evaluator-1.28.2/src/text/text_metrics.cpp +80 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_text.cpp +36 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/uv.lock +1 -1
- openscad_cpp_evaluator-1.28.1/src/text/text_metrics.cpp +0 -70
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/README.md +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/tools/cli/main.cpp +0 -0
|
@@ -12,7 +12,12 @@ namespace oscadeval {
|
|
|
12
12
|
// for `size`. `glyphs` is what text() places: each shaped glyph with its
|
|
13
13
|
// pen position, already scaled. An inkless glyph (a space) still advances
|
|
14
14
|
// the pen and still gets a glyphs entry -- it just contributes nothing to
|
|
15
|
-
// ascent/descent
|
|
15
|
+
// the ink box or ascent/descent.
|
|
16
|
+
//
|
|
17
|
+
// As in OpenSCAD's ShapeResults: left/right/bottom/top is the ink box of the
|
|
18
|
+
// glyphs where they are placed, while ascent/descent are the glyphs' own
|
|
19
|
+
// extents above and below THEIR baseline, ignoring where they sit. The two
|
|
20
|
+
// only differ for a vertical run or a glyph the shaper offsets (a mark).
|
|
16
21
|
//
|
|
17
22
|
// The run comes from the shaper, so kerning and ligatures are already
|
|
18
23
|
// applied and `spacing` scales the shaped advances rather than raw
|
|
@@ -23,8 +28,11 @@ struct TextMeasurement {
|
|
|
23
28
|
double x = 0, y = 0;
|
|
24
29
|
};
|
|
25
30
|
|
|
26
|
-
double ascent = 0, descent = 0
|
|
31
|
+
double ascent = 0, descent = 0;
|
|
32
|
+
double left = 0, right = 0, bottom = 0, top = 0;
|
|
27
33
|
double advanceX = 0, advanceY = 0;
|
|
34
|
+
bool hasInk = false;
|
|
35
|
+
bool vertical = false; // shaped ttb/btt
|
|
28
36
|
std::vector<Placed> glyphs;
|
|
29
37
|
};
|
|
30
38
|
|
|
@@ -32,7 +40,9 @@ TextMeasurement measureText(FontProvider& fp, FontHandle handle, const std::stri
|
|
|
32
40
|
double spacing, const ShapeOptions& opts = {});
|
|
33
41
|
|
|
34
42
|
// (offsetX, offsetY) translation for halign/valign, given a
|
|
35
|
-
// TextMeasurement.
|
|
43
|
+
// TextMeasurement. "default" is left/baseline for a horizontal run and
|
|
44
|
+
// center/top for a vertical one, as in OpenSCAD; text with no ink is not
|
|
45
|
+
// moved at all. Shared by textmetrics() (reports it) and text()
|
|
36
46
|
// (applies it).
|
|
37
47
|
std::pair<double, double> textAlignOffset(const std::string& halign, const std::string& valign,
|
|
38
48
|
const TextMeasurement& m);
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -792,8 +792,8 @@ Value builtinTextmetrics(Evaluator& ev, const CallArgs& args) {
|
|
|
792
792
|
// `font` being name-only here is what made
|
|
793
793
|
// `textmetrics("Hi", 10, "Liberation Sans:style=Bold")` silently
|
|
794
794
|
// measure the default face (BelfrySCAD #381).
|
|
795
|
-
const std::string halign = asStringOr(getArg(args, 6, "halign", Value{std::string("
|
|
796
|
-
const std::string valign = asStringOr(getArg(args, 7, "valign", Value{std::string("
|
|
795
|
+
const std::string halign = asStringOr(getArg(args, 6, "halign", Value{std::string("default")}), "default");
|
|
796
|
+
const std::string valign = asStringOr(getArg(args, 7, "valign", Value{std::string("default")}), "default");
|
|
797
797
|
const double spacing = toDoubleLenient(getArg(args, 8, "spacing", Value{1.0}));
|
|
798
798
|
const std::string fontSpec = asStringOr(getArg(args, 2, "font", Value{std::string("")}), "");
|
|
799
799
|
ShapeOptions shape;
|
|
@@ -807,8 +807,8 @@ Value builtinTextmetrics(Evaluator& ev, const CallArgs& args) {
|
|
|
807
807
|
const auto [offsetX, offsetY] = textAlignOffset(halign, valign, m);
|
|
808
808
|
|
|
809
809
|
return objectOf({
|
|
810
|
-
{"position", numList({offsetX + m.
|
|
811
|
-
{"size", numList({m.
|
|
810
|
+
{"position", numList({offsetX + m.left, offsetY + m.bottom})},
|
|
811
|
+
{"size", numList({m.right - m.left, m.top - m.bottom})},
|
|
812
812
|
{"ascent", Value{m.ascent}},
|
|
813
813
|
{"descent", Value{m.descent}},
|
|
814
814
|
{"offset", numList({offsetX, offsetY})},
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include <algorithm>
|
|
9
9
|
|
|
10
|
-
// text(text=, size=10, font=, halign="
|
|
10
|
+
// text(text=, size=10, 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).
|
|
@@ -46,8 +46,8 @@ CSGParams resolveText(Evaluator& ev, const oscad::ModularCall& node, EvalContext
|
|
|
46
46
|
// genuinely differ here -- textmetrics takes all nine positionally --
|
|
47
47
|
// so neither can be assumed from the other.
|
|
48
48
|
const std::string fontSpec = asStringOr(getArg(args, 2, "font", Value{std::string("")}), "");
|
|
49
|
-
const std::string halign = asStringOr(getArg(args, std::nullopt, "halign", Value{std::string("
|
|
50
|
-
const std::string valign = asStringOr(getArg(args, std::nullopt, "valign", Value{std::string("
|
|
49
|
+
const std::string halign = asStringOr(getArg(args, std::nullopt, "halign", Value{std::string("default")}), "default");
|
|
50
|
+
const std::string valign = asStringOr(getArg(args, std::nullopt, "valign", Value{std::string("default")}), "default");
|
|
51
51
|
const double spacing = toDoubleLenient(getArg(args, std::nullopt, "spacing", Value{1.0}));
|
|
52
52
|
ShapeOptions shape;
|
|
53
53
|
shape.direction = asStringOr(getArg(args, std::nullopt, "direction", Value{std::string("")}), "");
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/src/text/freetype_font_provider.cpp
RENAMED
|
@@ -31,6 +31,45 @@ void scaleHbFontToEm(hb_font_t* font, unsigned int unitsPerEm) {
|
|
|
31
31
|
hb_font_set_scale(font, static_cast<int>(unitsPerEm), static_cast<int>(unitsPerEm));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Vertical metrics come from FreeType, as they do in OpenSCAD (which shapes
|
|
35
|
+
// through hb-ft). For a font with no vmtx -- nearly every Latin font,
|
|
36
|
+
// Liberation Sans included -- the two disagree: hb-ot falls back to hhea
|
|
37
|
+
// ascender-descender, FreeType to OS/2 typo ascender-descender, so a ttb
|
|
38
|
+
// run of "abc" was 46.5 tall here and 39.1 there. Mirrors hb-ft's own
|
|
39
|
+
// callbacks; font units in and out, since the hb font is scaled to the em.
|
|
40
|
+
hb_position_t ftVAdvance(hb_font_t*, void* data, hb_codepoint_t glyph, void*) {
|
|
41
|
+
FT_Face ft = static_cast<FT_Face>(data);
|
|
42
|
+
if (FT_Load_Glyph(ft, glyph, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT) != 0) return 0;
|
|
43
|
+
return static_cast<hb_position_t>(-ft->glyph->metrics.vertAdvance); // FreeType's vertical grows downward
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
hb_bool_t ftVOrigin(hb_font_t*, void* data, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void*) {
|
|
47
|
+
FT_Face ft = static_cast<FT_Face>(data);
|
|
48
|
+
if (FT_Load_Glyph(ft, glyph, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT) != 0) return false;
|
|
49
|
+
const FT_Glyph_Metrics& m = ft->glyph->metrics;
|
|
50
|
+
*x = static_cast<hb_position_t>(m.horiBearingX - m.vertBearingX);
|
|
51
|
+
*y = static_cast<hb_position_t>(m.horiBearingY + m.vertBearingY);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// hb-ot for everything, with the vertical metrics overridden by FreeType.
|
|
56
|
+
hb_font_t* makeHbFont(hb_face_t* face, FT_Face ft, unsigned int unitsPerEm) {
|
|
57
|
+
static hb_font_funcs_t* vfuncs = [] {
|
|
58
|
+
hb_font_funcs_t* f = hb_font_funcs_create();
|
|
59
|
+
hb_font_funcs_set_glyph_v_advance_func(f, ftVAdvance, nullptr, nullptr);
|
|
60
|
+
hb_font_funcs_set_glyph_v_origin_func(f, ftVOrigin, nullptr, nullptr);
|
|
61
|
+
hb_font_funcs_make_immutable(f);
|
|
62
|
+
return f;
|
|
63
|
+
}();
|
|
64
|
+
hb_font_t* parent = hb_font_create(face);
|
|
65
|
+
hb_ot_font_set_funcs(parent);
|
|
66
|
+
scaleHbFontToEm(parent, unitsPerEm);
|
|
67
|
+
hb_font_t* font = hb_font_create_sub_font(parent); // everything unset delegates to parent
|
|
68
|
+
hb_font_destroy(parent);
|
|
69
|
+
hb_font_set_funcs(font, vfuncs, ft, nullptr);
|
|
70
|
+
return font;
|
|
71
|
+
}
|
|
72
|
+
|
|
34
73
|
struct OutlineSink {
|
|
35
74
|
GlyphContours contours;
|
|
36
75
|
std::vector<std::array<double, 2>> current;
|
|
@@ -159,10 +198,8 @@ struct FreetypeFontProvider::Impl {
|
|
|
159
198
|
return std::nullopt;
|
|
160
199
|
}
|
|
161
200
|
f.hbFace = hb_face_create(f.blob, static_cast<unsigned>(index));
|
|
162
|
-
f.hbFont = hb_font_create(f.hbFace);
|
|
163
|
-
hb_ot_font_set_funcs(f.hbFont);
|
|
164
201
|
f.metrics = readMetrics(f.ft);
|
|
165
|
-
|
|
202
|
+
f.hbFont = makeHbFont(f.hbFace, f.ft, static_cast<unsigned>(f.metrics.unitsPerEm));
|
|
166
203
|
faces.push_back(f);
|
|
167
204
|
return faces.size() - 1;
|
|
168
205
|
}
|
|
@@ -185,10 +222,8 @@ struct FreetypeFontProvider::Impl {
|
|
|
185
222
|
f.blob = hb_blob_create(reinterpret_cast<const char*>(src.data),
|
|
186
223
|
static_cast<unsigned>(src.size), HB_MEMORY_MODE_READONLY, nullptr, nullptr);
|
|
187
224
|
f.hbFace = hb_face_create(f.blob, 0);
|
|
188
|
-
f.hbFont = hb_font_create(f.hbFace);
|
|
189
|
-
hb_ot_font_set_funcs(f.hbFont);
|
|
190
225
|
f.metrics = readMetrics(f.ft);
|
|
191
|
-
|
|
226
|
+
f.hbFont = makeHbFont(f.hbFace, f.ft, static_cast<unsigned>(f.metrics.unitsPerEm));
|
|
192
227
|
faces.push_back(f);
|
|
193
228
|
}
|
|
194
229
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#include "openscad_cpp_evaluator/text_metrics.hpp"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cctype>
|
|
5
|
+
|
|
6
|
+
namespace oscadeval {
|
|
7
|
+
|
|
8
|
+
TextMeasurement measureText(FontProvider& fp, FontHandle handle, const std::string& text, double size,
|
|
9
|
+
double spacing, const ShapeOptions& opts) {
|
|
10
|
+
const FontMetrics fm = fp.metrics(handle);
|
|
11
|
+
// The 100/72 factor is real OpenSCAD's long-standing text() size bug
|
|
12
|
+
// (its issue #4304: FT_Set_Char_Size is given 100 dpi where 72 is
|
|
13
|
+
// correct, making glyphs ~1.39x the nominal size). It is reproduced
|
|
14
|
+
// deliberately -- a decade of models are drawn to it, and OpenSCAD
|
|
15
|
+
// itself chose to keep the bug and add an `em=` parameter rather than
|
|
16
|
+
// fix it.
|
|
17
|
+
const double scale = size * (100.0 / 72.0) / fm.unitsPerEm;
|
|
18
|
+
|
|
19
|
+
TextMeasurement m;
|
|
20
|
+
// hb_direction_from_string reads only the first letter, so this is
|
|
21
|
+
// exactly the set of strings the shaper takes as vertical.
|
|
22
|
+
const char d = opts.direction.empty() ? 'l' : static_cast<char>(std::tolower(opts.direction[0]));
|
|
23
|
+
m.vertical = d == 't' || d == 'b';
|
|
24
|
+
double penX = 0.0, penY = 0.0;
|
|
25
|
+
|
|
26
|
+
for (const ShapedGlyph& g : fp.shapeText(handle, text, opts)) {
|
|
27
|
+
const double x = (penX + g.xOffset) * scale;
|
|
28
|
+
const double y = (penY + g.yOffset) * scale;
|
|
29
|
+
|
|
30
|
+
if (const std::optional<std::array<double, 4>> b = fp.glyphInkBounds(handle, g.glyph)) {
|
|
31
|
+
const double gl = x + (*b)[0] * scale, gr = x + (*b)[2] * scale;
|
|
32
|
+
const double gb = y + (*b)[1] * scale, gt = y + (*b)[3] * scale;
|
|
33
|
+
const double asc = (*b)[3] * scale, desc = (*b)[1] * scale;
|
|
34
|
+
if (!m.hasInk) {
|
|
35
|
+
m.left = gl, m.right = gr, m.bottom = gb, m.top = gt;
|
|
36
|
+
m.ascent = asc, m.descent = desc;
|
|
37
|
+
m.hasInk = true;
|
|
38
|
+
} else {
|
|
39
|
+
m.left = std::min(m.left, gl);
|
|
40
|
+
m.right = std::max(m.right, gr);
|
|
41
|
+
m.bottom = std::min(m.bottom, gb);
|
|
42
|
+
m.top = std::max(m.top, gt);
|
|
43
|
+
m.ascent = std::max(m.ascent, asc);
|
|
44
|
+
m.descent = std::min(m.descent, desc);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
m.glyphs.push_back(TextMeasurement::Placed{g.glyph, x, y});
|
|
49
|
+
penX += g.xAdvance * spacing;
|
|
50
|
+
penY += g.yAdvance * spacing;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
m.advanceX = penX * scale;
|
|
54
|
+
m.advanceY = penY * scale;
|
|
55
|
+
return m;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// OpenSCAD's ShapeResults::calc_offsets_horiz/_vert. An unknown value (and,
|
|
59
|
+
// for a vertical run, valign="baseline") does not move the text there
|
|
60
|
+
// either; OpenSCAD also warns, which this does not.
|
|
61
|
+
std::pair<double, double> textAlignOffset(const std::string& halign, const std::string& valign,
|
|
62
|
+
const TextMeasurement& m) {
|
|
63
|
+
if (!m.hasInk) return {0.0, 0.0};
|
|
64
|
+
double offsetX = 0.0, offsetY = 0.0;
|
|
65
|
+
if (m.vertical) {
|
|
66
|
+
if (halign == "right") offsetX = -m.right;
|
|
67
|
+
else if (halign == "left") offsetX = -m.left;
|
|
68
|
+
if (valign == "center") offsetY = -m.advanceY / 2;
|
|
69
|
+
else if (valign == "bottom") offsetY = -m.advanceY;
|
|
70
|
+
} else {
|
|
71
|
+
if (halign == "center") offsetX = -0.5 * m.advanceX;
|
|
72
|
+
else if (halign == "right") offsetX = -m.advanceX;
|
|
73
|
+
if (valign == "top") offsetY = -m.ascent;
|
|
74
|
+
else if (valign == "center") offsetY = -(m.ascent + m.descent) / 2;
|
|
75
|
+
else if (valign == "bottom") offsetY = -m.descent;
|
|
76
|
+
}
|
|
77
|
+
return {offsetX, offsetY};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
} // namespace oscadeval
|
|
@@ -97,6 +97,42 @@ TEST(Textmetrics, AdvanceXIsPositiveForNonEmptyText) {
|
|
|
97
97
|
EXPECT_DOUBLE_EQ(asNum(items[1]), 0.0);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// Vertical runs, against OpenSCAD 2026.02.01 (it hints, so ~0.01 apart).
|
|
101
|
+
// Its vertical metrics are FreeType's -- OS/2 typo ascender-descender for a
|
|
102
|
+
// font without vmtx -- not hb-ot's hhea fallback, which gave 46.5 here.
|
|
103
|
+
namespace {
|
|
104
|
+
double vec(const Value& obj, const std::string& key, int i) {
|
|
105
|
+
return asNum(std::get<ListPtr>(objGet(obj, key))->items[i]);
|
|
106
|
+
}
|
|
107
|
+
} // namespace
|
|
108
|
+
|
|
109
|
+
TEST(Textmetrics, VerticalRunMatchesOpenscad) {
|
|
110
|
+
Evaluator ev;
|
|
111
|
+
Value v = asExpr("textmetrics(\"abc\", size=10, direction=\"ttb\")", ev);
|
|
112
|
+
EXPECT_NEAR(vec(v, "advance", 1), -39.1032, 1e-3);
|
|
113
|
+
EXPECT_NEAR(vec(v, "position", 0), -3.2733, 0.01);
|
|
114
|
+
EXPECT_NEAR(vec(v, "position", 1), -36.3957, 0.01);
|
|
115
|
+
EXPECT_NEAR(vec(v, "size", 1), 33.6848, 0.01);
|
|
116
|
+
EXPECT_NEAR(asNum(objGet(v, "ascent")), 10.0672, 0.01); // the glyphs' own, not their placement
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
TEST(Textmetrics, VerticalRunAlignsByItsOwnRules) {
|
|
120
|
+
Evaluator ev;
|
|
121
|
+
Value lc = asExpr("textmetrics(\"abc\", size=10, direction=\"ttb\", halign=\"left\", valign=\"center\")", ev);
|
|
122
|
+
EXPECT_NEAR(vec(lc, "offset", 0), 3.2733, 0.01);
|
|
123
|
+
EXPECT_NEAR(vec(lc, "offset", 1), 19.5516, 1e-3);
|
|
124
|
+
Value rb = asExpr("textmetrics(\"abc\", size=10, direction=\"ttb\", halign=\"right\", valign=\"bottom\")", ev);
|
|
125
|
+
EXPECT_NEAR(vec(rb, "offset", 0), -3.8627, 0.01);
|
|
126
|
+
EXPECT_NEAR(vec(rb, "offset", 1), 39.1032, 1e-3);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
TEST(Textmetrics, InklessTextIsNotAligned) {
|
|
130
|
+
Evaluator ev;
|
|
131
|
+
Value v = asExpr("textmetrics(\" \", size=10, halign=\"right\")", ev);
|
|
132
|
+
EXPECT_EQ(vec(v, "offset", 0), 0.0);
|
|
133
|
+
EXPECT_GT(vec(v, "advance", 0), 7.0);
|
|
134
|
+
}
|
|
135
|
+
|
|
100
136
|
TEST(Textmetrics, AscentIsPositiveDescentIsNonPositive) {
|
|
101
137
|
Evaluator ev;
|
|
102
138
|
Value v = asExpr("textmetrics(text=\"Hi\", size=10)", ev);
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
#include "openscad_cpp_evaluator/text_metrics.hpp"
|
|
2
|
-
|
|
3
|
-
#include <algorithm>
|
|
4
|
-
|
|
5
|
-
namespace oscadeval {
|
|
6
|
-
|
|
7
|
-
TextMeasurement measureText(FontProvider& fp, FontHandle handle, const std::string& text, double size,
|
|
8
|
-
double spacing, const ShapeOptions& opts) {
|
|
9
|
-
const FontMetrics fm = fp.metrics(handle);
|
|
10
|
-
// The 100/72 factor is real OpenSCAD's long-standing text() size bug
|
|
11
|
-
// (its issue #4304: FT_Set_Char_Size is given 100 dpi where 72 is
|
|
12
|
-
// correct, making glyphs ~1.39x the nominal size). It is reproduced
|
|
13
|
-
// deliberately -- a decade of models are drawn to it, and OpenSCAD
|
|
14
|
-
// itself chose to keep the bug and add an `em=` parameter rather than
|
|
15
|
-
// fix it.
|
|
16
|
-
const double scale = size * (100.0 / 72.0) / fm.unitsPerEm;
|
|
17
|
-
|
|
18
|
-
TextMeasurement m;
|
|
19
|
-
double penX = 0.0, penY = 0.0;
|
|
20
|
-
bool hasInk = false;
|
|
21
|
-
|
|
22
|
-
for (const ShapedGlyph& g : fp.shapeText(handle, text, opts)) {
|
|
23
|
-
const double x = (penX + g.xOffset) * scale;
|
|
24
|
-
const double y = (penY + g.yOffset) * scale;
|
|
25
|
-
|
|
26
|
-
if (const std::optional<std::array<double, 4>> b = fp.glyphInkBounds(handle, g.glyph)) {
|
|
27
|
-
const double left = x + (*b)[0] * scale;
|
|
28
|
-
const double right = x + (*b)[2] * scale;
|
|
29
|
-
const double bottom = y + (*b)[1] * scale;
|
|
30
|
-
const double top = y + (*b)[3] * scale;
|
|
31
|
-
if (!hasInk) {
|
|
32
|
-
m.inkMinX = left;
|
|
33
|
-
m.inkMaxX = right;
|
|
34
|
-
m.ascent = top;
|
|
35
|
-
m.descent = bottom;
|
|
36
|
-
hasInk = true;
|
|
37
|
-
} else {
|
|
38
|
-
m.inkMinX = std::min(m.inkMinX, left);
|
|
39
|
-
m.inkMaxX = std::max(m.inkMaxX, right);
|
|
40
|
-
m.ascent = std::max(m.ascent, top);
|
|
41
|
-
m.descent = std::min(m.descent, bottom);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
m.glyphs.push_back(TextMeasurement::Placed{g.glyph, x, y});
|
|
46
|
-
penX += g.xAdvance * spacing;
|
|
47
|
-
penY += g.yAdvance * spacing;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
m.advanceX = penX * scale;
|
|
51
|
-
m.advanceY = penY * scale;
|
|
52
|
-
return m;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
std::pair<double, double> textAlignOffset(const std::string& halign, const std::string& valign,
|
|
56
|
-
const TextMeasurement& m) {
|
|
57
|
-
double offsetX = 0.0;
|
|
58
|
-
if (halign == "center") offsetX = -0.5 * m.advanceX;
|
|
59
|
-
else if (halign == "right") offsetX = -1.0 * m.advanceX;
|
|
60
|
-
|
|
61
|
-
double offsetY = 0.0;
|
|
62
|
-
if (valign == "top") offsetY = -m.ascent;
|
|
63
|
-
else if (valign == "center") offsetY = -(m.ascent + m.descent) / 2;
|
|
64
|
-
else if (valign == "bottom") offsetY = -m.descent;
|
|
65
|
-
// "baseline" (or anything else) -> 0
|
|
66
|
-
|
|
67
|
-
return {offsetX, offsetY};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
} // namespace oscadeval
|
|
File without changes
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/.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
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.28.1 → openscad_cpp_evaluator-1.28.2}/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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|