ea 0.3.1 → 0.5.0
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.
- checksums.yaml +4 -4
- data/Rakefile +3 -0
- data/TODO.complete/01-t-xref-parsing.md +91 -0
- data/TODO.complete/02-per-label-geometry.md +50 -0
- data/TODO.complete/03-object-properties-constraints.md +57 -0
- data/TODO.complete/04-operation-params.md +37 -0
- data/TODO.complete/05-pdata-flag-matrix.md +52 -0
- data/TODO.complete/06-emf-image-rendering.md +34 -0
- data/TODO.complete/07-auxiliary-tables.md +47 -0
- data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
- data/TODO.complete/11-gml-xsd-generation.md +42 -0
- data/TODO.complete/13-shapescript-interpreter.md +28 -0
- data/TODO.complete/20-cli-diff.md +46 -0
- data/TODO.complete/21-cli-render.md +26 -0
- data/TODO.complete/22-cli-export.md +29 -0
- data/TODO.complete/23-cli-mdg.md +23 -0
- data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
- data/TODO.complete/31-public-send-cleanup.md +61 -0
- data/TODO.complete/32-spec-coverage.md +33 -0
- data/TODO.complete/33-blocked-parity-gaps.md +41 -0
- data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
- data/TODO.complete/37-cli-lint.md +32 -0
- data/TODO.complete/38-cli-query.md +26 -0
- data/TODO.complete/39-cli-info.md +23 -0
- data/TODO.complete/40-ocl-evaluator.md +31 -0
- data/TODO.complete/41-round-trip-spec.md +18 -0
- data/TODO.complete/42-html-diff-report.md +18 -0
- data/TODO.complete/43-json-schema-export.md +20 -0
- data/TODO.complete/44-remaining-qea-tables.md +40 -0
- data/TODO.complete/45-shapescript-extensions.md +25 -0
- data/TODO.complete/46-xsd-consolidation.md +20 -0
- data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
- data/TODO.complete/STATUS.md +109 -0
- data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
- data/TODO.diagrams/01-xmi-extension-elements-parsing.md +67 -0
- data/TODO.diagrams/02-diagram-element-rich-model.md +61 -0
- data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-ea-style-svg-emitter.md +70 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-connector-routing-from-soid-eoid.md +55 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/05-marker-rendering-per-relationship-type.md +49 -0
- data/TODO.diagrams/06-connector-labels.md +49 -0
- data/TODO.diagrams/06-group-layering-parity.md +39 -0
- data/TODO.diagrams/07-canvas-size-and-viewbox.md +39 -0
- data/TODO.diagrams/07-text-content-fidelity.md +65 -0
- data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
- data/TODO.diagrams/08-visual-regression-harness.md +34 -0
- data/TODO.diagrams/09-cli-render-all-diagrams.md +25 -0
- data/TODO.diagrams/10-stereotype-color-config.md +29 -0
- data/TODO.diagrams/11-elkrb-auto-layout-integration.md +53 -0
- data/TODO.diagrams/12-connector-labels.md +40 -0
- data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
- data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
- data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
- data/TODO.diagrams/14-center-header-text.md +33 -0
- data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
- data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
- data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
- data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
- data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
- data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
- data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
- data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
- data/TODO.diagrams/18-property-lookup-index.md +42 -0
- data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
- data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
- data/TODO.diagrams/20-split-labels-emitter.md +56 -0
- data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
- data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
- data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
- data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
- data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
- data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
- data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
- data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
- data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
- data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
- data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
- data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
- data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
- data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
- data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
- data/TODO.diagrams/36-instance-specification-model.md +42 -0
- data/TODO.diagrams/37-element-icon-decorations.md +41 -0
- data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
- data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
- data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
- data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
- data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
- data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
- data/TODO.diagrams/44-element-icon-decorations.md +34 -0
- data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
- data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
- data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
- data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
- data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
- data/TODO.diagrams/50-examples-parity.md +85 -0
- data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
- data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
- data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
- data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
- data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
- data/TODO.diagrams/56-package-contents-rendering.md +148 -0
- data/TODO.diagrams/57-instance-specification-model.md +100 -0
- data/TODO.diagrams/58-domain-model-note-text.md +67 -0
- data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
- data/TODO.diagrams/60-testschema-association-marker.md +40 -0
- data/TODO.diagrams/61-legend-block-rendering.md +55 -0
- data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
- data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
- data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
- data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
- data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/68-inherited-attributes.md +65 -0
- data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
- data/TODO.diagrams/70-mdg-technology-support.md +68 -0
- data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
- data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
- data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
- data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
- data/TODO.diagrams/75-plateau-text-gap.md +39 -0
- data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
- data/TODO.diagrams/77-basic-text-overrender.md +40 -0
- data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
- data/TODO.diagrams/79-architecture-backlog.md +65 -0
- data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
- data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
- data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
- data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
- data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
- data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
- data/TODO.diagrams/86-foreign-package-rule.md +62 -0
- data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
- data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
- data/TODO.diagrams/README.md +69 -0
- data/TODO.diagrams/STATUS.md +73 -0
- data/TODO.fixup/01-default-grouped-paths.md +34 -0
- data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
- data/TODO.fixup/03-diagram-font-inference.md +28 -0
- data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
- data/TODO.fixup/05-marker-registry-ocp.md +32 -0
- data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
- data/TODO.fixup/07-edge-attachment-formula.md +22 -0
- data/TODO.fixup/08-visual-diff-harness.md +28 -0
- data/TODO.fixup/09-extract-element-compartments.md +34 -0
- data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
- data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
- data/TODO.fixup/12-path-style-harmony.md +23 -0
- data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
- data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
- data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
- data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
- data/TODO.fixup/17-path-count-calibration.md +27 -0
- data/TODO.fixup/18-polygon-count-calibration.md +32 -0
- data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
- data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
- data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
- data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
- data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
- data/TODO.fixup/24-note-element-rendering.md +23 -0
- data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
- data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
- data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
- data/TODO.fixup/28-geometry-parser-identification.md +57 -0
- data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
- data/TODO.fixup/30-theme-system-stub.md +46 -0
- data/TODO.fixup/31-theme-value-object-registry.md +17 -0
- data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
- data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
- data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
- data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
- data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
- data/TODO.fixup/37-package-shape-rendering.md +22 -0
- data/TODO.fixup/38-note-element-rendering.md +15 -0
- data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
- data/TODO.fixup/40-connector-dashed-lines.md +15 -0
- data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
- data/TODO.fixup/42-textrenderer-centralization.md +10 -0
- data/TODO.fixup/43-colorresolver-unification.md +24 -0
- data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
- data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
- data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
- data/TODO.fixup/47-canvas-frame-inset.md +19 -0
- data/TODO.fixup/48-background-rect-format.md +15 -0
- data/TODO.fixup/49-all-samples-integration-test.md +17 -0
- data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
- data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
- data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
- data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
- data/TODO.fixup/54-diagram-theme-api.md +50 -0
- data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
- data/TODO.fixup/56-theme-yaml-files.md +65 -0
- data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
- data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
- data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
- data/TODO.fixup/60-cli-theme-option.md +22 -0
- data/TODO.fixup/61-theme-validation.md +28 -0
- data/TODO.fixup/62-theme-builder-dsl.md +31 -0
- data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
- data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
- data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
- data/TODO.fixup/66-styleex-writeback.md +22 -0
- data/TODO.fixup/67-delete-dead-code.md +28 -0
- data/TODO.fixup/68-figure-parity-status.md +82 -0
- data/TODO.fixup/69-package-polygon-rendering.md +54 -0
- data/TODO.fixup/70-tagged-values-compartment.md +39 -0
- data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
- data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
- data/TODO.fixup/73-delete-dead-transformations.md +14 -0
- data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
- data/TODO.fixup/75-visibility-legend-icons.md +23 -0
- data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
- data/TODO.fixup/77-canvas-frame-margins.md +28 -0
- data/TODO.fixup/78-note-element-rendering.md +30 -0
- data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
- data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
- data/TODO.fixup/81-figure-parity-current-state.md +63 -0
- data/config/qea_schema.yml +356 -0
- data/config/stereotype_colors.yml +15 -0
- data/config/themes/119.yml +98 -0
- data/config/themes/default.yml +14 -0
- data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
- data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
- data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
- data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
- data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
- data/examples/exports/UmlModel_template/model.xml +23 -0
- data/examples/exports/basic/UML_EA.DTD +6856 -0
- data/examples/exports/basic/model.xml +8039 -0
- data/examples/exports/simple/UML_EA.DTD +6856 -0
- data/examples/exports/simple/model.xml +585 -0
- data/examples/exports/simple_example/UML_EA.DTD +6856 -0
- data/examples/exports/simple_example/model.xml +23 -0
- data/examples/exports/test/UML_EA.DTD +6856 -0
- data/examples/exports/test/model.xml +1638 -0
- data/examples/qea/basic.qea +0 -0
- data/frontend/README.md +51 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/dist/style.css +1 -0
- data/frontend/index.html +26 -0
- data/frontend/package-lock.json +2359 -0
- data/frontend/package.json +26 -0
- data/frontend/src/App.vue +59 -0
- data/frontend/src/app.ts +8 -0
- data/frontend/src/components/AppHeader.vue +127 -0
- data/frontend/src/components/AppSidebar.vue +119 -0
- data/frontend/src/components/ClassDetails.vue +247 -0
- data/frontend/src/components/DiagramView.vue +79 -0
- data/frontend/src/components/PackageDetails.vue +92 -0
- data/frontend/src/components/PackageTreeNode.vue +64 -0
- data/frontend/src/components/SearchResults.vue +48 -0
- data/frontend/src/components/WelcomeView.vue +87 -0
- data/frontend/src/shims-vue.d.ts +5 -0
- data/frontend/src/stores/dataStore.ts +79 -0
- data/frontend/src/stores/uiStore.ts +167 -0
- data/frontend/src/styles/main.css +1566 -0
- data/frontend/src/types.ts +221 -0
- data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
- data/frontend/tests/e2e/render.spec.ts +188 -0
- data/frontend/tsconfig.json +20 -0
- data/frontend/vite.config.ts +26 -0
- data/frontend/vitest.config.ts +8 -0
- data/lib/ea/cli/app.rb +62 -1
- data/lib/ea/cli/command/diagrams.rb +37 -28
- data/lib/ea/cli/command/diff.rb +46 -0
- data/lib/ea/cli/command/export.rb +80 -0
- data/lib/ea/cli/command/info.rb +75 -0
- data/lib/ea/cli/command/lint.rb +48 -0
- data/lib/ea/cli/command/mdg.rb +98 -0
- data/lib/ea/cli/command/query.rb +34 -0
- data/lib/ea/cli/command/render.rb +135 -0
- data/lib/ea/cli/command/svg.rb +43 -6
- data/lib/ea/cli/command.rb +7 -0
- data/lib/ea/diagram/display_config.rb +184 -0
- data/lib/ea/diagram.rb +4 -41
- data/lib/ea/diff/change.rb +30 -0
- data/lib/ea/diff/comparator.rb +82 -0
- data/lib/ea/diff/html_reporter.rb +91 -0
- data/lib/ea/diff.rb +15 -0
- data/lib/ea/export/json/generator.rb +42 -0
- data/lib/ea/export/json.rb +12 -0
- data/lib/ea/export/json_schema/generator.rb +77 -0
- data/lib/ea/export/json_schema.rb +12 -0
- data/lib/ea/export/plantuml/generator.rb +73 -0
- data/lib/ea/export/plantuml.rb +12 -0
- data/lib/ea/export/xmi/generator.rb +77 -0
- data/lib/ea/export/xmi.rb +11 -0
- data/lib/ea/export/xsd/class_mapping.rb +65 -0
- data/lib/ea/export/xsd/generator.rb +142 -0
- data/lib/ea/export/xsd/namespace_registry.rb +82 -0
- data/lib/ea/export/xsd.rb +19 -0
- data/lib/ea/export.rb +14 -0
- data/lib/ea/image/emf_renderer.rb +42 -0
- data/lib/ea/image.rb +12 -0
- data/lib/ea/lint/engine.rb +30 -0
- data/lib/ea/lint/lint_rule.rb +38 -0
- data/lib/ea/lint/offense.rb +18 -0
- data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
- data/lib/ea/lint/rules/duplicate_name.rb +28 -0
- data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
- data/lib/ea/lint/rules/naming_convention.rb +44 -0
- data/lib/ea/lint/rules/orphan_element.rb +28 -0
- data/lib/ea/lint/rules.rb +14 -0
- data/lib/ea/lint.rb +13 -0
- data/lib/ea/mdg/document.rb +120 -0
- data/lib/ea/mdg/loader.rb +118 -0
- data/lib/ea/mdg/registry.rb +98 -0
- data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
- data/lib/ea/mdg/xml/applies_to.rb +18 -0
- data/lib/ea/mdg/xml/apply.rb +18 -0
- data/lib/ea/mdg/xml/content.rb +18 -0
- data/lib/ea/mdg/xml/documentation.rb +24 -0
- data/lib/ea/mdg/xml/stereotype.rb +28 -0
- data/lib/ea/mdg/xml/stereotypes.rb +18 -0
- data/lib/ea/mdg/xml/tag.rb +28 -0
- data/lib/ea/mdg/xml/tagged_values.rb +18 -0
- data/lib/ea/mdg/xml/technology.rb +28 -0
- data/lib/ea/mdg/xml/uml_profile.rb +22 -0
- data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
- data/lib/ea/mdg/xml.rb +24 -0
- data/lib/ea/mdg.rb +25 -0
- data/lib/ea/model/classifier.rb +4 -0
- data/lib/ea/model/constraint.rb +24 -0
- data/lib/ea/model/diagram.rb +85 -0
- data/lib/ea/model/diagram_connector.rb +53 -1
- data/lib/ea/model/diagram_element.rb +44 -0
- data/lib/ea/model/document.rb +47 -2
- data/lib/ea/model/ghost_label.rb +32 -0
- data/lib/ea/model/instance_specification.rb +34 -0
- data/lib/ea/model/legend.rb +43 -0
- data/lib/ea/model/legend_item.rb +26 -0
- data/lib/ea/model/note.rb +28 -0
- data/lib/ea/model/operation.rb +2 -0
- data/lib/ea/model/property.rb +2 -0
- data/lib/ea/model/relationship.rb +2 -0
- data/lib/ea/model/signal.rb +14 -0
- data/lib/ea/model/slot.rb +19 -0
- data/lib/ea/model.rb +8 -0
- data/lib/ea/ocl/evaluator.rb +94 -0
- data/lib/ea/ocl/nodes.rb +30 -0
- data/lib/ea/ocl/parser.rb +133 -0
- data/lib/ea/ocl/unsupported_error.rb +7 -0
- data/lib/ea/ocl.rb +13 -0
- data/lib/ea/qea/factory/document_builder.rb +24 -10
- data/lib/ea/qea/factory/generalization_builder.rb +9 -11
- data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
- data/lib/ea/qea/models/ea_author.rb +35 -0
- data/lib/ea/qea/models/ea_glossary.rb +34 -0
- data/lib/ea/qea/models/ea_image.rb +53 -0
- data/lib/ea/qea/models/ea_implement.rb +32 -0
- data/lib/ea/qea/models/ea_list.rb +42 -0
- data/lib/ea/qea/models/ea_object_effort.rb +34 -0
- data/lib/ea/qea/models/ea_object_problem.rb +37 -0
- data/lib/ea/qea/models/ea_object_require.rb +34 -0
- data/lib/ea/qea/models/ea_object_resource.rb +34 -0
- data/lib/ea/qea/models/ea_object_risk.rb +34 -0
- data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
- data/lib/ea/qea/models/ea_object_test.rb +35 -0
- data/lib/ea/qea/models/ea_object_trx.rb +34 -0
- data/lib/ea/qea/models/ea_operation.rb +7 -0
- data/lib/ea/qea/models/ea_palette.rb +30 -0
- data/lib/ea/qea/models/ea_palette_item.rb +36 -0
- data/lib/ea/qea/models/ea_phase.rb +40 -0
- data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
- data/lib/ea/qea/models/ea_secrypt.rb +34 -0
- data/lib/ea/qea/models/ea_version.rb +39 -0
- data/lib/ea/qea/models/ea_xref.rb +11 -1
- data/lib/ea/qea/models.rb +19 -0
- data/lib/ea/qea/services/database_loader.rb +22 -1
- data/lib/ea/query/builder.rb +108 -0
- data/lib/ea/query.rb +9 -0
- data/lib/ea/render/image_converter.rb +101 -0
- data/lib/ea/render.rb +10 -0
- data/lib/ea/shapescript/parser.rb +208 -0
- data/lib/ea/shapescript/renderer.rb +74 -0
- data/lib/ea/shapescript/shape.rb +34 -0
- data/lib/ea/shapescript.rb +24 -0
- data/lib/ea/sources/qea/adapter.rb +22 -5
- data/lib/ea/sources/qea/classifier_builder.rb +184 -7
- data/lib/ea/sources/qea/diagram_builder.rb +352 -24
- data/lib/ea/sources/qea/id_normalizer.rb +16 -1
- data/lib/ea/sources/qea/instance_builder.rb +113 -0
- data/lib/ea/sources/qea/legend_builder.rb +137 -0
- data/lib/ea/sources/qea/note_builder.rb +58 -0
- data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
- data/lib/ea/sources/qea/operation_builder.rb +1 -0
- data/lib/ea/sources/qea/package_builder.rb +16 -0
- data/lib/ea/sources/qea/relationship_builder.rb +21 -5
- data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
- data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
- data/lib/ea/sources/qea/xref/parser.rb +150 -0
- data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
- data/lib/ea/sources/qea/xref/record.rb +41 -0
- data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
- data/lib/ea/sources/qea/xref.rb +27 -0
- data/lib/ea/sources/qea.rb +4 -0
- data/lib/ea/sources/xmi/adapter.rb +80 -2
- data/lib/ea/sources/xmi/annotation_builder.rb +1 -1
- data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +242 -45
- data/lib/ea/sources/xmi/extension_elements.rb +74 -0
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +124 -0
- data/lib/ea/sources/xmi/extension_style_parser.rb +91 -0
- data/lib/ea/sources/xmi/note_builder.rb +46 -0
- data/lib/ea/sources/xmi/property_builder.rb +9 -0
- data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
- data/lib/ea/sources/xmi/tag_builder.rb +45 -0
- data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
- data/lib/ea/sources/xmi.rb +7 -0
- data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
- data/lib/ea/spa/output/single_file_strategy.rb +8 -2
- data/lib/ea/spa/output/strategy.rb +34 -0
- data/lib/ea/svg/connector_router.rb +134 -0
- data/lib/ea/svg/ea_emitter/background.rb +15 -0
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +88 -0
- data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
- data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
- data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
- data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
- data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
- data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
- data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
- data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
- data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
- data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
- data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
- data/lib/ea/svg/ea_emitter/connectors.rb +84 -0
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +35 -0
- data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
- data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
- data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
- data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
- data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
- data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
- data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
- data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
- data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
- data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
- data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
- data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
- data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
- data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
- data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
- data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
- data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
- data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
- data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
- data/lib/ea/svg/ea_emitter/element.rb +37 -0
- data/lib/ea/svg/ea_emitter/elements.rb +357 -0
- data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
- data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
- data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
- data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
- data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
- data/lib/ea/svg/ea_emitter/label.rb +23 -0
- data/lib/ea/svg/ea_emitter/labels.rb +130 -0
- data/lib/ea/svg/ea_emitter/layer.rb +20 -0
- data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
- data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
- data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
- data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
- data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
- data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
- data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
- data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
- data/lib/ea/svg/ea_emitter/marker.rb +37 -0
- data/lib/ea/svg/ea_emitter/markers.rb +404 -0
- data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
- data/lib/ea/svg/ea_emitter/style.rb +15 -0
- data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
- data/lib/ea/svg/ea_emitter.rb +51 -0
- data/lib/ea/svg/parity/checker.rb +105 -0
- data/lib/ea/svg/parity/source.rb +59 -0
- data/lib/ea/svg/parity/suite.rb +113 -0
- data/lib/ea/svg/parity.rb +14 -0
- data/lib/ea/svg/stereotype_color_resolver.rb +50 -0
- data/lib/ea/svg.rb +4 -15
- data/lib/ea/theme/definition.rb +176 -0
- data/lib/ea/theme/loader.rb +125 -0
- data/lib/ea/theme/registry.rb +96 -0
- data/lib/ea/theme.rb +37 -0
- data/lib/ea/transformations.rb +5 -88
- data/lib/ea/version.rb +4 -1
- data/lib/ea.rb +14 -4
- data/lib/tasks/svg_bench.rake +87 -0
- data/lutaml-uml-0.5.1.gem +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
- metadata +473 -26
- data/lib/ea/diagram/configuration.rb +0 -379
- data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
- data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
- data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
- data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
- data/lib/ea/diagram/element_renderers.rb +0 -43
- data/lib/ea/diagram/extractor.rb +0 -566
- data/lib/ea/diagram/layout_engine.rb +0 -170
- data/lib/ea/diagram/path_builder.rb +0 -202
- data/lib/ea/diagram/style_parser.rb +0 -42
- data/lib/ea/diagram/style_resolver.rb +0 -291
- data/lib/ea/diagram/svg_renderer.rb +0 -274
- data/lib/ea/diagram/util.rb +0 -73
- data/lib/ea/svg/bounds_calculator.rb +0 -74
- data/lib/ea/svg/connector_path.rb +0 -138
- data/lib/ea/svg/element_box.rb +0 -256
- data/lib/ea/svg/renderer.rb +0 -77
- data/lib/ea/svg/style_resolver.rb +0 -72
- data/lib/ea/transformations/configuration.rb +0 -333
- data/lib/ea/transformations/format_registry.rb +0 -366
- data/lib/ea/transformations/parsers/base_parser.rb +0 -482
- data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
- data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
- data/lib/ea/transformations/transformation_engine.rb +0 -390
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 18 - Polygon Count Calibration
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, closed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
After TODO.fixup/17 removed aggregation arrows, the polygon
|
|
8
|
+
count diff dropped. Remaining 45 diagrams with polygon >+1
|
|
9
|
+
fall into two categories:
|
|
10
|
+
|
|
11
|
+
1. **Aggregation vs Composition fill rule**: EA may use open
|
|
12
|
+
(white-fill) diamonds for `shared` aggregation kind and
|
|
13
|
+
filled for `composite`. Our Diamond kind always emits
|
|
14
|
+
`:diamond_filled`. Verified the source XMI stores 205
|
|
15
|
+
Aggregations, 0 Compositions — so this rule doesn't apply
|
|
16
|
+
to this dataset.
|
|
17
|
+
|
|
18
|
+
2. **NoteLink / Package connector markers**: 18 Package +
|
|
19
|
+
14 NoteLink connectors in source. We currently emit no
|
|
20
|
+
markers for these. EA may render small icon-shaped polygons
|
|
21
|
+
for them.
|
|
22
|
+
|
|
23
|
+
## Decision
|
|
24
|
+
|
|
25
|
+
Closing as analyzed — no clear win available without source
|
|
26
|
+
data distinguishing `shared` vs `composite` aggregations.
|
|
27
|
+
Future XMI imports with explicit composition markers will
|
|
28
|
+
need the open-vs-filled diamond rule.
|
|
29
|
+
|
|
30
|
+
## Files changed
|
|
31
|
+
|
|
32
|
+
None.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 19 - Rect Count Undershoot Investigation
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25, analyzed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
The 78 diagrams with rect count undershoot have a consistent
|
|
8
|
+
pattern: each is missing 3 small ~17×17 px "visibility toggle"
|
|
9
|
+
icons at the right edge of certain element boxes.
|
|
10
|
+
|
|
11
|
+
Example from `EAID_0016F797_*.svg`:
|
|
12
|
+
```
|
|
13
|
+
x=470 y=344 w=17 h=17
|
|
14
|
+
x=470 y=363 w=17 h=17
|
|
15
|
+
x=470 y=382 w=17 h=17
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
These icons appear to be "feature visibility toggles" (private/
|
|
19
|
+
protected/public indicator) that EA renders on some diagrams
|
|
20
|
+
when the diagram's "show feature visibility" option is enabled.
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
Not implementing icon decoration rendering because:
|
|
25
|
+
|
|
26
|
+
1. **Visual complexity**: requires reverse-engineering the icon
|
|
27
|
+
shapes (likely small triangles or circles filled with
|
|
28
|
+
specific colors).
|
|
29
|
+
2. **Marginal benefit**: 3 small rects per diagram doesn't
|
|
30
|
+
significantly affect visual fidelity.
|
|
31
|
+
3. **Configuration-gated**: appears only on diagrams with a
|
|
32
|
+
specific display flag set — we'd need to plumb that flag
|
|
33
|
+
through.
|
|
34
|
+
|
|
35
|
+
If full parity on rect count is needed in the future, this is
|
|
36
|
+
the next target. Tracked as TODO.fixup/23.
|
|
37
|
+
|
|
38
|
+
## Files changed
|
|
39
|
+
|
|
40
|
+
None.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 20 - Stereotype Color from Classifier (Beyond BCol)
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
`Element::BColDecoder` now treats `-1` as a sentinel meaning "no
|
|
8
|
+
color override" and returns nil. `Elements#groups_for` falls
|
|
9
|
+
through to `fill_for_classifier` which consults the
|
|
10
|
+
`StereotypeColorResolver` for the classifier's stereotype.
|
|
11
|
+
|
|
12
|
+
Effect: elements with `BCol=-1` (sentinel) now pick up the
|
|
13
|
+
canonical color for their stereotype (e.g., yellow for
|
|
14
|
+
«FeatureType»).
|
|
15
|
+
|
|
16
|
+
## Files changed
|
|
17
|
+
|
|
18
|
+
- `lib/ea/svg/ea_emitter/element/bcol_decoder.rb` — SENTINEL constant
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 21 - Visibility Filter for Properties
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, closed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
Sampled 5 reference SVGs to check whether private members are
|
|
8
|
+
hidden. Findings:
|
|
9
|
+
|
|
10
|
+
- All sample diagrams render only `+ ` (public) visibility
|
|
11
|
+
markers
|
|
12
|
+
- No `-` (private) or `#` (protected) markers visible
|
|
13
|
+
- All classifier properties in the source XMI have visibility
|
|
14
|
+
unset (treated as public by default)
|
|
15
|
+
|
|
16
|
+
## Decision
|
|
17
|
+
|
|
18
|
+
No filter needed — the current "show all properties" rule
|
|
19
|
+
already matches EA's behavior for this dataset. Future XMI
|
|
20
|
+
imports with mixed-visibility properties may need a filter.
|
|
21
|
+
|
|
22
|
+
## Files changed
|
|
23
|
+
|
|
24
|
+
None.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 22 - Multiplicity Display Rule Calibration
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, closed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
Sampled reference SVGs and observed multiplicity rendering
|
|
8
|
+
patterns:
|
|
9
|
+
|
|
10
|
+
- Most attributes show `[0..1]` or `[0..*]` etc. in brackets
|
|
11
|
+
- A few diagrams show attribute text WITHOUT multiplicity
|
|
12
|
+
(e.g., `+ areaType: gml::CodeType`)
|
|
13
|
+
- The "no multiplicity" cases appear to be box-fit truncation
|
|
14
|
+
(text was too wide, multiplicity got clipped) rather than
|
|
15
|
+
a display rule
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
Keeping current rule: always render `[lower..upper]` except
|
|
20
|
+
when `1..1` (default — omitted). The truncation case is a
|
|
21
|
+
rendering artifact we don't need to replicate.
|
|
22
|
+
|
|
23
|
+
## Files changed
|
|
24
|
+
|
|
25
|
+
None.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 23 - Diagram Frame Title Element
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, deferred)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
EA diagrams include a "diagram frame" — a thin border with the
|
|
8
|
+
diagram name in the upper-left "tab" area. Three small 17x17
|
|
9
|
+
rects per diagram appear to be visibility-toggle icons.
|
|
10
|
+
|
|
11
|
+
Verified via rect count diff: 78 of 185 diagrams are missing
|
|
12
|
+
exactly 3 small rects. These appear only on diagrams with
|
|
13
|
+
Yu Gothic UI 13px font (which have explicit feature visibility
|
|
14
|
+
toggles enabled).
|
|
15
|
+
|
|
16
|
+
## Decision
|
|
17
|
+
|
|
18
|
+
Deferring implementation:
|
|
19
|
+
|
|
20
|
+
1. Requires reverse-engineering icon shapes (likely small
|
|
21
|
+
colored triangles or squares)
|
|
22
|
+
2. Visual benefit marginal — 3 small icons in upper corner
|
|
23
|
+
don't affect overall diagram comprehension
|
|
24
|
+
3. Time investment vs parity gain is poor
|
|
25
|
+
|
|
26
|
+
If pixel-perfect parity becomes a hard requirement, this is
|
|
27
|
+
the next target.
|
|
28
|
+
|
|
29
|
+
## Files changed
|
|
30
|
+
|
|
31
|
+
None.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 24 - Note Element Rendering
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, closed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
Source XMI has 14 NoteLink connectors (out of 891 total). Note
|
|
8
|
+
elements themselves would be classifiers with a specific
|
|
9
|
+
uml:type or stereotype.
|
|
10
|
+
|
|
11
|
+
Sampled the dataset: zero classifiers have a «note» or
|
|
12
|
+
«text» stereotype, and zero packagedElements have type
|
|
13
|
+
uml:Note or similar.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
No note elements in this dataset — closing as not applicable.
|
|
18
|
+
If future XMI imports include Note elements, this TODO
|
|
19
|
+
resurfaces.
|
|
20
|
+
|
|
21
|
+
## Files changed
|
|
22
|
+
|
|
23
|
+
None.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# 25 - EA.exe SVG Renderer Disassembly Findings
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Tools used
|
|
6
|
+
|
|
7
|
+
- Ghidra 11.0.3 PUBLIC (headless mode)
|
|
8
|
+
- brew binutils (gobjdump, gnm, gstrings)
|
|
9
|
+
- Python with binary scanning
|
|
10
|
+
|
|
11
|
+
## Discovery: UTF-16LE format string table
|
|
12
|
+
|
|
13
|
+
EA is a Unicode Windows app — all literal strings are stored as
|
|
14
|
+
UTF-16LE (wide chars), invisible to default `strings` searches.
|
|
15
|
+
By scanning for UTF-16LE patterns, I found the complete SVG
|
|
16
|
+
output format string table at:
|
|
17
|
+
|
|
18
|
+
File offset: 0x477c000 - 0x477e000
|
|
19
|
+
VMA: 0x04b7c000 - 0x04b7e000
|
|
20
|
+
Section: .rdata
|
|
21
|
+
|
|
22
|
+
The string `SVGRenderer.cpp` (file offset 0x477c424, VMA 0x04b7d624)
|
|
23
|
+
sits inside this table — it's the source-file marker for the
|
|
24
|
+
SVG output module. The assert at VMA 0x2e8f6d1 confirms this is
|
|
25
|
+
the SVGRenderer.
|
|
26
|
+
|
|
27
|
+
## Complete SVG format string table
|
|
28
|
+
|
|
29
|
+
Extracted via UTF-16LE decode of the 8KB region:
|
|
30
|
+
|
|
31
|
+
### Document envelope
|
|
32
|
+
```
|
|
33
|
+
cm" viewBox="0 0 %d %d">
|
|
34
|
+
<title>%s</title>
|
|
35
|
+
<desc>
|
|
36
|
+
</desc>
|
|
37
|
+
</g>
|
|
38
|
+
</svg>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Group `<g>`
|
|
42
|
+
```
|
|
43
|
+
<g style="%s %s %s" %s> (3-part style + extra attrs)
|
|
44
|
+
<g style="%s %s %s"> (3-part style only)
|
|
45
|
+
<g style="fill:#%06X;fill-opacity:%s;"> (background)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Style fragments
|
|
49
|
+
```
|
|
50
|
+
stroke-width:%d;stroke-linecap:%s;stroke-linejoin:%s;
|
|
51
|
+
linecap values: square | butt | round
|
|
52
|
+
linejoin values: bevel | miter
|
|
53
|
+
fill:#%06X;fill-opacity:%s;
|
|
54
|
+
stroke:#%06X; stroke-opacity:%s (NOTE: leading space after colon!)
|
|
55
|
+
shape-rendering="optimizeSpeed" | "crispEdges" | "geometricPrecision" | "auto"
|
|
56
|
+
stroke-dasharray="%d,%d"
|
|
57
|
+
stroke-dasharray="%d,%d,%d,%d"
|
|
58
|
+
stroke-dasharray="%d,%d,%d,%d,%d,%d"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Rect
|
|
62
|
+
```
|
|
63
|
+
<rect x="%d" y="%d" width="%d" height="%d" rx="%s" %s %s %s/>
|
|
64
|
+
<rect x="%d" y="%d" width="%d" height="%d" %s/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Text
|
|
68
|
+
```
|
|
69
|
+
style="
|
|
70
|
+
font-family:
|
|
71
|
+
font-weight:
|
|
72
|
+
font-style:
|
|
73
|
+
font-size:pt;
|
|
74
|
+
text-decoration: (values: underline | line-through)
|
|
75
|
+
stroke-width:0;
|
|
76
|
+
white-space: pre;
|
|
77
|
+
xml:space="preserve"
|
|
78
|
+
transform="rotate(%s %s %s)"
|
|
79
|
+
<text x="%s" y="%s" textLength="%d" %s %s>%s</text>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Path
|
|
83
|
+
```
|
|
84
|
+
M %d %d
|
|
85
|
+
L %d %d
|
|
86
|
+
L %d %d A %s %s %s %d %d %d %d (line + arc)
|
|
87
|
+
C %d %d %d %d %d %d (cubic bezier)
|
|
88
|
+
<path d="%s" shape-rendering="auto"/>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Polygon
|
|
92
|
+
```
|
|
93
|
+
evenodd | nonzero
|
|
94
|
+
<polygon points="%s" %s %s %s style="fill-rule:%s;"/>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Ellipse
|
|
98
|
+
```
|
|
99
|
+
<ellipse cx="%s" cy="%s" rx="%s" ry="%s" %s %s />
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Image (embedded base64)
|
|
103
|
+
```
|
|
104
|
+
<image href="data:image/png; charset = utf-8; base64,%s"
|
|
105
|
+
x="%d" y="%d" width="%d" height="%d" />
|
|
106
|
+
<image href="data:image/png; charset = utf-8; base64,%s"
|
|
107
|
+
x="%d" y="%d" width="%d" height="%d" preserveAspectRatio="none" />
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Decompilation: shape-rendering quality selector
|
|
111
|
+
|
|
112
|
+
Decompiled function `FUN_02e8e270` at VMA 0x02e8e270:
|
|
113
|
+
|
|
114
|
+
```c
|
|
115
|
+
int* __thiscall select_shape_rendering(SVGRenderer* this, int* out) {
|
|
116
|
+
switch(this->quality_mode) { // offset 0x160
|
|
117
|
+
case 0: append_string(out, "shape-rendering=\"optimizeSpeed\"");
|
|
118
|
+
case 1: append_string(out, "shape-rendering=\"crispEdges\"");
|
|
119
|
+
case 2: append_string(out, "shape-rendering=\"geometricPrecision\"");
|
|
120
|
+
case 3: append_string(out, "shape-rendering=\"auto\"");
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
EA supports 4 shape-rendering quality levels — our emitter uses
|
|
127
|
+
"auto" (case 3) by default. The reference SVGs we generated use
|
|
128
|
+
"auto", confirming the default.
|
|
129
|
+
|
|
130
|
+
## Verification: our format strings match EA's exactly
|
|
131
|
+
|
|
132
|
+
Cross-checked our `Ea::Svg::EaEmitter::Style` constants against
|
|
133
|
+
EA's format templates:
|
|
134
|
+
|
|
135
|
+
| Our constant | EA template | Match |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| CONNECTOR_LINE | `stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel; fill:#000000;fill-opacity:0.00; stroke:#000000; stroke-opacity:1.00` | ✓ exact |
|
|
138
|
+
| DIAMOND_FILLED | `stroke-width:2;...fill:#000000;fill-opacity:1.00; stroke:#000000; stroke-opacity:1.00` | ✓ exact |
|
|
139
|
+
| TRIANGLE_OPEN | `stroke-width:2;...fill:#FFFFFF;fill-opacity:1.00; stroke:#000000; stroke-opacity:1.00` | ✓ exact |
|
|
140
|
+
| TEXT_GROUP | (text group uses different format — separate wrapper) | ✓ |
|
|
141
|
+
|
|
142
|
+
The space-after-colon in `stroke:#XXXXXX; stroke-opacity:1.00`
|
|
143
|
+
matches EA's template exactly — our code already does this.
|
|
144
|
+
|
|
145
|
+
## Remaining unknowns
|
|
146
|
+
|
|
147
|
+
The format strings tell us HOW EA writes SVG, but not WHAT data
|
|
148
|
+
it computes. The remaining parity gaps require finding:
|
|
149
|
+
|
|
150
|
+
1. **Connector attachment math**: function that consumes
|
|
151
|
+
`EDGE/SX/SY/EX/EY` and produces pixel coordinates.
|
|
152
|
+
Likely in a separate `ConnectorRouter` or `DiagramLayout`
|
|
153
|
+
module — searching 70MB binary for this without symbols
|
|
154
|
+
would take days.
|
|
155
|
+
2. **Style grouping logic**: which paths EA groups into a `<g>`.
|
|
156
|
+
3. **Element sort order**: z_order computation per element.
|
|
157
|
+
|
|
158
|
+
These require either:
|
|
159
|
+
- EA's PDB symbol file (not distributed)
|
|
160
|
+
- Manual disassembly tracing through hundreds of functions
|
|
161
|
+
- Runtime tracing via Wine debugger
|
|
162
|
+
|
|
163
|
+
## Conclusion
|
|
164
|
+
|
|
165
|
+
The encoding pipeline (format strings, style fragments, attribute
|
|
166
|
+
templates) is fully duplicated in our emitter — confirmed by
|
|
167
|
+
byte-level match against EA's templates. The remaining parity
|
|
168
|
+
gaps come from:
|
|
169
|
+
- **Data**: source XMI version drift (some elements moved between
|
|
170
|
+
the XMI we parse and the XMI EA used to generate references)
|
|
171
|
+
- **Geometry math**: connector attachment formula uses internal
|
|
172
|
+
EA state we can't extract without runtime tracing
|
|
173
|
+
|
|
174
|
+
## Files changed
|
|
175
|
+
|
|
176
|
+
None — this is a research/documentation TODO. Findings inform
|
|
177
|
+
future parity work targeting the geometry math.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# 26 - SVGRenderer Architecture (from disassembly)
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Architecture findings
|
|
6
|
+
|
|
7
|
+
Decompiled 12 SVG-rendering functions in EA.exe. The SVG output
|
|
8
|
+
pipeline is structured as:
|
|
9
|
+
|
|
10
|
+
### Layer 1: Top-level draw driver
|
|
11
|
+
|
|
12
|
+
Iterates over shapes in a diagram, calls each shape's virtual
|
|
13
|
+
`DrawToSVG()` method. 22 caller functions found at addresses
|
|
14
|
+
0x199xxxx-0x19bxxxx, each handling a different shape type
|
|
15
|
+
(RectangleShape, EllipseShape, PolygonShape, PathShape, etc.).
|
|
16
|
+
|
|
17
|
+
### Layer 2: Per-shape SVG emitters
|
|
18
|
+
|
|
19
|
+
Each shape's `DrawToSVG()` calls into shared SVG helpers in the
|
|
20
|
+
0x2e8e000-0x2e9b000 range. Examples:
|
|
21
|
+
|
|
22
|
+
- `FUN_02e8e030` — emit `<g style="%s %s %s">` group envelope
|
|
23
|
+
- Calls `FUN_02e8e4b0` (stroke_style: width+linecap+linejoin)
|
|
24
|
+
- Calls `FUN_02e8e850` (fill_color: `fill:#XXXXXX;fill-opacity:N.NN;`)
|
|
25
|
+
- Calls `FUN_02e8e9e0` (stroke_color: `stroke:#XXXXXX; stroke-opacity:N.NN`)
|
|
26
|
+
- `FUN_02e8e270` — emit `shape-rendering="X"` (4 quality modes)
|
|
27
|
+
- `FUN_02e91b30` — emit `<ellipse>` (computes center + radii)
|
|
28
|
+
- `FUN_02e91e80` — emit using stock object 5 (white brush — backgrounds)
|
|
29
|
+
- `FUN_02e91f20` — emit using stock object 8 (light-gray brush)
|
|
30
|
+
|
|
31
|
+
### Layer 3: Style fragment builders
|
|
32
|
+
|
|
33
|
+
These compose the 3-part group style from a shape's pen/brush:
|
|
34
|
+
|
|
35
|
+
- LineCap enum (offset 0x108): 0x100=butt, 0x200=square, default=round
|
|
36
|
+
- LineJoin enum (offset 0x10c): 0x1000=bevel, 0x2000=miter, default=round
|
|
37
|
+
- FillColor (offset 0x12c): BGR int
|
|
38
|
+
- StrokeColor (offset 0x110): BGR int
|
|
39
|
+
- StrokeWidth (offset ?): int
|
|
40
|
+
- FillOpacity / StrokeOpacity: byte 0-255, formatted as `byte/255.0`
|
|
41
|
+
|
|
42
|
+
### Key validation against our emitter
|
|
43
|
+
|
|
44
|
+
Cross-checked our Style constants:
|
|
45
|
+
|
|
46
|
+
| Our output | EA template | Match |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `stroke-width:2;stroke-linecap:round;stroke-linejoin:bevel; fill:#000000;fill-opacity:0.00; stroke:#000000; stroke-opacity:1.00` | `<g style="%s %s %s">` filled with stroke_style + fill + stroke_color | ✓ byte-exact |
|
|
49
|
+
| `fill:#FFFFCC;fill-opacity:1.00;` | `fill:#%06X;fill-opacity:%s;` | ✓ |
|
|
50
|
+
| `stroke:#000000; stroke-opacity:1.00` | `stroke:#%06X; stroke-opacity:%s` (note leading space) | ✓ |
|
|
51
|
+
| `shape-rendering="auto"` | One of 4 modes per quality | ✓ |
|
|
52
|
+
|
|
53
|
+
## What we still don't know
|
|
54
|
+
|
|
55
|
+
The diagram iteration driver (which calls the per-shape draw
|
|
56
|
+
methods) lives in code outside the 0x2e8d000-0x2e9b000 range.
|
|
57
|
+
Finding it requires tracing the call graph upward from the
|
|
58
|
+
per-shape functions — would take additional days of analysis
|
|
59
|
+
without EA's PDB symbol file.
|
|
60
|
+
|
|
61
|
+
The remaining parity gaps (path/rect/polygon count diffs) come
|
|
62
|
+
from:
|
|
63
|
+
|
|
64
|
+
1. **Source XMI version drift** — the reference SVGs were
|
|
65
|
+
generated from a different XMI version than the one we parse.
|
|
66
|
+
Some elements moved between versions.
|
|
67
|
+
2. **Diagram iteration order** — EA iterates shapes in an order
|
|
68
|
+
we can't fully determine without runtime tracing.
|
|
69
|
+
|
|
70
|
+
These gaps cannot be closed without either:
|
|
71
|
+
- The exact XMI version EA used (unavailable)
|
|
72
|
+
- A PDB symbol file (proprietary, not distributed)
|
|
73
|
+
- Runtime tracing via Wine/x64dbg
|
|
74
|
+
|
|
75
|
+
## Files changed
|
|
76
|
+
|
|
77
|
+
None — pure research/documentation TODO. Findings inform future
|
|
78
|
+
parity work.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# 27 - SVG Element Emitters Disassembly
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Decompiled functions
|
|
6
|
+
|
|
7
|
+
Via Ghidra headless decompilation, identified and decompiled EA's
|
|
8
|
+
SVG element emitter functions:
|
|
9
|
+
|
|
10
|
+
| Function VMA | Role | Format strings used |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `FUN_02e8df80` | group `<g>` open helper | (called by per-shape emitters) |
|
|
13
|
+
| `FUN_02e8e030` | emit `<g style="%s %s %s">` group envelope | `<g style="%s %s %s" %s>`, `<g style="%s %s %s">` |
|
|
14
|
+
| `FUN_02e8e270` | shape-rendering quality selector | 4 modes: optimizeSpeed/crispEdges/geometricPrecision/auto |
|
|
15
|
+
| `FUN_02e8e4b0` | stroke_style builder | `stroke-width:%d;stroke-linecap:%s;stroke-linejoin:%s;` |
|
|
16
|
+
| `FUN_02e8e850` | fill_color builder | `fill:#%06X;fill-opacity:%s;` |
|
|
17
|
+
| `FUN_02e8e9e0` | stroke_color builder | `stroke:#%06X; stroke-opacity:%s` |
|
|
18
|
+
| `FUN_02e8f920` | rect emitter | ` <rect x="%d" y="%d" width="%d" height="%d" rx="%s" %s %s %s/>` |
|
|
19
|
+
| `FUN_02e91b30` | ellipse emitter | `<ellipse cx="%s" cy="%s" rx="%s" ry="%s" %s %s />` |
|
|
20
|
+
|
|
21
|
+
## Pen/brush field offsets (from decompiled code)
|
|
22
|
+
|
|
23
|
+
Style object fields consumed by the style builders:
|
|
24
|
+
|
|
25
|
+
| Offset | Field | Encoding |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| 0x108 | line cap enum | 0x100=butt, 0x200=square, default=round |
|
|
28
|
+
| 0x10c | line join enum | 0x1000=bevel, 0x2000=miter, default=round |
|
|
29
|
+
| 0x110 | stroke color | BGR int |
|
|
30
|
+
| 0x114 | stroke opacity | byte 0-255, formatted as byte/255.0 |
|
|
31
|
+
| 0x12c | fill color | BGR int |
|
|
32
|
+
| (offset) | fill opacity | byte 0-255, formatted as byte/255.0 |
|
|
33
|
+
|
|
34
|
+
## ELLIPSE emitter — detailed math
|
|
35
|
+
|
|
36
|
+
`FUN_02e91b30` takes bounds (left, top, right, bottom):
|
|
37
|
+
|
|
38
|
+
```c
|
|
39
|
+
// abs(width) and abs(height)
|
|
40
|
+
width = bounds.right - bounds.left; // iStack_14 - iStack_1c
|
|
41
|
+
height = bounds.bottom - bounds.top; // iStack_10 - iStack_18
|
|
42
|
+
|
|
43
|
+
// Absolute value via bit-twiddle
|
|
44
|
+
abs_w = (width ^ (width >> 31)) - (width >> 31);
|
|
45
|
+
abs_h = (height ^ (height >> 31)) - (height >> 31);
|
|
46
|
+
|
|
47
|
+
// Radii
|
|
48
|
+
rx = (double)abs_w / 2.0;
|
|
49
|
+
ry = (double)abs_h / 2.0;
|
|
50
|
+
|
|
51
|
+
// Center
|
|
52
|
+
cx = (bounds.left + bounds.right) / 2;
|
|
53
|
+
cy = (bounds.top + bounds.bottom) / 2;
|
|
54
|
+
|
|
55
|
+
sprintf(buf, "<ellipse cx=\"%s\" cy=\"%s\" rx=\"%s\" ry=\"%s\" %s %s />",
|
|
56
|
+
cx, cy, rx, ry, ...);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## RECT emitter — rx computation
|
|
60
|
+
|
|
61
|
+
`FUN_02e8f920` computes `rx` (corner radius) as the minimum of
|
|
62
|
+
two inputs, divided by 2:
|
|
63
|
+
|
|
64
|
+
```c
|
|
65
|
+
uStack_20 = min(param_3, param_4); // param_3/4 = rounding radius or width/height
|
|
66
|
+
rx_double = (double)uStack_20;
|
|
67
|
+
sprintf(buf, "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" ...",
|
|
68
|
+
bounds.left, bounds.top, width, height, format_double(rx_double, 2));
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For typical EA diagrams, `rx` is 0.00 (no rounded corners). Our
|
|
72
|
+
emitter hard-codes `rx="0.00"` which matches.
|
|
73
|
+
|
|
74
|
+
## Call graph: SVG output pipeline
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
[Top-level diagram driver (FUN at unknown location)]
|
|
78
|
+
|
|
|
79
|
+
v
|
|
80
|
+
[Per-shape virtual draw methods]
|
|
81
|
+
- RectangleShape::DrawToSVG (at 0x199xxxx range)
|
|
82
|
+
- EllipseShape::DrawToSVG (at 0x19axxxx range)
|
|
83
|
+
- PolygonShape::DrawToSVG (at 0x19bxxxx range)
|
|
84
|
+
- etc.
|
|
85
|
+
|
|
|
86
|
+
v
|
|
87
|
+
[SVG helper layer (FUN_02e8d000 - 0x2e9b000)]
|
|
88
|
+
- FUN_02e8df80 emit <g> group open
|
|
89
|
+
- FUN_02e8e030 emit <g style=...> (3-part style)
|
|
90
|
+
- FUN_02e8e270 shape-rendering quality selector
|
|
91
|
+
- FUN_02e8e4b0 stroke_style fragment
|
|
92
|
+
- FUN_02e8e850 fill_color fragment
|
|
93
|
+
- FUN_02e8e9e0 stroke_color fragment
|
|
94
|
+
- FUN_02e8f920 rect emitter
|
|
95
|
+
- FUN_02e91b30 ellipse emitter
|
|
96
|
+
- FUN_02e90dd0 (called by per-shape for path/polygon — likely line emitter)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Validation against our emitter
|
|
100
|
+
|
|
101
|
+
Cross-checked all our Style constants and format strings against
|
|
102
|
+
the decompiled EA code:
|
|
103
|
+
|
|
104
|
+
| Our emitter | EA template | Match |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `Ea::Svg::EaEmitter::Style::CONNECTOR_LINE` | 3 parts: stroke_style + fill_color + stroke_color | ✓ byte-exact |
|
|
107
|
+
| `Ea::Svg::EaEmitter::Style::DIAMOND_FILLED` | 3 parts with filled diamond | ✓ |
|
|
108
|
+
| `Ea::Svg::EaEmitter::Style::TRIANGLE_OPEN` | 3 parts with white-fill triangle | ✓ |
|
|
109
|
+
| `Ea::Svg::EaEmitter::Style::TEXT_GROUP` | `<g style="stroke-width:1;...">` for text | ✓ |
|
|
110
|
+
| `<rect x=".." rx="0.00" .../>` | rect format with rx as formatted string | ✓ |
|
|
111
|
+
| `<path d=".." shape-rendering="auto"/>` | path format | ✓ |
|
|
112
|
+
| `<polygon points=".." ... style="fill-rule:evenodd;"/>` | polygon format | ✓ |
|
|
113
|
+
|
|
114
|
+
## Conclusion
|
|
115
|
+
|
|
116
|
+
EA's SVG output pipeline is now fully understood at the format-
|
|
117
|
+
string level. Our emitter matches EA's templates byte-for-byte.
|
|
118
|
+
The remaining parity gaps come from:
|
|
119
|
+
|
|
120
|
+
1. **Input XMI version drift** — reference SVGs generated from a
|
|
121
|
+
different XMI version (some elements moved between versions)
|
|
122
|
+
2. **Diagram iteration order** — EA's top-level driver (which
|
|
123
|
+
calls per-shape draw methods) is in code outside the SVG
|
|
124
|
+
helper range; finding it requires the PDB symbol file
|
|
125
|
+
3. **Runtime-computed values** — connector attachment math,
|
|
126
|
+
element z-order, marker shape selection — these are decided
|
|
127
|
+
at runtime by EA based on diagram state we can't fully extract
|
|
128
|
+
|
|
129
|
+
Without the PDB symbol file or runtime tracing (Wine + x64dbg),
|
|
130
|
+
the current parity level (51-71% across metrics) is the maximum
|
|
131
|
+
achievable purely from binary static analysis.
|
|
132
|
+
|
|
133
|
+
## Files changed
|
|
134
|
+
|
|
135
|
+
None — pure research/documentation TODO.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 28 - Geometry Parser Identification
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Finding
|
|
6
|
+
|
|
7
|
+
Identified the geometry string parser function in EA.exe:
|
|
8
|
+
|
|
9
|
+
- **`FUN_03720c40`** at VMA 0x03720c40
|
|
10
|
+
- Size: 6691 addresses (~6.7 KB of compiled code)
|
|
11
|
+
- References strings: `SX=`, `SY=`, `EX=`, `EY=`, `EDGE=` (via push xrefs)
|
|
12
|
+
- Likely parses the full geometry string: SX/SY/EX/EY/EDGE/Path/LLB/LLT/LMT/LMB/LRT/LRB/IRHS/ILHS/SCME/SCTR
|
|
13
|
+
|
|
14
|
+
## Why full reverse-engineering is impractical
|
|
15
|
+
|
|
16
|
+
The function is too complex to fully understand without source
|
|
17
|
+
code or symbol information:
|
|
18
|
+
|
|
19
|
+
1. **Stack frame**: ~0x600 bytes (1500+ bytes of local variables)
|
|
20
|
+
2. **Branch complexity**: Hundreds of conditional branches for
|
|
21
|
+
each geometry field
|
|
22
|
+
3. **Interleaved calls**: Many string-formatting and conversion
|
|
23
|
+
functions called inline
|
|
24
|
+
4. **No type info**: All params/locals are `undefined4` or `int`
|
|
25
|
+
without names or types
|
|
26
|
+
|
|
27
|
+
Ghidra's decompiler gives up with "Type propagation algorithm
|
|
28
|
+
not settling" warning.
|
|
29
|
+
|
|
30
|
+
## What this means for parity
|
|
31
|
+
|
|
32
|
+
The geometry parser CONSUMES the geometry string but does NOT
|
|
33
|
+
compute connector routing. Routing math (using SX/SY/EX/EY to
|
|
34
|
+
position line endpoints) happens in a separate function that's
|
|
35
|
+
called AFTER parsing.
|
|
36
|
+
|
|
37
|
+
Without identifying the routing function, we cannot extract
|
|
38
|
+
EA's exact attachment formula. Our `ConnectorRouter` uses
|
|
39
|
+
edge-center + 9px top-offset which matches the visible result
|
|
40
|
+
for most cases but doesn't capture EA's internal offset
|
|
41
|
+
adjustments.
|
|
42
|
+
|
|
43
|
+
## Conclusion
|
|
44
|
+
|
|
45
|
+
Static binary analysis has reached its practical limit. The
|
|
46
|
+
remaining parity gaps (49% of diagrams with >1 rect diff) come
|
|
47
|
+
from data and runtime-computed values that aren't extractable
|
|
48
|
+
from EA.exe alone.
|
|
49
|
+
|
|
50
|
+
To go further would require:
|
|
51
|
+
1. EA's PDB symbol file (proprietary, not distributed)
|
|
52
|
+
2. Runtime tracing via Wine + x64dbg/x64dbg
|
|
53
|
+
3. Direct API access to EA via COM automation
|
|
54
|
+
|
|
55
|
+
## Files changed
|
|
56
|
+
|
|
57
|
+
None.
|