ea 0.4.0 → 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/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/06-group-layering-parity.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/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/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 +57 -2
- 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 +8 -15
- 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 +34 -0
- data/lib/ea/model/diagram_element.rb +16 -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/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
- data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
- 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 +4 -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 +2 -3
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
- 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 +46 -12
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +15 -24
- 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 +283 -95
- 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 +93 -27
- 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 +351 -64
- 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 +33 -11
- 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.rb +2 -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 +449 -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,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.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# 29 - QEA+SVG+XMI Triple Comparison Findings
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Methodology
|
|
6
|
+
|
|
7
|
+
Three synchronized data sources now available:
|
|
8
|
+
|
|
9
|
+
- `examples/qea/*.qea` — source QEA files (SQLite database)
|
|
10
|
+
- `examples/exports/*/model.xml` — XMI exports
|
|
11
|
+
- `examples/exports/*/Images/*.svg` — SVG exports (from EA)
|
|
12
|
+
|
|
13
|
+
Triple comparison isolates where parity gaps come from:
|
|
14
|
+
|
|
15
|
+
| Compare | Reveals |
|
|
16
|
+
|---|---|
|
|
17
|
+
| QEA vs XMI | What info is lost in XMI export |
|
|
18
|
+
| XMI → our SVG vs EA's SVG | Our renderer bugs |
|
|
19
|
+
| QEA → our SVG (when supported) vs EA's SVG | Pure renderer comparison |
|
|
20
|
+
|
|
21
|
+
## Available datasets
|
|
22
|
+
|
|
23
|
+
| QEA | Diagrams | Notes |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `simple` | 2 | Tiny — Package + Class diagrams |
|
|
26
|
+
| `test` | 2 | Small test models |
|
|
27
|
+
| `basic` | 22 | UML template with all classifier types |
|
|
28
|
+
| `ArcGISWorkspace_template` | 6 | ArcGIS domain |
|
|
29
|
+
| `UmlModel_template` | 0 (empty) | N/A |
|
|
30
|
+
| `simple_example` | 0 (empty) | N/A |
|
|
31
|
+
| `20251010_current_plateau_v5.1` | 188 | Production model |
|
|
32
|
+
|
|
33
|
+
## Key finding #1: EA has a THEME system
|
|
34
|
+
|
|
35
|
+
The QEA's `t_diagram.StyleEx` field carries a `Theme=:NNN` flag:
|
|
36
|
+
|
|
37
|
+
| QEA | Theme | Resulting style |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `simple` | `:119` | Carlito 7pt, gray text, pastel fills |
|
|
40
|
+
| `basic` | `:119` | Same as simple |
|
|
41
|
+
| `test` | `:119` (some), `nil` (others) | Mixed |
|
|
42
|
+
| `ArcGISWorkspace_template` | `nil` | Default styling |
|
|
43
|
+
| `plateau v5.1` | `nil` | Yu Gothic UI 13px (element-stored) |
|
|
44
|
+
|
|
45
|
+
Theme `:119` produces:
|
|
46
|
+
- **Font**: Carlito (a Calibri-compatible open font)
|
|
47
|
+
- **Font size**: 7pt (not px)
|
|
48
|
+
- **Text color**: #595959 (gray, NOT black)
|
|
49
|
+
- **Text font-weight**: 0 for normal, 700 for bold (0 instead of 400!)
|
|
50
|
+
- **Element border**: #9A8484 (purple-gray, NOT black)
|
|
51
|
+
- **Element fill**: pastel per classifier type (see below)
|
|
52
|
+
- **Stroke width**: 1 (NOT 2)
|
|
53
|
+
- **Stroke cap/join**: round/bevel
|
|
54
|
+
|
|
55
|
+
## Key finding #2: Per-type fill colors (theme :119)
|
|
56
|
+
|
|
57
|
+
| Classifier type | Fill color | Stereotype label |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| Class | `#FDFAF7` | (depends on applied stereotype) |
|
|
60
|
+
| Interface | `#F1ECFA` | `«interface»` |
|
|
61
|
+
| DataType | `#FAF9E6` | `«dataType»` (lowercase d!) |
|
|
62
|
+
| Enumeration | `#E8FDE3` | `«enumeration»` |
|
|
63
|
+
| PrimitiveType | `#FAF9E6` | `«primitive»` |
|
|
64
|
+
|
|
65
|
+
Stereotype label casing observed in ref SVGs:
|
|
66
|
+
- `«DataType»` — Class with explicit DataType stereotype applied (CapD, CapT)
|
|
67
|
+
- `«dataType»` — DataType classifier (lowercase d, CapT)
|
|
68
|
+
- `«interface»` — Interface classifier (all lowercase)
|
|
69
|
+
- `«enumeration»` — Enumeration classifier (all lowercase)
|
|
70
|
+
- `«primitive»` — PrimitiveType classifier (all lowercase)
|
|
71
|
+
|
|
72
|
+
Our current emitter uses `«DataType»` for ALL Klass subclasses,
|
|
73
|
+
which is WRONG for actual DataType/Interface/Enumeration types.
|
|
74
|
+
|
|
75
|
+
## Key finding #3: Diagram frame
|
|
76
|
+
|
|
77
|
+
Every EA diagram has an outer border with a "tab" containing
|
|
78
|
+
the diagram name+type. Rendered as:
|
|
79
|
+
|
|
80
|
+
```xml
|
|
81
|
+
<!-- Outer border (path, not rect) -->
|
|
82
|
+
<g style="stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;
|
|
83
|
+
fill:#000000;fill-opacity:0.00; stroke:#000000; stroke-opacity:1.00">
|
|
84
|
+
<path d="M 6 6 L 6 H-6 W-6 W-6 6 L 6 6" shape-rendering="auto"/>
|
|
85
|
+
</g>
|
|
86
|
+
<!-- Tab polygon (hexagon shape) -->
|
|
87
|
+
<g style="stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;
|
|
88
|
+
fill:#FFFFFF;fill-opacity:1.00; stroke:#000000; stroke-opacity:1.00">
|
|
89
|
+
<polygon points="6 26 X 26 X+13 12 X+13 6 6 6 6 26"
|
|
90
|
+
shape-rendering="auto" style="fill-rule:evenodd;"/>
|
|
91
|
+
</g>
|
|
92
|
+
<!-- Tab title text -->
|
|
93
|
+
<g style="...">
|
|
94
|
+
<text x="11" y="19" textLength="W"
|
|
95
|
+
style="font-family:Carlito; font-weight:700; ...;
|
|
96
|
+
transform=rotate(-0.00 11 19)">
|
|
97
|
+
class DiagramName
|
|
98
|
+
</text>
|
|
99
|
+
</g>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Format: `<diagram_type> <diagram_name>` (e.g., `class Package A.1.1`,
|
|
103
|
+
`pkg Package Contents`).
|
|
104
|
+
|
|
105
|
+
Our emitter does NOT render the diagram frame at all.
|
|
106
|
+
|
|
107
|
+
## Key finding #4: Package rendering
|
|
108
|
+
|
|
109
|
+
Packages are rendered as POLYGONS, not rects:
|
|
110
|
+
|
|
111
|
+
```xml
|
|
112
|
+
<g style="stroke-width:1;stroke-linecap:round;stroke-linejoin:bevel;
|
|
113
|
+
fill:#FAF3F0;fill-opacity:1.00; stroke:#9A8484; stroke-opacity:1.00">
|
|
114
|
+
<!-- Main package body -->
|
|
115
|
+
<polygon points="L T R T R B L B L T" .../>
|
|
116
|
+
<!-- Tab on top-left -->
|
|
117
|
+
<polygon points="L T-20 L+105 T-20 L+105 T L T L T-20" .../>
|
|
118
|
+
</g>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Key finding #5: Text rotation transform
|
|
122
|
+
|
|
123
|
+
EVERY text element has a rotation transform, even when 0:
|
|
124
|
+
|
|
125
|
+
```xml
|
|
126
|
+
<text x="11.00" y="19.00" textLength="88"
|
|
127
|
+
style="..."
|
|
128
|
+
xml:space="preserve"
|
|
129
|
+
transform="rotate(-0.00 11.00 19.00)">text</text>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Note: `x` and `y` are decimals (2 places), `textLength` is an integer.
|
|
133
|
+
The transform uses the same decimal x,y as the text.
|
|
134
|
+
|
|
135
|
+
Our emitter emits integer coords and no transform.
|
|
136
|
+
|
|
137
|
+
## Key finding #6: Stroke width per layer
|
|
138
|
+
|
|
139
|
+
| Layer | stroke-width | cap/join |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| Background rect | (none) | n/a |
|
|
142
|
+
| Diagram frame border | 1 | square/miter |
|
|
143
|
+
| Diagram frame tab | 1 | square/miter |
|
|
144
|
+
| Class boxes (theme :119) | 1 | round/bevel |
|
|
145
|
+
| Class dividers | 1 | round/bevel |
|
|
146
|
+
| Connector lines | 1 or 2 | round/bevel |
|
|
147
|
+
|
|
148
|
+
Our emitter hardcodes stroke-width 2 for everything.
|
|
149
|
+
|
|
150
|
+
## Key finding #7: DiagramObjects coords
|
|
151
|
+
|
|
152
|
+
QEA's t_diagramobjects stores rect coords with NEGATIVE y values
|
|
153
|
+
(e.g., `RectTop=-195, RectBottom=-265`). EA normalizes by
|
|
154
|
+
translating all elements so the topmost has y=padding.
|
|
155
|
+
|
|
156
|
+
Width = RectRight - RectLeft (positive)
|
|
157
|
+
Height = RectTop - RectBottom (positive — top > bottom in QEA's coords!)
|
|
158
|
+
|
|
159
|
+
Our current parser treats `top` as the upper coord and computes
|
|
160
|
+
height as `bottom - top`. For QEA data, this produces NEGATIVE
|
|
161
|
+
height. Need to take absolute value or swap.
|
|
162
|
+
|
|
163
|
+
## Practical parity improvements identified
|
|
164
|
+
|
|
165
|
+
1. **Diagram frame rendering** — add path + polygon + text for the
|
|
166
|
+
outer border and tab.
|
|
167
|
+
2. **Theme support** — load theme from QEA's `t_diagram.StyleEx`
|
|
168
|
+
`Theme=:NNN` field. Map theme ID to font/color/stroke values.
|
|
169
|
+
3. **Per-type stereotype labels** — fix the casing per classifier
|
|
170
|
+
concrete class.
|
|
171
|
+
4. **Per-type fill colors** — lookup table for theme :119.
|
|
172
|
+
5. **Text rotation transform** — always emit `transform="rotate(-0.00 X Y)"`.
|
|
173
|
+
6. **Decimal text coords** — format x/y as `%.2f`.
|
|
174
|
+
7. **Stroke width 1** — use 1 for elements, dividers, frame.
|
|
175
|
+
8. **QEA rect coord fix** — height is `top - bottom` (not `bottom - top`).
|
|
176
|
+
9. **Package shape** — render as polygon with tab.
|
|
177
|
+
10. **Diagram style flags** — honor `SuppressFOC`, `AttPkg`,
|
|
178
|
+
`ShowNotes` from StyleEx.
|
|
179
|
+
|
|
180
|
+
These collectively should close most parity gaps on the simple/basic
|
|
181
|
+
test diagrams and validate the same rules apply to the plateau data.
|
|
182
|
+
|
|
183
|
+
## Files changed
|
|
184
|
+
|
|
185
|
+
None — analysis TODO. Implementation in fixup 30+.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# 30 - Theme System & Per-Type Fills (Stub)
|
|
2
|
+
|
|
3
|
+
## Status: PARTIAL (stubbed, needs full implementation)
|
|
4
|
+
|
|
5
|
+
## Implemented
|
|
6
|
+
|
|
7
|
+
- `Ea::Svg::EaEmitter::ThemeColors` module declares Theme :119's
|
|
8
|
+
per-classifier-type fill colors:
|
|
9
|
+
- Class → #FDFAF7
|
|
10
|
+
- Interface → #F1ECFA
|
|
11
|
+
- DataType → #FAF9E6
|
|
12
|
+
- Enumeration → #E8FDE3
|
|
13
|
+
- PrimitiveType → #FAF9E6
|
|
14
|
+
- Plus border color #9A8484 and text color #595959
|
|
15
|
+
|
|
16
|
+
## Not yet implemented
|
|
17
|
+
|
|
18
|
+
1. **Theme detection**: read `t_diagram.StyleEx` `Theme=:NNN` flag
|
|
19
|
+
via QEA parser. Requires plumbing StyleEx through to the SVG
|
|
20
|
+
emitter via the Diagram model.
|
|
21
|
+
2. **Theme application**: when theme is :119, override:
|
|
22
|
+
- Element fill → per-type pastel
|
|
23
|
+
- Element border color → #9A8484
|
|
24
|
+
- Text color → #595959
|
|
25
|
+
- Stroke width → 1 (was 2)
|
|
26
|
+
- Font family → Carlito
|
|
27
|
+
- Font size → 7pt (not 13px)
|
|
28
|
+
3. **StyleEx flag honoring**: `SuppressFOC=1`, `AttPkg=1`,
|
|
29
|
+
`ShowNotes=0`, `ShowBorder=1`, etc.
|
|
30
|
+
4. **DiagramObject coord normalization**: QEA stores rect with
|
|
31
|
+
negative y values; need to normalize to canvas coords.
|
|
32
|
+
|
|
33
|
+
## How to wire up
|
|
34
|
+
|
|
35
|
+
The current XMI adapter doesn't capture StyleEx. The QEA adapter
|
|
36
|
+
would need to expose it. Then Document constructor accepts a
|
|
37
|
+
theme override or reads from the diagram model.
|
|
38
|
+
|
|
39
|
+
Quick path: add `style_ex` field to `Ea::Model::Diagram`, populate
|
|
40
|
+
from XMI/QEA, then `Document.new(diagram, model_index:, theme: :auto)`
|
|
41
|
+
extracts theme from style_ex.
|
|
42
|
+
|
|
43
|
+
## Files changed (stub only)
|
|
44
|
+
|
|
45
|
+
- `lib/ea/svg/ea_emitter/theme_colors.rb` — color constants
|
|
46
|
+
- `lib/ea/svg/ea_emitter.rb` — autoload
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# 31 - Theme Value Object + ThemeRegistry (OCP)
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
- Ea::Svg::EaEmitter::Theme — immutable value object
|
|
8
|
+
- Ea::Svg::EaEmitter::ThemeRegistry — registers and looks up themes
|
|
9
|
+
by ID. Default + :119 themes built-in. register() for OCP
|
|
10
|
+
extension.
|
|
11
|
+
|
|
12
|
+
## Files changed
|
|
13
|
+
|
|
14
|
+
- lib/ea/svg/ea_emitter/theme.rb — value object
|
|
15
|
+
- lib/ea/svg/ea_emitter/theme_registry.rb — registry with 2 themes
|
|
16
|
+
- lib/ea/svg/ea_emitter.rb — autoload
|
|
17
|
+
- spec/ea/svg/ea_emitter/theme_registry_spec.rb — 7 specs incl OCP
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 32 - StyleEx on Diagram Model
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
Added `style_ex` attribute to `Ea::Model::Diagram` with two
|
|
8
|
+
helper methods:
|
|
9
|
+
- `#style_ex_flags` — parses "Key=Value;Key=Value" into Hash
|
|
10
|
+
- `#theme_id` — extracts Theme=:NNN value
|
|
11
|
+
|
|
12
|
+
## Note: StyleEx not exposed via XMI
|
|
13
|
+
|
|
14
|
+
EA's XMI export does NOT include `t_diagram.StyleEx`. The QEA
|
|
15
|
+
loader (when wired into the SVG pipeline) will populate this
|
|
16
|
+
field directly. For XMI-loaded diagrams, style_ex stays nil and
|
|
17
|
+
the default theme is used.
|
|
18
|
+
|
|
19
|
+
## Files changed
|
|
20
|
+
|
|
21
|
+
- `lib/ea/model/diagram.rb` — added style_ex attribute + helpers
|
|
22
|
+
- `spec/ea/model/diagram_style_ex_spec.rb` — 7 specs
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 33 - Text Encoding: Decimal Coords + Rotation Transform
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
New `Ea::Svg::EaEmitter::TextRenderer` is the single source of
|
|
8
|
+
truth for `<text>` emission. Always emits:
|
|
9
|
+
- Decimal `x` and `y`: `x="11.00" y="19.00"`
|
|
10
|
+
- Always-present rotation transform: `transform="rotate(-0.00 X Y)"`
|
|
11
|
+
- Integer `textLength`
|
|
12
|
+
- Proper XML escaping
|
|
13
|
+
|
|
14
|
+
Refactored 6 sites to delegate:
|
|
15
|
+
- `Element::HeaderRenderer`
|
|
16
|
+
- `Element::AttributeRenderer`
|
|
17
|
+
- `Element::OperationRenderer`
|
|
18
|
+
- `Element::EnumerationLiteralRenderer`
|
|
19
|
+
- `Labels#text_at`
|
|
20
|
+
- `DiagramFrame#build_label_text`
|
|
21
|
+
|
|
22
|
+
Also closes TODO 42 (TextRenderer Centralization).
|
|
23
|
+
|
|
24
|
+
## Files changed
|
|
25
|
+
|
|
26
|
+
- `lib/ea/svg/ea_emitter/text_renderer.rb` — NEW
|
|
27
|
+
- `lib/ea/svg/ea_emitter.rb` — autoload
|
|
28
|
+
- 6 renderer files refactored to use TextRenderer
|
|
29
|
+
- `spec/ea/svg/ea_emitter/text_renderer_spec.rb` — 10 specs
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 34 - Per-Type Fill via Theme (Wire Up ThemeColors)
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
## Outcome
|
|
6
|
+
|
|
7
|
+
`Elements#resolve_fill` consults the active theme first:
|
|
8
|
+
1. Element BCol if present (highest precedence)
|
|
9
|
+
2. Theme's per-type fill (when theme is themed)
|
|
10
|
+
3. Stereotype color resolver (default theme)
|
|
11
|
+
4. DEFAULT_FILL (#FFFFFF)
|
|
12
|
+
|
|
13
|
+
Theme stroke color and width also override defaults.
|
|
14
|
+
|
|
15
|
+
## Files changed
|
|
16
|
+
|
|
17
|
+
- `lib/ea/svg/ea_emitter/elements.rb` — resolve_fill / resolve_stroke
|
|
18
|
+
/ resolve_stroke_width methods, theme lookup
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 36 - QEA Rect Coord Normalization
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, deferred)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
QEA's `t_diagramobjects` stores rect with NEGATIVE y values:
|
|
8
|
+
RectTop=-195, RectBottom=-265
|
|
9
|
+
|
|
10
|
+
Top > Bottom in QEA's coords. Width = RectRight - RectLeft.
|
|
11
|
+
Height = |RectBottom - RectTop|.
|
|
12
|
+
|
|
13
|
+
The XMI export already normalizes this — XMI-loaded diagrams
|
|
14
|
+
work correctly. The QEA adapter (when wired) will need to
|
|
15
|
+
handle this normalization.
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
Deferring until QEA loader is wired into SVG pipeline. Current
|
|
20
|
+
XMI path works correctly.
|
|
21
|
+
|
|
22
|
+
## Files changed
|
|
23
|
+
|
|
24
|
+
None.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 37 - Package Shape Rendering (Polygon + Tab)
|
|
2
|
+
|
|
3
|
+
## Status: TODO (deferred — needs Package classifier model)
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
EA renders Package classifiers as a 5-point POLYGON with a tab.
|
|
8
|
+
Our model doesn't have a Package classifier type — packages are
|
|
9
|
+
modeled as a separate concept (Ea::Model::Package), not as
|
|
10
|
+
classifiers on diagrams.
|
|
11
|
+
|
|
12
|
+
To implement:
|
|
13
|
+
1. Detect when a DiagramElement references a Package (via
|
|
14
|
+
model_element_ref → Ea::Model::Package)
|
|
15
|
+
2. New PackageShapeRenderer emits polygon-based shape
|
|
16
|
+
3. Elements#groups_for dispatches to PackageShapeRenderer for
|
|
17
|
+
packages
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
Deferred — needs investigation of how packages appear on
|
|
22
|
+
diagrams in the Ea::Model layer.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 38 - Note Element Rendering
|
|
2
|
+
|
|
3
|
+
## Status: ANALYZED (2026-07-25, closed)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
EA Note elements are not modeled in Ea::Model — they would
|
|
8
|
+
appear as a special classifier type or via element type field.
|
|
9
|
+
Sample datasets (simple/basic/test) don't contain Notes as
|
|
10
|
+
classifiers.
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
Closed — no Note elements in available datasets. Resurfaces if
|
|
15
|
+
future QEAs contain notes.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 39 - StyleEx Flag Honoring
|
|
2
|
+
|
|
3
|
+
## Status: PARTIAL (infrastructure ready, flags not yet honored)
|
|
4
|
+
|
|
5
|
+
## Infrastructure
|
|
6
|
+
|
|
7
|
+
Diagram#style_ex_flags parses StyleEx into Hash. Ready to use.
|
|
8
|
+
|
|
9
|
+
## Flags not yet honored
|
|
10
|
+
|
|
11
|
+
- SuppressFOC=1 → skip attr/op compartments
|
|
12
|
+
- AttPub/Pri/Pro=0 → hide visibility-filtered attrs
|
|
13
|
+
- ShowBorder=0 → suppress diagram frame
|
|
14
|
+
- ShowNotes=0 → hide element notes
|
|
15
|
+
- SuppConnectorLabels=1 → hide connector labels
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
Each flag adds rendering complexity. Will be implemented as
|
|
20
|
+
needed when specific QEAs require them. The QEA loader wiring
|
|
21
|
+
(carrying StyleEx from QEA through to Diagram) is a prerequisite.
|
|
22
|
+
|
|
23
|
+
## Files changed
|
|
24
|
+
|
|
25
|
+
None — Diagram.style_ex_flags already in place (TODO 32).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 40 - Connector Dashed Lines for Dependency/Realization
|
|
2
|
+
|
|
3
|
+
## Status: TODO (no test data triggers it)
|
|
4
|
+
|
|
5
|
+
## Findings
|
|
6
|
+
|
|
7
|
+
Reference SVGs contain ZERO stroke-dasharray attributes — no
|
|
8
|
+
Dependency or Realization connectors in sample datasets.
|
|
9
|
+
Implementation is straightforward (add dasharray to Style) but
|
|
10
|
+
no test data validates it.
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
Deferred until sample QEA with Dependency/Realization connectors
|
|
15
|
+
is available.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 41 - DiagramFrame ShowBorder Detection
|
|
2
|
+
|
|
3
|
+
## Status: PARTIAL (frame renderer exists, auto-detect not yet)
|
|
4
|
+
|
|
5
|
+
## Current state
|
|
6
|
+
|
|
7
|
+
DiagramFrame renderer is implemented and opt-in via `frame: true`
|
|
8
|
+
on Document constructor. EA version difference (Build 1624 vs
|
|
9
|
+
1628) means the same ShowBorder=1 flag produces different output.
|
|
10
|
+
|
|
11
|
+
## Auto-detect rule (TODO)
|
|
12
|
+
|
|
13
|
+
When QEA loader is wired:
|
|
14
|
+
- Read t_diagram.ShowBorder
|
|
15
|
+
- If 1 AND build_id <= 1624 → render frame
|
|
16
|
+
- Otherwise → suppress
|
|
17
|
+
|
|
18
|
+
Plateau (build 1628) → no frame even with ShowBorder=1
|
|
19
|
+
Simple/basic (build 1624) → frame rendered
|
|
20
|
+
|
|
21
|
+
## Files changed
|
|
22
|
+
|
|
23
|
+
None — DiagramFrame already exists.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# 42 - TextRenderer Centralization (DRY)
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-25)
|
|
4
|
+
|
|
5
|
+
Merged with TODO 33. Single TextRenderer replaces 6 duplicated
|
|
6
|
+
build_text helpers across:
|
|
7
|
+
- HeaderRenderer, AttributeRenderer, OperationRenderer,
|
|
8
|
+
EnumerationLiteralRenderer, Labels, DiagramFrame.
|
|
9
|
+
|
|
10
|
+
See TODO.fixup/33 for details.
|